From 539523ff447674113c816857653c42dbaaae0c03 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:59:57 -0300 Subject: [PATCH 01/24] Add HTTP API server infrastructure to node daemon - Add APIPort (default 8280) and OpenAPIPort config params to SmartnodeConfig - Add RestrictedPortModes() (Closed/Localhost only) to port-modes.go - Add GetNodeOpenPorts() to RocketPoolConfig for docker-compose port mapping - Update node.tmpl to expose the API port on 127.0.0.1 (Docker mode) - Create rocketpool/node/http.go: startHTTP() binds 0.0.0.0 in Docker mode, respects OpenAPIPort in native mode, shuts down gracefully on SIGTERM - Create rocketpool/node/routes/routes.go: route registration skeleton - Wire startHTTP() into node daemon startup (node.go) - Add callHTTPAPI() and getAPIURL() to the CLI Client struct; apiURL is lazily derived from config and cached for subsequent calls Co-authored-by: Cursor --- rocketpool/node/http.go | 64 ++++++++++++++ rocketpool/node/node.go | 11 +++ rocketpool/node/routes/routes.go | 15 ++++ shared/services/config/rocket-pool-config.go | 13 +++ shared/services/config/smartnode-config.go | 31 +++++++ .../assets/install/templates/node.tmpl | 1 + shared/services/rocketpool/client.go | 88 +++++++++++++++++++ shared/types/config/port-modes.go | 14 +++ 8 files changed, 237 insertions(+) create mode 100644 rocketpool/node/http.go create mode 100644 rocketpool/node/routes/routes.go diff --git a/rocketpool/node/http.go b/rocketpool/node/http.go new file mode 100644 index 000000000..ca4a09e07 --- /dev/null +++ b/rocketpool/node/http.go @@ -0,0 +1,64 @@ +package node + +import ( + "context" + "fmt" + "log" + "net/http" + + "github.com/urfave/cli" + + "github.com/rocket-pool/smartnode/rocketpool/node/routes" + "github.com/rocket-pool/smartnode/shared/services/config" + cfgtypes "github.com/rocket-pool/smartnode/shared/types/config" +) + +type httpServer struct { + server *http.Server + mux *http.ServeMux +} + +// startHTTP starts the node's HTTP API server and returns immediately. +// The server runs in the background for the lifetime of the process. +func startHTTP(ctx context.Context, c *cli.Context, cfg *config.RocketPoolConfig) { + port, ok := cfg.Smartnode.APIPort.Value.(uint16) + if !ok || port == 0 { + log.Println("Warning: APIPort not configured, HTTP API server will not start.") + return + } + + // In Docker mode the server must bind to 0.0.0.0 so the port mapping in + // node.tmpl makes it accessible from the host. In native mode we respect + // the OpenAPIPort setting: Closed → 127.0.0.1, OpenLocalhost → 0.0.0.0. + var host string + if !cfg.IsNativeMode { + host = "0.0.0.0" + } else { + portMode, _ := cfg.Smartnode.OpenAPIPort.Value.(cfgtypes.RPCMode) + if portMode == cfgtypes.RPC_OpenLocalhost { + host = "0.0.0.0" + } else { + host = "127.0.0.1" + } + } + + mux := http.NewServeMux() + routes.RegisterRoutes(mux, c) + + srv := &http.Server{ + Addr: fmt.Sprintf("%s:%d", host, port), + Handler: mux, + } + + go func() { + log.Printf("Node HTTP API server listening on %s:%d\n", host, port) + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Printf("Node HTTP API server error: %v\n", err) + } + }() + + go func() { + <-ctx.Done() + _ = srv.Shutdown(context.Background()) + }() +} diff --git a/rocketpool/node/node.go b/rocketpool/node/node.go index ccf6c362f..c0929cb23 100644 --- a/rocketpool/node/node.go +++ b/rocketpool/node/node.go @@ -7,8 +7,10 @@ import ( "math/big" "net/http" "os" + "os/signal" "path/filepath" "sync" + "syscall" "time" "github.com/ethereum/go-ethereum/common" @@ -131,6 +133,15 @@ func run(c *cli.Command) error { errorLog := log.NewColorLogger(ErrorColor) updateLog := log.NewColorLogger(UpdateColor) + // Create a context that is cancelled on SIGINT/SIGTERM so the HTTP server + // and other background goroutines can shut down gracefully. + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer cancel() + + // Start the HTTP API server. It runs in the background for the lifetime + // of the daemon and serves all migrated API endpoints. + startHTTP(ctx, c, cfg) + // Create the state manager m := state.NewNetworkStateManager(rp, cfg.Smartnode.GetStateManagerContracts(), bc, &updateLog) stateLocker := collectors.NewStateLocker() diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go new file mode 100644 index 000000000..99c1da10c --- /dev/null +++ b/rocketpool/node/routes/routes.go @@ -0,0 +1,15 @@ +package routes + +import ( + "net/http" + + "github.com/urfave/cli" +) + +// RegisterRoutes registers all HTTP API routes onto mux. +// Module-specific routes are registered by successive migration branches. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + }) +} diff --git a/shared/services/config/rocket-pool-config.go b/shared/services/config/rocket-pool-config.go index cc9df1387..cd6ef5a28 100644 --- a/shared/services/config/rocket-pool-config.go +++ b/shared/services/config/rocket-pool-config.go @@ -1254,6 +1254,19 @@ func (cfg *RocketPoolConfig) GetECStopSignal() (string, error) { return "", fmt.Errorf("Unknown Execution Client %s", string(cfg.ExecutionClient.Value.(config.ExecutionClient))) } +// Gets the port mapping string for the node API webserver. +// In Docker mode this always returns "127.0.0.1:PORT:PORT/tcp" so the CLI on +// the host can reach the server. In native mode Docker is not involved so an +// empty string is returned. +// Used by text/template to format node.tmpl. +func (cfg *RocketPoolConfig) GetNodeOpenPorts() string { + if cfg.IsNativeMode { + return "" + } + port := cfg.Smartnode.APIPort.Value.(uint16) + return fmt.Sprintf("\"127.0.0.1:%d:%d/tcp\"", port, port) +} + // Gets the stop signal of the ec container // Used by text/template to format eth1.yml func (cfg *RocketPoolConfig) GetECOpenAPIPorts() string { diff --git a/shared/services/config/smartnode-config.go b/shared/services/config/smartnode-config.go index 7c2803df1..bda308ece 100644 --- a/shared/services/config/smartnode-config.go +++ b/shared/services/config/smartnode-config.go @@ -114,6 +114,12 @@ type SmartnodeConfig struct { // Delay for automatic queue assignment AutoAssignmentDelay config.Parameter `yaml:"autoAssignmentDelay,omitempty"` + // Port for the node's HTTP API webserver + APIPort config.Parameter `yaml:"apiPort,omitempty"` + + // Whether to expose the node's API port to the local network + OpenAPIPort config.Parameter `yaml:"openAPIPort,omitempty"` + /////////////////////////// // Non-editable settings // /////////////////////////// @@ -413,6 +419,29 @@ func NewSmartnodeConfig(cfg *RocketPoolConfig) *SmartnodeConfig { OverwriteOnUpgrade: true, }, + APIPort: config.Parameter{ + ID: "apiPort", + Name: "API Port", + Description: "The port your Smartnode's HTTP API server should listen on.", + Type: config.ParameterType_Uint16, + Default: map[config.Network]interface{}{config.Network_All: uint16(8280)}, + AffectsContainers: []config.ContainerID{config.ContainerID_Node}, + CanBeBlank: false, + OverwriteOnUpgrade: false, + }, + + OpenAPIPort: config.Parameter{ + ID: "openAPIPort", + Name: "Expose API Port", + Description: "Expose the API port to other processes on your machine. For security reasons, this port can only be exposed to localhost. It is recommended to keep this setting on Closed unless you have a specific reason to expose it.", + Type: config.ParameterType_Choice, + Default: map[config.Network]interface{}{config.Network_All: config.RPC_Closed}, + AffectsContainers: []config.ContainerID{config.ContainerID_Node}, + CanBeBlank: false, + OverwriteOnUpgrade: false, + Options: config.RestrictedPortModes(), + }, + txWatchUrl: map[config.Network]string{ config.Network_Mainnet: "https://etherscan.io/tx", config.Network_Devnet: "https://hoodi.etherscan.io/tx", @@ -642,6 +671,8 @@ func (cfg *SmartnodeConfig) GetParameters() []*config.Parameter { &cfg.ArchiveECUrl, &cfg.WatchtowerMaxFeeOverride, &cfg.WatchtowerPrioFeeOverride, + &cfg.APIPort, + &cfg.OpenAPIPort, } } diff --git a/shared/services/rocketpool/assets/install/templates/node.tmpl b/shared/services/rocketpool/assets/install/templates/node.tmpl index 3f564e086..6d6fb5992 100644 --- a/shared/services/rocketpool/assets/install/templates/node.tmpl +++ b/shared/services/rocketpool/assets/install/templates/node.tmpl @@ -11,6 +11,7 @@ services: container_name: {{.Smartnode.ProjectName}}_node restart: unless-stopped tty: true + ports: [{{.GetNodeOpenPorts}}] volumes: - /var/run/docker.sock:/var/run/docker.sock - {{.RocketPoolDirectory}}:/.rocketpool diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index b99bd878b..17ecb084c 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -2,17 +2,21 @@ package rocketpool import ( "bufio" + "bytes" "errors" "fmt" "io" "io/fs" "math" "math/big" + "net/http" + "net/url" "os" "os/exec" "path/filepath" "slices" "strings" + "sync" "time" "github.com/fatih/color" @@ -85,6 +89,11 @@ type Client struct { originalGasLimit uint64 ignoreSyncCheck bool forceFallbacks bool + + // apiURL is the base URL for the node's HTTP API server. + // It is derived lazily from config on first use. + apiURL string + apiURLOnce sync.Once } func getClientStatusString(clientStatus api.ClientStatus) string { @@ -1264,6 +1273,85 @@ func (c *Client) composeAddons(cfg *config.RocketPoolConfig, rocketpoolDir strin } +// getAPIURL returns the base URL for the node's HTTP API server, e.g. +// "http://127.0.0.1:8280". The result is derived from config and cached. +func (c *Client) getAPIURL() string { + c.apiURLOnce.Do(func() { + cfg, _, err := c.LoadConfig() + if err != nil { + return + } + port, ok := cfg.Smartnode.APIPort.Value.(uint16) + if !ok || port == 0 { + return + } + c.apiURL = fmt.Sprintf("http://127.0.0.1:%d", port) + }) + return c.apiURL +} + +// callHTTPAPI calls the node's HTTP API server. +// method is "GET" or "POST". +// path is the URL path, e.g. "/api/node/status". +// params are appended as query string parameters for GET or as a JSON body +// for POST. +// The response body is returned as-is; callers unmarshal it the same way +// they currently unmarshal the output of callAPI. +func (c *Client) callHTTPAPI(method, path string, params url.Values) ([]byte, error) { + base := c.getAPIURL() + if base == "" { + return nil, fmt.Errorf("node HTTP API URL is not configured (APIPort may be 0)") + } + + target := base + path + + var req *http.Request + var err error + switch method { + case http.MethodGet: + if len(params) > 0 { + target += "?" + params.Encode() + } + req, err = http.NewRequest(http.MethodGet, target, nil) + case http.MethodPost: + body := []byte(params.Encode()) + req, err = http.NewRequest(http.MethodPost, target, bytes.NewReader(body)) + if err == nil { + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + } + default: + return nil, fmt.Errorf("unsupported HTTP method: %s", method) + } + if err != nil { + return nil, fmt.Errorf("error building HTTP request for %s %s: %w", method, path, err) + } + + if c.debugPrint { + fmt.Printf("HTTP API: %s %s\n", method, target) + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("error calling HTTP API %s %s: %w", method, path, err) + } + defer resp.Body.Close() + + responseBytes, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("error reading HTTP API response for %s %s: %w", method, path, err) + } + + if c.debugPrint { + fmt.Printf("HTTP API response (%d): %s\n", resp.StatusCode, string(responseBytes)) + } + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("HTTP API %s %s returned status %d: %s", method, path, resp.StatusCode, string(responseBytes)) + } + + return responseBytes, nil +} + // Call the Rocket Pool API func (c *Client) callAPI(args string, otherArgs ...string) ([]byte, error) { // Sanitize and parse the args diff --git a/shared/types/config/port-modes.go b/shared/types/config/port-modes.go index 936474fde..603d81da3 100644 --- a/shared/types/config/port-modes.go +++ b/shared/types/config/port-modes.go @@ -55,3 +55,17 @@ func PortModes(warningOverride string) []ParameterOption { Value: RPC_OpenExternal, }} } + +// RestrictedPortModes returns port mode options limited to Closed or Localhost only. +// Used for ports that must never be exposed externally (e.g. the node API). +func RestrictedPortModes() []ParameterOption { + return []ParameterOption{{ + Name: "Closed", + Description: "Do not allow connections to the port", + Value: RPC_Closed, + }, { + Name: "Open to Localhost", + Description: "Allow connections from this host only", + Value: RPC_OpenLocalhost, + }} +} From c474e06da3607e556215f2f6d2372da8d6772e39 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:02:45 -0300 Subject: [PATCH 02/24] Migrate queue and service modules to HTTP API Server side: - rocketpool/api/queue/routes.go: RegisterRoutes() for all 6 queue endpoints - rocketpool/api/service/routes.go: RegisterRoutes() for all 3 service endpoints - rocketpool/node/routes/routes.go: wire queue and service route registrations - shared/utils/api/http.go: WriteResponse/WriteErrorResponse helpers Client side: - shared/services/rocketpool/queue.go: replace callAPI with callHTTPAPI - shared/services/rocketpool/service.go: replace callAPI with callHTTPAPI debug module skipped (handlers write to stdout directly, not JSON API pattern) Co-authored-by: Cursor --- rocketpool/api/queue/routes.go | 75 +++++++++++++++++++++++++++ rocketpool/api/service/routes.go | 27 ++++++++++ rocketpool/node/routes/routes.go | 8 ++- shared/services/rocketpool/queue.go | 13 ++--- shared/services/rocketpool/service.go | 6 +-- shared/utils/api/http.go | 61 ++++++++++++++++++++++ 6 files changed, 180 insertions(+), 10 deletions(-) create mode 100644 rocketpool/api/queue/routes.go create mode 100644 rocketpool/api/service/routes.go create mode 100644 shared/utils/api/http.go diff --git a/rocketpool/api/queue/routes.go b/rocketpool/api/queue/routes.go new file mode 100644 index 000000000..bb15ddcce --- /dev/null +++ b/rocketpool/api/queue/routes.go @@ -0,0 +1,75 @@ +package queue + +import ( + "net/http" + "strconv" + + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the queue module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/queue/status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/queue/can-process", func(w http.ResponseWriter, r *http.Request) { + max, err := parseUint32Param(r, "max") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProcessQueue(c, int64(max)) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/queue/process", func(w http.ResponseWriter, r *http.Request) { + max, err := parseUint32Param(r, "max") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := processQueue(c, int64(max)) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/queue/get-queue-details", func(w http.ResponseWriter, r *http.Request) { + resp, err := getQueueDetails(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/queue/can-assign-deposits", func(w http.ResponseWriter, r *http.Request) { + max, err := parseUint32Param(r, "max") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canAssignDeposits(c, int64(max)) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/queue/assign-deposits", func(w http.ResponseWriter, r *http.Request) { + max, err := parseUint32Param(r, "max") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := assignDeposits(c, int64(max)) + apiutils.WriteResponse(w, resp, err) + }) +} + +func parseUint32Param(r *http.Request, name string) (uint32, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + v, err := strconv.ParseUint(raw, 10, 32) + if err != nil { + return 0, err + } + return uint32(v), nil +} diff --git a/rocketpool/api/service/routes.go b/rocketpool/api/service/routes.go new file mode 100644 index 000000000..7c49913bf --- /dev/null +++ b/rocketpool/api/service/routes.go @@ -0,0 +1,27 @@ +package service + +import ( + "net/http" + + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the service module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/service/get-client-status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getClientStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/service/restart-vc", func(w http.ResponseWriter, r *http.Request) { + resp, err := restartVc(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/service/terminate-data-folder", func(w http.ResponseWriter, r *http.Request) { + resp, err := terminateDataFolder(c) + apiutils.WriteResponse(w, resp, err) + }) +} diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index 99c1da10c..389a5f7aa 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -4,12 +4,18 @@ import ( "net/http" "github.com/urfave/cli" + + queueroutes "github.com/rocket-pool/smartnode/rocketpool/api/queue" + serviceroutes "github.com/rocket-pool/smartnode/rocketpool/api/service" ) // RegisterRoutes registers all HTTP API routes onto mux. -// Module-specific routes are registered by successive migration branches. +// Each migration branch adds additional module registrations here. func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) + + queueroutes.RegisterRoutes(mux, c) + serviceroutes.RegisterRoutes(mux, c) } diff --git a/shared/services/rocketpool/queue.go b/shared/services/rocketpool/queue.go index 4ae9e1246..d62ee04af 100644 --- a/shared/services/rocketpool/queue.go +++ b/shared/services/rocketpool/queue.go @@ -3,6 +3,7 @@ package rocketpool import ( "fmt" "math/big" + "net/url" "github.com/goccy/go-json" @@ -11,7 +12,7 @@ import ( // Get queue status func (c *Client) QueueStatus() (api.QueueStatusResponse, error) { - responseBytes, err := c.callAPI("queue status") + responseBytes, err := c.callHTTPAPI("GET", "/api/queue/status", nil) if err != nil { return api.QueueStatusResponse{}, fmt.Errorf("Could not get queue status: %w", err) } @@ -33,7 +34,7 @@ func (c *Client) QueueStatus() (api.QueueStatusResponse, error) { // Check whether the queue can be processed func (c *Client) CanProcessQueue(max uint32) (api.CanProcessQueueResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("queue can-process %d", max)) + responseBytes, err := c.callHTTPAPI("GET", "/api/queue/can-process", url.Values{"max": {fmt.Sprintf("%d", max)}}) if err != nil { return api.CanProcessQueueResponse{}, fmt.Errorf("Could not get can process queue status: %w", err) } @@ -49,7 +50,7 @@ func (c *Client) CanProcessQueue(max uint32) (api.CanProcessQueueResponse, error // Process the queue func (c *Client) ProcessQueue(max uint32) (api.ProcessQueueResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("queue process %d", max)) + responseBytes, err := c.callHTTPAPI("POST", "/api/queue/process", url.Values{"max": {fmt.Sprintf("%d", max)}}) if err != nil { return api.ProcessQueueResponse{}, fmt.Errorf("Could not process queue: %w", err) } @@ -65,7 +66,7 @@ func (c *Client) ProcessQueue(max uint32) (api.ProcessQueueResponse, error) { // Check whether deposits can be assigned func (c *Client) CanAssignDeposits(max uint32) (api.CanAssignDepositsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("queue can-assign-deposits %d", max)) + responseBytes, err := c.callHTTPAPI("GET", "/api/queue/can-assign-deposits", url.Values{"max": {fmt.Sprintf("%d", max)}}) if err != nil { return api.CanAssignDepositsResponse{}, fmt.Errorf("Could not get can assign deposits status: %w", err) } @@ -81,7 +82,7 @@ func (c *Client) CanAssignDeposits(max uint32) (api.CanAssignDepositsResponse, e // Assign deposits to queued validators func (c *Client) AssignDeposits(max uint32) (api.AssignDepositsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("queue assign-deposits %d", max)) + responseBytes, err := c.callHTTPAPI("POST", "/api/queue/assign-deposits", url.Values{"max": {fmt.Sprintf("%d", max)}}) if err != nil { return api.AssignDepositsResponse{}, fmt.Errorf("Could not assign deposits: %w", err) } @@ -96,7 +97,7 @@ func (c *Client) AssignDeposits(max uint32) (api.AssignDepositsResponse, error) } func (c *Client) GetQueueDetails() (api.GetQueueDetailsResponse, error) { - responseBytes, err := c.callAPI("queue get-queue-details") + responseBytes, err := c.callHTTPAPI("GET", "/api/queue/get-queue-details", nil) if err != nil { return api.GetQueueDetailsResponse{}, fmt.Errorf("Could not get total queue length: %w", err) } diff --git a/shared/services/rocketpool/service.go b/shared/services/rocketpool/service.go index dd91b1455..1adc4c182 100644 --- a/shared/services/rocketpool/service.go +++ b/shared/services/rocketpool/service.go @@ -11,7 +11,7 @@ import ( // Deletes the data folder including the wallet file, password file, and all validator keys. // Don't use this unless you have a very good reason to do it (such as switching from a Testnet to Mainnet). func (c *Client) TerminateDataFolder() (api.TerminateDataFolderResponse, error) { - responseBytes, err := c.callAPI("service terminate-data-folder") + responseBytes, err := c.callHTTPAPI("POST", "/api/service/terminate-data-folder", nil) if err != nil { return api.TerminateDataFolderResponse{}, fmt.Errorf("Could not delete data folder: %w", err) } @@ -27,7 +27,7 @@ func (c *Client) TerminateDataFolder() (api.TerminateDataFolderResponse, error) // Gets the status of the configured Execution and Beacon clients func (c *Client) GetClientStatus() (api.ClientStatusResponse, error) { - responseBytes, err := c.callAPI("service get-client-status") + responseBytes, err := c.callHTTPAPI("GET", "/api/service/get-client-status", nil) if err != nil { return api.ClientStatusResponse{}, fmt.Errorf("Could not get client status: %w", err) } @@ -43,7 +43,7 @@ func (c *Client) GetClientStatus() (api.ClientStatusResponse, error) { // Restarts the Validator client func (c *Client) RestartVc() (api.RestartVcResponse, error) { - responseBytes, err := c.callAPI("service restart-vc") + responseBytes, err := c.callHTTPAPI("POST", "/api/service/restart-vc", nil) if err != nil { return api.RestartVcResponse{}, fmt.Errorf("Could not get restart-vc status: %w", err) } diff --git a/shared/utils/api/http.go b/shared/utils/api/http.go new file mode 100644 index 000000000..3d5e4afbe --- /dev/null +++ b/shared/utils/api/http.go @@ -0,0 +1,61 @@ +package api + +import ( + "errors" + "fmt" + "net/http" + "reflect" + + "github.com/goccy/go-json" + + "github.com/rocket-pool/smartnode/shared/types/api" +) + +// WriteResponse serialises response as JSON and writes it to w, applying the +// same Status/Error population logic as PrintResponse. +// response must be a pointer to a struct with string fields named Status and +// Error (same contract as PrintResponse). +func WriteResponse(w http.ResponseWriter, response interface{}, responseError error) { + r := reflect.ValueOf(response) + if !(r.Kind() == reflect.Ptr && r.Type().Elem().Kind() == reflect.Struct) { + WriteErrorResponse(w, errors.New("invalid API response")) + return + } + + if r.IsNil() { + response = reflect.New(r.Type().Elem()).Interface() + r = reflect.ValueOf(response) + } + + sf := r.Elem().FieldByName("Status") + ef := r.Elem().FieldByName("Error") + if !(sf.IsValid() && sf.CanSet() && sf.Kind() == reflect.String && + ef.IsValid() && ef.CanSet() && ef.Kind() == reflect.String) { + WriteErrorResponse(w, errors.New("invalid API response")) + return + } + + if responseError != nil { + ef.SetString(responseError.Error()) + } + if ef.String() == "" { + sf.SetString("success") + } else { + sf.SetString("error") + } + + responseBytes, err := json.Marshal(response) + if err != nil { + WriteErrorResponse(w, fmt.Errorf("could not encode API response: %w", err)) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(responseBytes) +} + +// WriteErrorResponse writes a generic error response to w. +func WriteErrorResponse(w http.ResponseWriter, err error) { + WriteResponse(w, &api.APIResponse{}, err) +} From beccb6c0df01a5ebe3dcc59ffde35742dae060af Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:09:19 -0300 Subject: [PATCH 03/24] Migrate auction, network, and wallet modules to HTTP API Server side (routes.go in each api/ module): - auction: 10 routes with lotIndex/amountWei param parsing - network: 9 routes with uint64 param parsing - wallet: 12 routes; refactor init/recover/test handlers to accept explicit params instead of reading CLI flags (c.String/c.Bool/c.Uint) Client side (shared/services/rocketpool/): - auction.go, network.go, wallet.go: replace callAPI with callHTTPAPI Co-authored-by: Cursor --- rocketpool/api/auction/routes.go | 119 ++++++++++++++++++++++++++ rocketpool/api/network/routes.go | 81 ++++++++++++++++++ rocketpool/api/wallet/init.go | 6 +- rocketpool/api/wallet/recover.go | 21 +++-- rocketpool/api/wallet/routes.go | 104 ++++++++++++++++++++++ rocketpool/api/wallet/test.go | 21 +++-- rocketpool/node/routes/routes.go | 6 ++ shared/services/rocketpool/auction.go | 35 +++++--- shared/services/rocketpool/network.go | 19 ++-- shared/services/rocketpool/wallet.go | 81 ++++++++++-------- 10 files changed, 420 insertions(+), 73 deletions(-) create mode 100644 rocketpool/api/auction/routes.go create mode 100644 rocketpool/api/network/routes.go create mode 100644 rocketpool/api/wallet/routes.go diff --git a/rocketpool/api/auction/routes.go b/rocketpool/api/auction/routes.go new file mode 100644 index 000000000..4e4139b15 --- /dev/null +++ b/rocketpool/api/auction/routes.go @@ -0,0 +1,119 @@ +package auction + +import ( + "fmt" + "math/big" + "net/http" + "strconv" + + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the auction module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/auction/status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/lots", func(w http.ResponseWriter, r *http.Request) { + resp, err := getLots(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/can-create-lot", func(w http.ResponseWriter, r *http.Request) { + resp, err := canCreateLot(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/create-lot", func(w http.ResponseWriter, r *http.Request) { + resp, err := createLot(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/can-bid-lot", func(w http.ResponseWriter, r *http.Request) { + lotIndex, amountWei, err := parseLotIndexAndAmount(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canBidOnLot(c, lotIndex, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/bid-lot", func(w http.ResponseWriter, r *http.Request) { + lotIndex, amountWei, err := parseLotIndexAndAmount(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := bidOnLot(c, lotIndex, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/can-claim-lot", func(w http.ResponseWriter, r *http.Request) { + lotIndex, err := parseLotIndex(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canClaimFromLot(c, lotIndex) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/claim-lot", func(w http.ResponseWriter, r *http.Request) { + lotIndex, err := parseLotIndex(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := claimFromLot(c, lotIndex) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/can-recover-lot", func(w http.ResponseWriter, r *http.Request) { + lotIndex, err := parseLotIndex(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canRecoverRplFromLot(c, lotIndex) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/auction/recover-lot", func(w http.ResponseWriter, r *http.Request) { + lotIndex, err := parseLotIndex(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := recoverRplFromLot(c, lotIndex) + apiutils.WriteResponse(w, resp, err) + }) +} + +func parseLotIndex(r *http.Request) (uint64, error) { + raw := r.URL.Query().Get("lotIndex") + if raw == "" { + raw = r.FormValue("lotIndex") + } + return strconv.ParseUint(raw, 10, 64) +} + +func parseLotIndexAndAmount(r *http.Request) (uint64, *big.Int, error) { + lotIndex, err := parseLotIndex(r) + if err != nil { + return 0, nil, err + } + raw := r.URL.Query().Get("amountWei") + if raw == "" { + raw = r.FormValue("amountWei") + } + amountWei, ok := new(big.Int).SetString(raw, 10) + if !ok { + return 0, nil, fmt.Errorf("invalid amountWei: %s", raw) + } + return lotIndex, amountWei, nil +} diff --git a/rocketpool/api/network/routes.go b/rocketpool/api/network/routes.go new file mode 100644 index 000000000..8ec082ab3 --- /dev/null +++ b/rocketpool/api/network/routes.go @@ -0,0 +1,81 @@ +package network + +import ( + "net/http" + "strconv" + + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the network module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/network/node-fee", func(w http.ResponseWriter, r *http.Request) { + resp, err := getNodeFee(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/network/rpl-price", func(w http.ResponseWriter, r *http.Request) { + resp, err := getRplPrice(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/network/stats", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStats(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/network/timezone-map", func(w http.ResponseWriter, r *http.Request) { + resp, err := getTimezones(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/network/can-generate-rewards-tree", func(w http.ResponseWriter, r *http.Request) { + index, err := parseUint64Param(r, "index") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canGenerateRewardsTree(c, index) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/network/generate-rewards-tree", func(w http.ResponseWriter, r *http.Request) { + index, err := parseUint64Param(r, "index") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := generateRewardsTree(c, index) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/network/dao-proposals", func(w http.ResponseWriter, r *http.Request) { + resp, err := getActiveDAOProposals(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/network/download-rewards-file", func(w http.ResponseWriter, r *http.Request) { + interval, err := parseUint64Param(r, "interval") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := downloadRewardsFile(c, interval) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/network/latest-delegate", func(w http.ResponseWriter, r *http.Request) { + resp, err := getLatestDelegate(c) + apiutils.WriteResponse(w, resp, err) + }) +} + +func parseUint64Param(r *http.Request, name string) (uint64, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + return strconv.ParseUint(raw, 10, 64) +} diff --git a/rocketpool/api/wallet/init.go b/rocketpool/api/wallet/init.go index 70bf5d4bf..19bd1167c 100644 --- a/rocketpool/api/wallet/init.go +++ b/rocketpool/api/wallet/init.go @@ -11,6 +11,10 @@ import ( ) func initWallet(c *cli.Command) (*api.InitWalletResponse, error) { + return initWalletWithPath(c, c.String("derivation-path")) +} + +func initWalletWithPath(c *cli.Command, derivationPath string) (*api.InitWalletResponse, error) { // Get services w, err := services.GetWallet(c) @@ -27,7 +31,7 @@ func initWallet(c *cli.Command) (*api.InitWalletResponse, error) { } // Get the derivation path - path := c.String("derivation-path") + path := derivationPath switch path { case "": path = wallet.DefaultNodeKeyPath diff --git a/rocketpool/api/wallet/recover.go b/rocketpool/api/wallet/recover.go index d7622732c..5bfee2262 100644 --- a/rocketpool/api/wallet/recover.go +++ b/rocketpool/api/wallet/recover.go @@ -19,6 +19,10 @@ const ( ) func recoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, error) { + return recoverWalletWithParams(c, mnemonic, c.Bool("skip-validator-key-recovery"), c.String("derivation-path"), c.Uint("wallet-index")) +} + +func recoverWalletWithParams(c *cli.Command, mnemonic string, skipValidatorKeyRecovery bool, derivationPath string, walletIndex uint) (*api.RecoverWalletResponse, error) { // Get services w, err := services.GetWallet(c) @@ -26,7 +30,7 @@ func recoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, return nil, err } var rp *rocketpool.RocketPool - if !c.Bool("skip-validator-key-recovery") { + if !skipValidatorKeyRecovery { if err := services.RequireRocketStorage(c); err != nil { return nil, err } @@ -49,7 +53,7 @@ func recoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, } // Get the derivation path - path := c.String("derivation-path") + path := derivationPath switch path { case "": path = wallet.DefaultNodeKeyPath @@ -59,9 +63,6 @@ func recoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, path = wallet.MyEtherWalletNodeKeyPath } - // Get the wallet index - walletIndex := c.Uint("wallet-index") - // Recover wallet if err := w.Recover(path, walletIndex, mnemonic); err != nil { return nil, err @@ -74,7 +75,7 @@ func recoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, } response.AccountAddress = nodeAccount.Address - if !c.Bool("skip-validator-key-recovery") { + if !skipValidatorKeyRecovery { response.ValidatorKeys, err = walletutils.RecoverNodeKeys(c, rp, bc, nodeAccount.Address, w, false) if err != nil { return nil, err @@ -92,6 +93,10 @@ func recoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, } func searchAndRecoverWallet(c *cli.Command, mnemonic string, address common.Address) (*api.SearchAndRecoverWalletResponse, error) { + return searchAndRecoverWalletWithParams(c, mnemonic, address, c.Bool("skip-validator-key-recovery")) +} + +func searchAndRecoverWalletWithParams(c *cli.Command, mnemonic string, address common.Address, skipValidatorKeyRecovery bool) (*api.SearchAndRecoverWalletResponse, error) { // Get services w, err := services.GetWallet(c) @@ -99,7 +104,7 @@ func searchAndRecoverWallet(c *cli.Command, mnemonic string, address common.Addr return nil, err } var rp *rocketpool.RocketPool - if !c.Bool("skip-validator-key-recovery") { + if !skipValidatorKeyRecovery { if err := services.RequireRocketStorage(c); err != nil { return nil, err } @@ -173,7 +178,7 @@ func searchAndRecoverWallet(c *cli.Command, mnemonic string, address common.Addr } response.AccountAddress = nodeAccount.Address - if !c.Bool("skip-validator-key-recovery") { + if !skipValidatorKeyRecovery { response.ValidatorKeys, err = walletutils.RecoverNodeKeys(c, rp, bc, nodeAccount.Address, w, false) if err != nil { return nil, err diff --git a/rocketpool/api/wallet/routes.go b/rocketpool/api/wallet/routes.go new file mode 100644 index 000000000..63c86645e --- /dev/null +++ b/rocketpool/api/wallet/routes.go @@ -0,0 +1,104 @@ +package wallet + +import ( + "net/http" + "strconv" + + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the wallet module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/wallet/status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/set-password", func(w http.ResponseWriter, r *http.Request) { + password := r.FormValue("password") + resp, err := setPassword(c, password) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/init", func(w http.ResponseWriter, r *http.Request) { + derivationPath := r.URL.Query().Get("derivationPath") + if derivationPath == "" { + derivationPath = r.FormValue("derivationPath") + } + resp, err := initWalletWithPath(c, derivationPath) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/recover", func(w http.ResponseWriter, r *http.Request) { + mnemonic := r.FormValue("mnemonic") + skipRecovery := r.FormValue("skipValidatorKeyRecovery") == "true" + derivationPath := r.FormValue("derivationPath") + walletIndex, _ := strconv.ParseUint(r.FormValue("walletIndex"), 10, 64) + resp, err := recoverWalletWithParams(c, mnemonic, skipRecovery, derivationPath, uint(walletIndex)) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/search-and-recover", func(w http.ResponseWriter, r *http.Request) { + mnemonic := r.FormValue("mnemonic") + address := common.HexToAddress(r.FormValue("address")) + skipRecovery := r.FormValue("skipValidatorKeyRecovery") == "true" + resp, err := searchAndRecoverWalletWithParams(c, mnemonic, address, skipRecovery) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/test-recover", func(w http.ResponseWriter, r *http.Request) { + mnemonic := r.FormValue("mnemonic") + skipRecovery := r.FormValue("skipValidatorKeyRecovery") == "true" + derivationPath := r.FormValue("derivationPath") + walletIndex, _ := strconv.ParseUint(r.FormValue("walletIndex"), 10, 64) + resp, err := testRecoverWalletWithParams(c, mnemonic, skipRecovery, derivationPath, uint(walletIndex)) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/test-search-and-recover", func(w http.ResponseWriter, r *http.Request) { + mnemonic := r.FormValue("mnemonic") + address := common.HexToAddress(r.FormValue("address")) + skipRecovery := r.FormValue("skipValidatorKeyRecovery") == "true" + resp, err := testSearchAndRecoverWalletWithParams(c, mnemonic, address, skipRecovery) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/rebuild", func(w http.ResponseWriter, r *http.Request) { + resp, err := rebuildWallet(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/export", func(w http.ResponseWriter, r *http.Request) { + resp, err := exportWallet(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/masquerade", func(w http.ResponseWriter, r *http.Request) { + address := common.HexToAddress(r.FormValue("address")) + resp, err := masquerade(c, address) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/end-masquerade", func(w http.ResponseWriter, r *http.Request) { + resp, err := endMasquerade(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/estimate-gas-set-ens-name", func(w http.ResponseWriter, r *http.Request) { + name := r.URL.Query().Get("name") + if name == "" { + name = r.FormValue("name") + } + resp, err := setEnsName(c, name, true) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/wallet/set-ens-name", func(w http.ResponseWriter, r *http.Request) { + name := r.FormValue("name") + resp, err := setEnsName(c, name, false) + apiutils.WriteResponse(w, resp, err) + }) +} diff --git a/rocketpool/api/wallet/test.go b/rocketpool/api/wallet/test.go index ce124c5cc..639e819aa 100644 --- a/rocketpool/api/wallet/test.go +++ b/rocketpool/api/wallet/test.go @@ -14,6 +14,10 @@ import ( ) func testRecoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletResponse, error) { + return testRecoverWalletWithParams(c, mnemonic, c.Bool("skip-validator-key-recovery"), c.String("derivation-path"), c.Uint("wallet-index")) +} + +func testRecoverWalletWithParams(c *cli.Command, mnemonic string, skipValidatorKeyRecovery bool, derivationPath string, walletIndex uint) (*api.RecoverWalletResponse, error) { // Get services cfg, err := services.GetConfig(c) @@ -21,7 +25,7 @@ func testRecoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletRespo return nil, err } var rp *rocketpool.RocketPool - if !c.Bool("skip-validator-key-recovery") { + if !skipValidatorKeyRecovery { if err := services.RequireRocketStorage(c); err != nil { return nil, err } @@ -47,7 +51,7 @@ func testRecoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletRespo response := api.RecoverWalletResponse{} // Get the derivation path - path := c.String("derivation-path") + path := derivationPath switch path { case "": path = wallet.DefaultNodeKeyPath @@ -57,9 +61,6 @@ func testRecoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletRespo path = wallet.MyEtherWalletNodeKeyPath } - // Get the wallet index - walletIndex := c.Uint("wallet-index") - // Recover wallet if err := w.TestRecovery(path, walletIndex, mnemonic); err != nil { return nil, err @@ -72,7 +73,7 @@ func testRecoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletRespo } response.AccountAddress = nodeAccount.Address - if !c.Bool("skip-validator-key-recovery") { + if !skipValidatorKeyRecovery { response.ValidatorKeys, err = walletutils.RecoverNodeKeys(c, rp, bc, nodeAccount.Address, w, true) if err != nil { return nil, err @@ -85,6 +86,10 @@ func testRecoverWallet(c *cli.Command, mnemonic string) (*api.RecoverWalletRespo } func testSearchAndRecoverWallet(c *cli.Command, mnemonic string, address common.Address) (*api.SearchAndRecoverWalletResponse, error) { + return testSearchAndRecoverWalletWithParams(c, mnemonic, address, c.Bool("skip-validator-key-recovery")) +} + +func testSearchAndRecoverWalletWithParams(c *cli.Command, mnemonic string, address common.Address, skipValidatorKeyRecovery bool) (*api.SearchAndRecoverWalletResponse, error) { // Get services cfg, err := services.GetConfig(c) @@ -92,7 +97,7 @@ func testSearchAndRecoverWallet(c *cli.Command, mnemonic string, address common. return nil, err } var rp *rocketpool.RocketPool - if !c.Bool("skip-validator-key-recovery") { + if !skipValidatorKeyRecovery { if err := services.RequireRocketStorage(c); err != nil { return nil, err } @@ -169,7 +174,7 @@ func testSearchAndRecoverWallet(c *cli.Command, mnemonic string, address common. } response.AccountAddress = nodeAccount.Address - if !c.Bool("skip-validator-key-recovery") { + if !skipValidatorKeyRecovery { response.ValidatorKeys, err = walletutils.RecoverNodeKeys(c, rp, bc, nodeAccount.Address, w, true) if err != nil { return nil, err diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index 389a5f7aa..7f0fa56b1 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -5,8 +5,11 @@ import ( "github.com/urfave/cli" + auctionroutes "github.com/rocket-pool/smartnode/rocketpool/api/auction" + networkroutes "github.com/rocket-pool/smartnode/rocketpool/api/network" queueroutes "github.com/rocket-pool/smartnode/rocketpool/api/queue" serviceroutes "github.com/rocket-pool/smartnode/rocketpool/api/service" + walletroutes "github.com/rocket-pool/smartnode/rocketpool/api/wallet" ) // RegisterRoutes registers all HTTP API routes onto mux. @@ -16,6 +19,9 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { w.WriteHeader(http.StatusOK) }) + auctionroutes.RegisterRoutes(mux, c) + networkroutes.RegisterRoutes(mux, c) queueroutes.RegisterRoutes(mux, c) serviceroutes.RegisterRoutes(mux, c) + walletroutes.RegisterRoutes(mux, c) } diff --git a/shared/services/rocketpool/auction.go b/shared/services/rocketpool/auction.go index f22714e35..12f0aa5c5 100644 --- a/shared/services/rocketpool/auction.go +++ b/shared/services/rocketpool/auction.go @@ -3,6 +3,7 @@ package rocketpool import ( "fmt" "math/big" + "net/url" "github.com/goccy/go-json" "github.com/rocket-pool/smartnode/shared/types/api" @@ -10,7 +11,7 @@ import ( // Get RPL auction status func (c *Client) AuctionStatus() (api.AuctionStatusResponse, error) { - responseBytes, err := c.callAPI("auction status") + responseBytes, err := c.callHTTPAPI("GET", "/api/auction/status", nil) if err != nil { return api.AuctionStatusResponse{}, fmt.Errorf("Could not get auction status: %w", err) } @@ -35,7 +36,7 @@ func (c *Client) AuctionStatus() (api.AuctionStatusResponse, error) { // Get RPL lots for auction func (c *Client) AuctionLots() (api.AuctionLotsResponse, error) { - responseBytes, err := c.callAPI("auction lots") + responseBytes, err := c.callHTTPAPI("GET", "/api/auction/lots", nil) if err != nil { return api.AuctionLotsResponse{}, fmt.Errorf("Could not get auction lots: %w", err) } @@ -84,7 +85,7 @@ func (c *Client) AuctionLots() (api.AuctionLotsResponse, error) { // Check whether the node can create a new lot func (c *Client) CanCreateLot() (api.CanCreateLotResponse, error) { - responseBytes, err := c.callAPI("auction can-create-lot") + responseBytes, err := c.callHTTPAPI("GET", "/api/auction/can-create-lot", nil) if err != nil { return api.CanCreateLotResponse{}, fmt.Errorf("Could not get can create lot status: %w", err) } @@ -100,7 +101,7 @@ func (c *Client) CanCreateLot() (api.CanCreateLotResponse, error) { // Create a new lot func (c *Client) CreateLot() (api.CreateLotResponse, error) { - responseBytes, err := c.callAPI("auction create-lot") + responseBytes, err := c.callHTTPAPI("POST", "/api/auction/create-lot", nil) if err != nil { return api.CreateLotResponse{}, fmt.Errorf("Could not create lot: %w", err) } @@ -116,7 +117,10 @@ func (c *Client) CreateLot() (api.CreateLotResponse, error) { // Check whether the node can bid on a lot func (c *Client) CanBidOnLot(lotIndex uint64, amountWei *big.Int) (api.CanBidOnLotResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("auction can-bid-lot %d %s", lotIndex, amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/auction/can-bid-lot", url.Values{ + "lotIndex": {fmt.Sprintf("%d", lotIndex)}, + "amountWei": {amountWei.String()}, + }) if err != nil { return api.CanBidOnLotResponse{}, fmt.Errorf("Could not get can bid on lot status: %w", err) } @@ -132,7 +136,10 @@ func (c *Client) CanBidOnLot(lotIndex uint64, amountWei *big.Int) (api.CanBidOnL // Bid on a lot func (c *Client) BidOnLot(lotIndex uint64, amountWei *big.Int) (api.BidOnLotResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("auction bid-lot %d %s", lotIndex, amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/auction/bid-lot", url.Values{ + "lotIndex": {fmt.Sprintf("%d", lotIndex)}, + "amountWei": {amountWei.String()}, + }) if err != nil { return api.BidOnLotResponse{}, fmt.Errorf("Could not bid on lot: %w", err) } @@ -148,7 +155,9 @@ func (c *Client) BidOnLot(lotIndex uint64, amountWei *big.Int) (api.BidOnLotResp // Check whether the node can claim RPL from a lot func (c *Client) CanClaimFromLot(lotIndex uint64) (api.CanClaimFromLotResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("auction can-claim-lot %d", lotIndex)) + responseBytes, err := c.callHTTPAPI("GET", "/api/auction/can-claim-lot", url.Values{ + "lotIndex": {fmt.Sprintf("%d", lotIndex)}, + }) if err != nil { return api.CanClaimFromLotResponse{}, fmt.Errorf("Could not get can claim RPL from lot status: %w", err) } @@ -164,7 +173,9 @@ func (c *Client) CanClaimFromLot(lotIndex uint64) (api.CanClaimFromLotResponse, // Claim RPL from a lot func (c *Client) ClaimFromLot(lotIndex uint64) (api.ClaimFromLotResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("auction claim-lot %d", lotIndex)) + responseBytes, err := c.callHTTPAPI("POST", "/api/auction/claim-lot", url.Values{ + "lotIndex": {fmt.Sprintf("%d", lotIndex)}, + }) if err != nil { return api.ClaimFromLotResponse{}, fmt.Errorf("Could not claim RPL from lot: %w", err) } @@ -180,7 +191,9 @@ func (c *Client) ClaimFromLot(lotIndex uint64) (api.ClaimFromLotResponse, error) // Check whether the node can recover unclaimed RPL from a lot func (c *Client) CanRecoverUnclaimedRPLFromLot(lotIndex uint64) (api.CanRecoverRPLFromLotResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("auction can-recover-lot %d", lotIndex)) + responseBytes, err := c.callHTTPAPI("GET", "/api/auction/can-recover-lot", url.Values{ + "lotIndex": {fmt.Sprintf("%d", lotIndex)}, + }) if err != nil { return api.CanRecoverRPLFromLotResponse{}, fmt.Errorf("Could not get can recover unclaimed RPL from lot status: %w", err) } @@ -196,7 +209,9 @@ func (c *Client) CanRecoverUnclaimedRPLFromLot(lotIndex uint64) (api.CanRecoverR // Recover unclaimed RPL from a lot (returning it to the auction contract) func (c *Client) RecoverUnclaimedRPLFromLot(lotIndex uint64) (api.RecoverRPLFromLotResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("auction recover-lot %d", lotIndex)) + responseBytes, err := c.callHTTPAPI("POST", "/api/auction/recover-lot", url.Values{ + "lotIndex": {fmt.Sprintf("%d", lotIndex)}, + }) if err != nil { return api.RecoverRPLFromLotResponse{}, fmt.Errorf("Could not recover unclaimed RPL from lot: %w", err) } diff --git a/shared/services/rocketpool/network.go b/shared/services/rocketpool/network.go index d72e30ca8..175462a35 100644 --- a/shared/services/rocketpool/network.go +++ b/shared/services/rocketpool/network.go @@ -3,6 +3,7 @@ package rocketpool import ( "fmt" "math/big" + "net/url" "github.com/goccy/go-json" "github.com/rocket-pool/smartnode/shared/types/api" @@ -10,7 +11,7 @@ import ( // Get network node fee func (c *Client) NodeFee() (api.NodeFeeResponse, error) { - responseBytes, err := c.callAPI("network node-fee") + responseBytes, err := c.callHTTPAPI("GET", "/api/network/node-fee", nil) if err != nil { return api.NodeFeeResponse{}, fmt.Errorf("Could not get network node fee: %w", err) } @@ -26,7 +27,7 @@ func (c *Client) NodeFee() (api.NodeFeeResponse, error) { // Get network RPL price func (c *Client) RplPrice() (api.RplPriceResponse, error) { - responseBytes, err := c.callAPI("network rpl-price") + responseBytes, err := c.callHTTPAPI("GET", "/api/network/rpl-price", nil) if err != nil { return api.RplPriceResponse{}, fmt.Errorf("Could not get network RPL price: %w", err) } @@ -45,7 +46,7 @@ func (c *Client) RplPrice() (api.RplPriceResponse, error) { // Get network stats func (c *Client) NetworkStats() (api.NetworkStatsResponse, error) { - responseBytes, err := c.callAPI("network stats") + responseBytes, err := c.callHTTPAPI("GET", "/api/network/stats", nil) if err != nil { return api.NetworkStatsResponse{}, fmt.Errorf("Could not get network stats: %w", err) } @@ -61,7 +62,7 @@ func (c *Client) NetworkStats() (api.NetworkStatsResponse, error) { // Get the timezone map func (c *Client) TimezoneMap() (api.NetworkTimezonesResponse, error) { - responseBytes, err := c.callAPI("network timezone-map") + responseBytes, err := c.callHTTPAPI("GET", "/api/network/timezone-map", nil) if err != nil { return api.NetworkTimezonesResponse{}, fmt.Errorf("Could not get network timezone map: %w", err) } @@ -77,7 +78,7 @@ func (c *Client) TimezoneMap() (api.NetworkTimezonesResponse, error) { // Check if the rewards tree for the provided interval can be generated func (c *Client) CanGenerateRewardsTree(index uint64) (api.CanNetworkGenerateRewardsTreeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("network can-generate-rewards-tree %d", index)) + responseBytes, err := c.callHTTPAPI("GET", "/api/network/can-generate-rewards-tree", url.Values{"index": {fmt.Sprintf("%d", index)}}) if err != nil { return api.CanNetworkGenerateRewardsTreeResponse{}, fmt.Errorf("Could not check rewards tree generation status: %w", err) } @@ -93,7 +94,7 @@ func (c *Client) CanGenerateRewardsTree(index uint64) (api.CanNetworkGenerateRew // Set a request marker for the watchtower to generate the rewards tree for the given interval func (c *Client) GenerateRewardsTree(index uint64) (api.NetworkGenerateRewardsTreeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("network generate-rewards-tree %d", index)) + responseBytes, err := c.callHTTPAPI("POST", "/api/network/generate-rewards-tree", url.Values{"index": {fmt.Sprintf("%d", index)}}) if err != nil { return api.NetworkGenerateRewardsTreeResponse{}, fmt.Errorf("Could not initialize rewards tree generation: %w", err) } @@ -109,7 +110,7 @@ func (c *Client) GenerateRewardsTree(index uint64) (api.NetworkGenerateRewardsTr // GetActiveDAOProposals fetches information about active DAO proposals func (c *Client) GetActiveDAOProposals() (api.NetworkDAOProposalsResponse, error) { - responseBytes, err := c.callAPI("network dao-proposals") + responseBytes, err := c.callHTTPAPI("GET", "/api/network/dao-proposals", nil) if err != nil { return api.NetworkDAOProposalsResponse{}, fmt.Errorf("could not request active DAO proposals: %w", err) } @@ -125,7 +126,7 @@ func (c *Client) GetActiveDAOProposals() (api.NetworkDAOProposalsResponse, error // Download a rewards info file from IPFS for the given interval func (c *Client) DownloadRewardsFile(interval uint64) (api.DownloadRewardsFileResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("network download-rewards-file %d", interval)) + responseBytes, err := c.callHTTPAPI("POST", "/api/network/download-rewards-file", url.Values{"interval": {fmt.Sprintf("%d", interval)}}) if err != nil { return api.DownloadRewardsFileResponse{}, fmt.Errorf("could not download rewards file: %w", err) } @@ -141,7 +142,7 @@ func (c *Client) DownloadRewardsFile(interval uint64) (api.DownloadRewardsFileRe // Get the address of the latest minipool delegate contract func (c *Client) GetLatestDelegate() (api.GetLatestDelegateResponse, error) { - responseBytes, err := c.callAPI("network latest-delegate") + responseBytes, err := c.callHTTPAPI("GET", "/api/network/latest-delegate", nil) if err != nil { return api.GetLatestDelegateResponse{}, fmt.Errorf("could not get latest delegate: %w", err) } diff --git a/shared/services/rocketpool/wallet.go b/shared/services/rocketpool/wallet.go index a82a60e62..f21075725 100644 --- a/shared/services/rocketpool/wallet.go +++ b/shared/services/rocketpool/wallet.go @@ -2,6 +2,7 @@ package rocketpool import ( "fmt" + "net/url" "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" @@ -11,7 +12,7 @@ import ( // Get wallet status func (c *Client) WalletStatus() (api.WalletStatusResponse, error) { - responseBytes, err := c.callAPI("wallet status") + responseBytes, err := c.callHTTPAPI("GET", "/api/wallet/status", nil) if err != nil { return api.WalletStatusResponse{}, fmt.Errorf("Could not get wallet status: %w", err) } @@ -27,7 +28,7 @@ func (c *Client) WalletStatus() (api.WalletStatusResponse, error) { // Set wallet password func (c *Client) SetPassword(password string) (api.SetPasswordResponse, error) { - responseBytes, err := c.callAPI("wallet set-password", password) + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/set-password", url.Values{"password": {password}}) if err != nil { return api.SetPasswordResponse{}, fmt.Errorf("Could not set wallet password: %w", err) } @@ -43,7 +44,7 @@ func (c *Client) SetPassword(password string) (api.SetPasswordResponse, error) { // Initialize wallet func (c *Client) InitWallet(derivationPath string) (api.InitWalletResponse, error) { - responseBytes, err := c.callAPI("wallet init --derivation-path", derivationPath) + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/init", url.Values{"derivationPath": {derivationPath}}) if err != nil { return api.InitWalletResponse{}, fmt.Errorf("Could not initialize wallet: %w", err) } @@ -59,16 +60,16 @@ func (c *Client) InitWallet(derivationPath string) (api.InitWalletResponse, erro // Recover wallet func (c *Client) RecoverWallet(mnemonic string, skipValidatorKeyRecovery bool, derivationPath string, walletIndex uint) (api.RecoverWalletResponse, error) { - command := "wallet recover " + skipStr := "false" if skipValidatorKeyRecovery { - command += "--skip-validator-key-recovery " - } - if walletIndex != 0 { - command += fmt.Sprintf("--wallet-index %d ", walletIndex) - } - command += "--derivation-path" - - responseBytes, err := c.callAPI(command, derivationPath, mnemonic) + skipStr = "true" + } + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/recover", url.Values{ + "mnemonic": {mnemonic}, + "skipValidatorKeyRecovery": {skipStr}, + "derivationPath": {derivationPath}, + "walletIndex": {fmt.Sprintf("%d", walletIndex)}, + }) if err != nil { return api.RecoverWalletResponse{}, fmt.Errorf("Could not recover wallet: %w", err) } @@ -84,12 +85,15 @@ func (c *Client) RecoverWallet(mnemonic string, skipValidatorKeyRecovery bool, d // Search and recover wallet func (c *Client) SearchAndRecoverWallet(mnemonic string, address common.Address, skipValidatorKeyRecovery bool) (api.SearchAndRecoverWalletResponse, error) { - command := "wallet search-and-recover " + skipStr := "false" if skipValidatorKeyRecovery { - command += "--skip-validator-key-recovery " + skipStr = "true" } - - responseBytes, err := c.callAPI(command, mnemonic, address.Hex()) + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/search-and-recover", url.Values{ + "mnemonic": {mnemonic}, + "address": {address.Hex()}, + "skipValidatorKeyRecovery": {skipStr}, + }) if err != nil { return api.SearchAndRecoverWalletResponse{}, fmt.Errorf("Could not search and recover wallet: %w", err) } @@ -103,18 +107,18 @@ func (c *Client) SearchAndRecoverWallet(mnemonic string, address common.Address, return response, nil } -// Recover wallet +// Recover wallet (test, no save) func (c *Client) TestRecoverWallet(mnemonic string, skipValidatorKeyRecovery bool, derivationPath string, walletIndex uint) (api.RecoverWalletResponse, error) { - command := "wallet test-recovery " + skipStr := "false" if skipValidatorKeyRecovery { - command += "--skip-validator-key-recovery " - } - if walletIndex != 0 { - command += fmt.Sprintf("--wallet-index %d ", walletIndex) - } - command += "--derivation-path" - - responseBytes, err := c.callAPI(command, derivationPath, mnemonic) + skipStr = "true" + } + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/test-recover", url.Values{ + "mnemonic": {mnemonic}, + "skipValidatorKeyRecovery": {skipStr}, + "derivationPath": {derivationPath}, + "walletIndex": {fmt.Sprintf("%d", walletIndex)}, + }) if err != nil { return api.RecoverWalletResponse{}, fmt.Errorf("Could not test recover wallet: %w", err) } @@ -128,14 +132,17 @@ func (c *Client) TestRecoverWallet(mnemonic string, skipValidatorKeyRecovery boo return response, nil } -// Search and recover wallet +// Search and recover wallet (test, no save) func (c *Client) TestSearchAndRecoverWallet(mnemonic string, address common.Address, skipValidatorKeyRecovery bool) (api.SearchAndRecoverWalletResponse, error) { - command := "wallet test-search-and-recover " + skipStr := "false" if skipValidatorKeyRecovery { - command += "--skip-validator-key-recovery " + skipStr = "true" } - - responseBytes, err := c.callAPI(command, mnemonic, address.Hex()) + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/test-search-and-recover", url.Values{ + "mnemonic": {mnemonic}, + "address": {address.Hex()}, + "skipValidatorKeyRecovery": {skipStr}, + }) if err != nil { return api.SearchAndRecoverWalletResponse{}, fmt.Errorf("Could not test search and recover wallet: %w", err) } @@ -151,7 +158,7 @@ func (c *Client) TestSearchAndRecoverWallet(mnemonic string, address common.Addr // Rebuild wallet func (c *Client) RebuildWallet() (api.RebuildWalletResponse, error) { - responseBytes, err := c.callAPI("wallet rebuild") + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/rebuild", nil) if err != nil { return api.RebuildWalletResponse{}, fmt.Errorf("Could not rebuild wallet: %w", err) } @@ -167,7 +174,7 @@ func (c *Client) RebuildWallet() (api.RebuildWalletResponse, error) { // Estimate the gas required to set an ENS reverse record to a name func (c *Client) EstimateGasSetEnsName(name string) (api.SetEnsNameResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("wallet estimate-gas-set-ens-name %s", name)) + responseBytes, err := c.callHTTPAPI("GET", "/api/wallet/estimate-gas-set-ens-name", url.Values{"name": {name}}) if err != nil { return api.SetEnsNameResponse{}, fmt.Errorf("Could not get estimate-gas-set-ens-name response: %w", err) } @@ -183,7 +190,7 @@ func (c *Client) EstimateGasSetEnsName(name string) (api.SetEnsNameResponse, err // Set an ENS reverse record to a name func (c *Client) SetEnsName(name string) (api.SetEnsNameResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("wallet set-ens-name %s", name)) + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/set-ens-name", url.Values{"name": {name}}) if err != nil { return api.SetEnsNameResponse{}, fmt.Errorf("Could not update ENS record: %w", err) } @@ -199,7 +206,7 @@ func (c *Client) SetEnsName(name string) (api.SetEnsNameResponse, error) { // Export wallet func (c *Client) ExportWallet() (api.ExportWalletResponse, error) { - responseBytes, err := c.callAPI("wallet export") + responseBytes, err := c.callHTTPAPI("GET", "/api/wallet/export", nil) if err != nil { return api.ExportWalletResponse{}, fmt.Errorf("Could not export wallet: %w", err) } @@ -215,7 +222,7 @@ func (c *Client) ExportWallet() (api.ExportWalletResponse, error) { // Set the node address to an arbitrary address func (c *Client) Masquerade(address common.Address) (api.MasqueradeResponse, error) { - responseBytes, err := c.callAPI("wallet masquerade", address.Hex()) + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/masquerade", url.Values{"address": {address.Hex()}}) if err != nil { return api.MasqueradeResponse{}, fmt.Errorf("Could not masquerade wallet: %w", err) } @@ -231,7 +238,7 @@ func (c *Client) Masquerade(address common.Address) (api.MasqueradeResponse, err // Delete the address file, ending a masquerade func (c *Client) EndMasquerade() (api.EndMasqueradeResponse, error) { - responseBytes, err := c.callAPI("wallet end-masquerade") + responseBytes, err := c.callHTTPAPI("POST", "/api/wallet/end-masquerade", nil) if err != nil { return api.EndMasqueradeResponse{}, fmt.Errorf("Could not end masquerade: %w", err) } From 2db029f1c755e90d2154226d83ac97c97e0f341e Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:14:45 -0300 Subject: [PATCH 04/24] Migrate security and megapool modules to HTTP API Server side: - security/routes.go: RegisterRoutes() for 18 security endpoints (note: ProposeInvite/Kick/KickMulti/Replace have no server-side handlers and remain on callAPI in the client) - megapool/routes.go: RegisterRoutes() for 28 megapool endpoints Client side: - security.go: migrate 22 of 26 methods to callHTTPAPI; 4 legacy methods (ProposeInvite/Kick/KickMulti/Replace) kept on callAPI (no server handler) - megapool.go: all methods migrated to callHTTPAPI Co-authored-by: Cursor --- rocketpool/api/megapool/routes.go | 328 +++++++++++++++++++++++++ rocketpool/api/security/routes.go | 153 ++++++++++++ rocketpool/node/routes/routes.go | 4 + shared/services/rocketpool/megapool.go | 158 ++++++++---- shared/services/rocketpool/security.go | 63 +++-- 5 files changed, 630 insertions(+), 76 deletions(-) create mode 100644 rocketpool/api/megapool/routes.go create mode 100644 rocketpool/api/security/routes.go diff --git a/rocketpool/api/megapool/routes.go b/rocketpool/api/megapool/routes.go new file mode 100644 index 000000000..457a5c4fe --- /dev/null +++ b/rocketpool/api/megapool/routes.go @@ -0,0 +1,328 @@ +package megapool + +import ( + "fmt" + "math/big" + "net/http" + "strconv" + + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the megapool module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/megapool/status", func(w http.ResponseWriter, r *http.Request) { + finalizedState := r.URL.Query().Get("finalizedState") == "true" + resp, err := getStatus(c, finalizedState) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/validator-map-and-balances", func(w http.ResponseWriter, r *http.Request) { + resp, err := getValidatorMapAndBalances(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-claim-refund", func(w http.ResponseWriter, r *http.Request) { + resp, err := canClaimRefund(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/claim-refund", func(w http.ResponseWriter, r *http.Request) { + resp, err := claimRefund(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-repay-debt", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canRepayDebt(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/repay-debt", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := repayDebt(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-reduce-bond", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canReduceBond(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/reduce-bond", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := reduceBond(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-stake", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint64(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canStake(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/stake", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint64(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := stake(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-dissolve-validator", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canDissolveValidator(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/dissolve-validator", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := dissolveValidator(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-dissolve-with-proof", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canDissolveWithProof(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/dissolve-with-proof", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := dissolveWithProof(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-exit-validator", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canExitValidator(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/exit-validator", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := exitValidator(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-notify-validator-exit", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNotifyValidatorExit(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/notify-validator-exit", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := notifyValidatorExit(c, validatorId) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-notify-final-balance", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + slot, err := parseUint64(r, "slot") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNotifyFinalBalance(c, validatorId, slot) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/notify-final-balance", func(w http.ResponseWriter, r *http.Request) { + validatorId, err := parseUint32(r, "validatorId") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + slot, err := parseUint64(r, "slot") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := notifyFinalBalance(c, validatorId, slot) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-exit-queue", func(w http.ResponseWriter, r *http.Request) { + validatorIndex, err := parseUint32(r, "validatorIndex") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canExitQueue(c, validatorIndex) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/exit-queue", func(w http.ResponseWriter, r *http.Request) { + validatorIndex, err := parseUint32(r, "validatorIndex") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := exitQueue(c, validatorIndex) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-distribute", func(w http.ResponseWriter, r *http.Request) { + resp, err := canDistributeMegapool(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/distribute", func(w http.ResponseWriter, r *http.Request) { + resp, err := distributeMegapool(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/get-new-validator-bond-requirement", func(w http.ResponseWriter, r *http.Request) { + resp, err := getNewValidatorBondRequirement(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/pending-rewards", func(w http.ResponseWriter, r *http.Request) { + resp, err := calculatePendingRewards(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/calculate-rewards", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := calculateRewards(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/get-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { + address := common.HexToAddress(r.URL.Query().Get("address")) + resp, err := getUseLatestDelegate(c, address) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-delegate-upgrade", func(w http.ResponseWriter, r *http.Request) { + address := common.HexToAddress(r.URL.Query().Get("address")) + resp, err := canDelegateUpgrade(c, address) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/delegate-upgrade", func(w http.ResponseWriter, r *http.Request) { + address := common.HexToAddress(r.FormValue("address")) + resp, err := delegateUpgrade(c, address) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/can-set-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { + address := common.HexToAddress(r.URL.Query().Get("address")) + resp, err := canSetUseLatestDelegate(c, address) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/set-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { + address := common.HexToAddress(r.FormValue("address")) + resp, err := setUseLatestDelegate(c, address) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/get-delegate", func(w http.ResponseWriter, r *http.Request) { + address := common.HexToAddress(r.URL.Query().Get("address")) + resp, err := getDelegate(c, address) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/megapool/get-effective-delegate", func(w http.ResponseWriter, r *http.Request) { + address := common.HexToAddress(r.URL.Query().Get("address")) + resp, err := getEffectiveDelegate(c, address) + apiutils.WriteResponse(w, resp, err) + }) +} + +func parseUint64(r *http.Request, name string) (uint64, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + return strconv.ParseUint(raw, 10, 64) +} + +func parseUint32(r *http.Request, name string) (uint32, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + v, err := strconv.ParseUint(raw, 10, 32) + return uint32(v), err +} + +func parseBigInt(r *http.Request, name string) (*big.Int, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + v, ok := new(big.Int).SetString(raw, 10) + if !ok { + return nil, fmt.Errorf("invalid %s: %s", name, raw) + } + return v, nil +} diff --git a/rocketpool/api/security/routes.go b/rocketpool/api/security/routes.go new file mode 100644 index 000000000..b82e3d787 --- /dev/null +++ b/rocketpool/api/security/routes.go @@ -0,0 +1,153 @@ +package security + +import ( + "net/http" + "strconv" + + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the security module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/security/status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/members", func(w http.ResponseWriter, r *http.Request) { + resp, err := getMembers(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/proposals", func(w http.ResponseWriter, r *http.Request) { + resp, err := getProposals(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/proposal-details", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/can-propose-leave", func(w http.ResponseWriter, r *http.Request) { + resp, err := canProposeLeave(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/propose-leave", func(w http.ResponseWriter, r *http.Request) { + resp, err := proposeLeave(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/can-propose-setting", func(w http.ResponseWriter, r *http.Request) { + contractName := r.URL.Query().Get("contractName") + settingName := r.URL.Query().Get("settingName") + value := r.URL.Query().Get("value") + resp, err := canProposeSetting(c, contractName, settingName, value) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/propose-setting", func(w http.ResponseWriter, r *http.Request) { + contractName := r.FormValue("contractName") + settingName := r.FormValue("settingName") + value := r.FormValue("value") + resp, err := proposeSetting(c, contractName, settingName, value) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/can-cancel-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canCancelProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/cancel-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := cancelProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/can-vote-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canVoteOnProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/vote-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + support := r.FormValue("support") == "true" + resp, err := voteOnProposal(c, id, support) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/can-execute-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canExecuteProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/execute-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := executeProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/can-join", func(w http.ResponseWriter, r *http.Request) { + resp, err := canJoin(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/join", func(w http.ResponseWriter, r *http.Request) { + resp, err := join(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/can-leave", func(w http.ResponseWriter, r *http.Request) { + resp, err := canLeave(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/security/leave", func(w http.ResponseWriter, r *http.Request) { + resp, err := leave(c) + apiutils.WriteResponse(w, resp, err) + }) +} + +func parseUint64(r *http.Request, name string) (uint64, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + return strconv.ParseUint(raw, 10, 64) +} diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index 7f0fa56b1..39b7feb47 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -6,8 +6,10 @@ import ( "github.com/urfave/cli" auctionroutes "github.com/rocket-pool/smartnode/rocketpool/api/auction" + megapoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/megapool" networkroutes "github.com/rocket-pool/smartnode/rocketpool/api/network" queueroutes "github.com/rocket-pool/smartnode/rocketpool/api/queue" + securityroutes "github.com/rocket-pool/smartnode/rocketpool/api/security" serviceroutes "github.com/rocket-pool/smartnode/rocketpool/api/service" walletroutes "github.com/rocket-pool/smartnode/rocketpool/api/wallet" ) @@ -20,8 +22,10 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { }) auctionroutes.RegisterRoutes(mux, c) + megapoolroutes.RegisterRoutes(mux, c) networkroutes.RegisterRoutes(mux, c) queueroutes.RegisterRoutes(mux, c) + securityroutes.RegisterRoutes(mux, c) serviceroutes.RegisterRoutes(mux, c) walletroutes.RegisterRoutes(mux, c) } diff --git a/shared/services/rocketpool/megapool.go b/shared/services/rocketpool/megapool.go index 021886ac1..7c6228103 100644 --- a/shared/services/rocketpool/megapool.go +++ b/shared/services/rocketpool/megapool.go @@ -3,6 +3,7 @@ package rocketpool import ( "fmt" "math/big" + "net/url" "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" @@ -11,7 +12,11 @@ import ( // Get megapool status func (c *Client) MegapoolStatus(finalizedState bool) (api.MegapoolStatusResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool status %t", finalizedState)) + finalizedStr := "false" + if finalizedState { + finalizedStr = "true" + } + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/status", url.Values{"finalizedState": {finalizedStr}}) if err != nil { return api.MegapoolStatusResponse{}, fmt.Errorf("Could not get megapool status: %w", err) } @@ -22,13 +27,12 @@ func (c *Client) MegapoolStatus(finalizedState bool) (api.MegapoolStatusResponse if response.Error != "" { return api.MegapoolStatusResponse{}, fmt.Errorf("Could not get megapool status: %s", response.Error) } - return response, nil } // Get a map of the node's validators and beacon balances func (c *Client) GetValidatorMapAndBalances() (api.MegapoolValidatorMapAndRewardsResponse, error) { - responseBytes, err := c.callAPI("megapool validator-map-and-balances") + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/validator-map-and-balances", nil) if err != nil { return api.MegapoolValidatorMapAndRewardsResponse{}, fmt.Errorf("Could not get megapool validator-map-and-balances: %w", err) } @@ -42,9 +46,9 @@ func (c *Client) GetValidatorMapAndBalances() (api.MegapoolValidatorMapAndReward return response, nil } -// Check whether the node can repay megapool debt +// Check whether the node can claim a megapool refund func (c *Client) CanClaimMegapoolRefund() (api.CanClaimRefundResponse, error) { - responseBytes, err := c.callAPI("megapool can-claim-refund") + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-claim-refund", nil) if err != nil { return api.CanClaimRefundResponse{}, fmt.Errorf("Could not get can claim refund status: %w", err) } @@ -58,9 +62,9 @@ func (c *Client) CanClaimMegapoolRefund() (api.CanClaimRefundResponse, error) { return response, nil } -// Repay megapool debt +// Claim megapool refund func (c *Client) ClaimMegapoolRefund() (api.ClaimRefundResponse, error) { - responseBytes, err := c.callAPI("megapool claim-refund") + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/claim-refund", nil) if err != nil { return api.ClaimRefundResponse{}, fmt.Errorf("Could not claim refund: %w", err) } @@ -76,7 +80,7 @@ func (c *Client) ClaimMegapoolRefund() (api.ClaimRefundResponse, error) { // Check whether the node can repay megapool debt func (c *Client) CanRepayDebt(amountWei *big.Int) (api.CanRepayDebtResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-repay-debt %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-repay-debt", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanRepayDebtResponse{}, fmt.Errorf("Could not get can repay debt status: %w", err) } @@ -92,7 +96,7 @@ func (c *Client) CanRepayDebt(amountWei *big.Int) (api.CanRepayDebtResponse, err // Repay megapool debt func (c *Client) RepayDebt(amountWei *big.Int) (api.RepayDebtResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool repay-debt %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/repay-debt", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.RepayDebtResponse{}, fmt.Errorf("Could not repay megapool debt: %w", err) } @@ -108,7 +112,7 @@ func (c *Client) RepayDebt(amountWei *big.Int) (api.RepayDebtResponse, error) { // Check whether the node can reduce the megapool bond func (c *Client) CanReduceBond(amountWei *big.Int) (api.CanReduceBondResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-reduce-bond %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-reduce-bond", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanReduceBondResponse{}, fmt.Errorf("Could not get can reduce bond status: %w", err) } @@ -124,7 +128,7 @@ func (c *Client) CanReduceBond(amountWei *big.Int) (api.CanReduceBondResponse, e // Reduce megapool bond func (c *Client) ReduceBond(amountWei *big.Int) (api.ReduceBondResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool reduce-bond %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/reduce-bond", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.ReduceBondResponse{}, fmt.Errorf("Could not reduce bond: %w", err) } @@ -140,7 +144,7 @@ func (c *Client) ReduceBond(amountWei *big.Int) (api.ReduceBondResponse, error) // Check whether the node can stake a megapool validator func (c *Client) CanStake(validatorId uint64) (api.CanStakeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-stake %d", validatorId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-stake", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) if err != nil { return api.CanStakeResponse{}, fmt.Errorf("Could not get can stake status: %w", err) } @@ -156,7 +160,7 @@ func (c *Client) CanStake(validatorId uint64) (api.CanStakeResponse, error) { // Stake a megapool validator func (c *Client) Stake(validatorId uint64) (api.StakeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool stake %d", validatorId)) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/stake", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) if err != nil { return api.StakeResponse{}, fmt.Errorf("Could not stake megapool validator: %w", err) } @@ -170,9 +174,9 @@ func (c *Client) Stake(validatorId uint64) (api.StakeResponse, error) { return response, nil } -// Check whether the megapool validator can be disoolved +// Check whether a megapool validator can be dissolved func (c *Client) CanDissolveValidator(validatorId uint64) (api.CanDissolveValidatorResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-dissolve-validator %d", validatorId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-dissolve-validator", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) if err != nil { return api.CanDissolveValidatorResponse{}, fmt.Errorf("Could not get can dissolve validator status: %w", err) } @@ -188,7 +192,7 @@ func (c *Client) CanDissolveValidator(validatorId uint64) (api.CanDissolveValida // Dissolve a megapool validator func (c *Client) DissolveValidator(validatorId uint64) (api.DissolveValidatorResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool dissolve-validator %d", validatorId)) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/dissolve-validator", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) if err != nil { return api.DissolveValidatorResponse{}, fmt.Errorf("Could not dissolve megapool validator: %w", err) } @@ -202,9 +206,41 @@ func (c *Client) DissolveValidator(validatorId uint64) (api.DissolveValidatorRes return response, nil } -// Check whether the megapool validator can be exited +// Check whether a megapool validator can be dissolved with proof +func (c *Client) CanDissolveWithProof(validatorId uint64) (api.CanDissolveWithProofResponse, error) { + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-dissolve-with-proof", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) + if err != nil { + return api.CanDissolveWithProofResponse{}, fmt.Errorf("Could not get can dissolve-with-proof status: %w", err) + } + var response api.CanDissolveWithProofResponse + if err := json.Unmarshal(responseBytes, &response); err != nil { + return api.CanDissolveWithProofResponse{}, fmt.Errorf("Could not decode can dissolve-with-proof response: %w", err) + } + if response.Error != "" { + return api.CanDissolveWithProofResponse{}, fmt.Errorf("Could not get can dissolve-with-proof status: %s", response.Error) + } + return response, nil +} + +// Dissolve a megapool validator with proof +func (c *Client) DissolveWithProof(validatorId uint64) (api.DissolveWithProofResponse, error) { + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/dissolve-with-proof", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) + if err != nil { + return api.DissolveWithProofResponse{}, fmt.Errorf("Could not dissolve megapool validator with proof: %w", err) + } + var response api.DissolveWithProofResponse + if err := json.Unmarshal(responseBytes, &response); err != nil { + return api.DissolveWithProofResponse{}, fmt.Errorf("Could not decode dissolve-with-proof response: %w", err) + } + if response.Error != "" { + return api.DissolveWithProofResponse{}, fmt.Errorf("Could not dissolve megapool validator with proof: %s", response.Error) + } + return response, nil +} + +// Check whether a megapool validator can be exited func (c *Client) CanExitValidator(validatorId uint64) (api.CanExitValidatorResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-exit-validator %d", validatorId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-exit-validator", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) if err != nil { return api.CanExitValidatorResponse{}, fmt.Errorf("Could not get can exit validator status: %w", err) } @@ -220,7 +256,7 @@ func (c *Client) CanExitValidator(validatorId uint64) (api.CanExitValidatorRespo // Exit a megapool validator func (c *Client) ExitValidator(validatorId uint64) (api.ExitValidatorResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool exit-validator %d", validatorId)) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/exit-validator", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) if err != nil { return api.ExitValidatorResponse{}, fmt.Errorf("Could not exit megapool validator: %w", err) } @@ -234,15 +270,15 @@ func (c *Client) ExitValidator(validatorId uint64) (api.ExitValidatorResponse, e return response, nil } -// Check whether we can notify a validator exit +// Check whether the node can notify validator exit func (c *Client) CanNotifyValidatorExit(validatorId uint64) (api.CanNotifyValidatorExitResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-notify-validator-exit %d", validatorId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-notify-validator-exit", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) if err != nil { return api.CanNotifyValidatorExitResponse{}, fmt.Errorf("Could not get can notify validator exit status: %w", err) } var response api.CanNotifyValidatorExitResponse if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.CanNotifyValidatorExitResponse{}, fmt.Errorf("Could not decode can notify-validator-exit response: %w", err) + return api.CanNotifyValidatorExitResponse{}, fmt.Errorf("Could not decode can notify validator exit response: %w", err) } if response.Error != "" { return api.CanNotifyValidatorExitResponse{}, fmt.Errorf("Could not get can notify validator exit status: %s", response.Error) @@ -250,57 +286,63 @@ func (c *Client) CanNotifyValidatorExit(validatorId uint64) (api.CanNotifyValida return response, nil } -// Notify exit of a megapool validator +// Notify the megapool that a validator has exited func (c *Client) NotifyValidatorExit(validatorId uint64) (api.NotifyValidatorExitResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool notify-validator-exit %d", validatorId)) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/notify-validator-exit", url.Values{"validatorId": {fmt.Sprintf("%d", validatorId)}}) if err != nil { return api.NotifyValidatorExitResponse{}, fmt.Errorf("Could not notify validator exit: %w", err) } var response api.NotifyValidatorExitResponse if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.NotifyValidatorExitResponse{}, fmt.Errorf("Could not decode notify-validator-exit response: %w", err) + return api.NotifyValidatorExitResponse{}, fmt.Errorf("Could not decode notify validator exit response: %w", err) } if response.Error != "" { - return api.NotifyValidatorExitResponse{}, fmt.Errorf("Could not get notify-validator-exit status: %s", response.Error) + return api.NotifyValidatorExitResponse{}, fmt.Errorf("Could not notify validator exit: %s", response.Error) } return response, nil } -// Check whether we can notify a validator's final balance +// Check whether the node can notify final balance func (c *Client) CanNotifyFinalBalance(validatorId uint64, slot uint64) (api.CanNotifyFinalBalanceResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-notify-final-balance %d %d", validatorId, slot)) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-notify-final-balance", url.Values{ + "validatorId": {fmt.Sprintf("%d", validatorId)}, + "slot": {fmt.Sprintf("%d", slot)}, + }) if err != nil { - return api.CanNotifyFinalBalanceResponse{}, fmt.Errorf("Could not get can notify validator final balance status: %w", err) + return api.CanNotifyFinalBalanceResponse{}, fmt.Errorf("Could not get can notify final balance status: %w", err) } var response api.CanNotifyFinalBalanceResponse if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.CanNotifyFinalBalanceResponse{}, fmt.Errorf("Could not decode can notify-final-balance response: %w", err) + return api.CanNotifyFinalBalanceResponse{}, fmt.Errorf("Could not decode can notify final balance response: %w", err) } if response.Error != "" { - return api.CanNotifyFinalBalanceResponse{}, fmt.Errorf("Could not get can notify validator final balance status: %s", response.Error) + return api.CanNotifyFinalBalanceResponse{}, fmt.Errorf("Could not get can notify final balance status: %s", response.Error) } return response, nil } -// Notify final balance of a megapool validator +// Notify the megapool of a validator's final balance func (c *Client) NotifyFinalBalance(validatorId uint64, slot uint64) (api.NotifyFinalBalanceResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool notify-final-balance %d %d", validatorId, slot)) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/notify-final-balance", url.Values{ + "validatorId": {fmt.Sprintf("%d", validatorId)}, + "slot": {fmt.Sprintf("%d", slot)}, + }) if err != nil { return api.NotifyFinalBalanceResponse{}, fmt.Errorf("Could not notify final balance: %w", err) } var response api.NotifyFinalBalanceResponse if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.NotifyFinalBalanceResponse{}, fmt.Errorf("Could not decode notify-final-balance response: %w", err) + return api.NotifyFinalBalanceResponse{}, fmt.Errorf("Could not decode notify final balance response: %w", err) } if response.Error != "" { - return api.NotifyFinalBalanceResponse{}, fmt.Errorf("Could not get notify-final-balance status: %s", response.Error) + return api.NotifyFinalBalanceResponse{}, fmt.Errorf("Could not notify final balance: %s", response.Error) } return response, nil } -// Check whether the node can exit the megapool queue +// Check whether the node can exit the validator queue func (c *Client) CanExitQueue(validatorIndex uint32) (api.CanExitQueueResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-exit-queue %d", validatorIndex)) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-exit-queue", url.Values{"validatorIndex": {fmt.Sprintf("%d", validatorIndex)}}) if err != nil { return api.CanExitQueueResponse{}, fmt.Errorf("Could not get can exit queue status: %w", err) } @@ -314,9 +356,9 @@ func (c *Client) CanExitQueue(validatorIndex uint32) (api.CanExitQueueResponse, return response, nil } -// Exit the megapool queue +// Exit the validator queue func (c *Client) ExitQueue(validatorIndex uint32) (api.ExitQueueResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool exit-queue %d", validatorIndex)) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/exit-queue", url.Values{"validatorIndex": {fmt.Sprintf("%d", validatorIndex)}}) if err != nil { return api.ExitQueueResponse{}, fmt.Errorf("Could not exit queue: %w", err) } @@ -332,7 +374,7 @@ func (c *Client) ExitQueue(validatorIndex uint32) (api.ExitQueueResponse, error) // Get the gas info for a megapool delegate upgrade func (c *Client) CanDelegateUpgradeMegapool(address common.Address) (api.MegapoolCanDelegateUpgradeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-delegate-upgrade %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-delegate-upgrade", url.Values{"address": {address.Hex()}}) if err != nil { return api.MegapoolCanDelegateUpgradeResponse{}, fmt.Errorf("Could not get can delegate upgrade megapool status: %w", err) } @@ -348,7 +390,7 @@ func (c *Client) CanDelegateUpgradeMegapool(address common.Address) (api.Megapoo // Upgrade the megapool delegate func (c *Client) DelegateUpgradeMegapool(address common.Address) (api.MegapoolDelegateUpgradeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool delegate-upgrade %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/delegate-upgrade", url.Values{"address": {address.Hex()}}) if err != nil { return api.MegapoolDelegateUpgradeResponse{}, fmt.Errorf("Could not upgrade megapool delegate: %w", err) } @@ -364,7 +406,7 @@ func (c *Client) DelegateUpgradeMegapool(address common.Address) (api.MegapoolDe // Get the megapool's use-latest-delegate setting func (c *Client) GetUseLatestDelegate(address common.Address) (api.MegapoolGetUseLatestDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool get-use-latest-delegate %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/get-use-latest-delegate", url.Values{"address": {address.Hex()}}) if err != nil { return api.MegapoolGetUseLatestDelegateResponse{}, fmt.Errorf("Could not get use latest delegate for megapool: %w", err) } @@ -380,7 +422,7 @@ func (c *Client) GetUseLatestDelegate(address common.Address) (api.MegapoolGetUs // Check whether a megapool can have its use-latest-delegate setting changed func (c *Client) CanSetUseLatestDelegateMegapool(address common.Address, setting bool) (api.MegapoolCanSetUseLatestDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool can-set-use-latest-delegate %s %t", address.Hex(), setting)) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-set-use-latest-delegate", url.Values{"address": {address.Hex()}}) if err != nil { return api.MegapoolCanSetUseLatestDelegateResponse{}, fmt.Errorf("Could not get can set use latest delegate for megapool status: %w", err) } @@ -396,7 +438,14 @@ func (c *Client) CanSetUseLatestDelegateMegapool(address common.Address, setting // Change a megapool's use-latest-delegate setting func (c *Client) SetUseLatestDelegateMegapool(address common.Address, setting bool) (api.MegapoolSetUseLatestDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool set-use-latest-delegate %s %t", address.Hex(), setting)) + settingStr := "false" + if setting { + settingStr = "true" + } + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/set-use-latest-delegate", url.Values{ + "address": {address.Hex()}, + "setting": {settingStr}, + }) if err != nil { return api.MegapoolSetUseLatestDelegateResponse{}, fmt.Errorf("Could not set use latest delegate for megapool: %w", err) } @@ -412,7 +461,7 @@ func (c *Client) SetUseLatestDelegateMegapool(address common.Address, setting bo // Get the megapool's delegate address func (c *Client) GetDelegate(address common.Address) (api.MegapoolGetDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool get-delegate %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/get-delegate", url.Values{"address": {address.Hex()}}) if err != nil { return api.MegapoolGetDelegateResponse{}, fmt.Errorf("Could get delegate for megapool: %w", err) } @@ -428,7 +477,7 @@ func (c *Client) GetDelegate(address common.Address) (api.MegapoolGetDelegateRes // Get the megapool's effective delegate address func (c *Client) GetEffectiveDelegate(address common.Address) (api.MegapoolGetEffectiveDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool get-effective-delegate %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/get-effective-delegate", url.Values{"address": {address.Hex()}}) if err != nil { return api.MegapoolGetEffectiveDelegateResponse{}, fmt.Errorf("Could get effective delegate for megapool: %w", err) } @@ -444,7 +493,7 @@ func (c *Client) GetEffectiveDelegate(address common.Address) (api.MegapoolGetEf // Calculate the megapool pending rewards func (c *Client) CalculatePendingRewards() (api.MegapoolRewardSplitResponse, error) { - responseBytes, err := c.callAPI("megapool pending-rewards") + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/pending-rewards", nil) if err != nil { return api.MegapoolRewardSplitResponse{}, fmt.Errorf("Could not get pending rewards: %w", err) } @@ -458,9 +507,9 @@ func (c *Client) CalculatePendingRewards() (api.MegapoolRewardSplitResponse, err return response, nil } -// Calculate Rewards split given an arbitrary amount +// Calculate rewards split given an arbitrary amount func (c *Client) CalculateRewards(amountWei *big.Int) (api.MegapoolRewardSplitResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("megapool calculate-rewards %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/calculate-rewards", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.MegapoolRewardSplitResponse{}, fmt.Errorf("Could not calculate rewards: %w", err) } @@ -471,13 +520,12 @@ func (c *Client) CalculateRewards(amountWei *big.Int) (api.MegapoolRewardSplitRe if response.Error != "" { return api.MegapoolRewardSplitResponse{}, fmt.Errorf("Could not get calculate rewards: %s", response.Error) } - return response, nil } // Check if the node can distribute megapool rewards func (c *Client) CanDistributeMegapool() (api.CanDistributeMegapoolResponse, error) { - responseBytes, err := c.callAPI("megapool can-distribute-megapool") + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-distribute", nil) if err != nil { return api.CanDistributeMegapoolResponse{}, fmt.Errorf("Could not get can-distribute-megapool response: %w", err) } @@ -493,7 +541,7 @@ func (c *Client) CanDistributeMegapool() (api.CanDistributeMegapoolResponse, err // Distribute megapool rewards func (c *Client) DistributeMegapool() (api.DistributeMegapoolResponse, error) { - responseBytes, err := c.callAPI("megapool distribute-megapool") + responseBytes, err := c.callHTTPAPI("POST", "/api/megapool/distribute", nil) if err != nil { return api.DistributeMegapoolResponse{}, fmt.Errorf("Could not get distribute-megapool response: %w", err) } @@ -509,7 +557,7 @@ func (c *Client) DistributeMegapool() (api.DistributeMegapoolResponse, error) { // Get the bond amount required for the megapool's next validator func (c *Client) GetNewValidatorBondRequirement() (api.GetNewValidatorBondRequirementResponse, error) { - responseBytes, err := c.callAPI("megapool get-new-validator-bond-requirement") + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/get-new-validator-bond-requirement", nil) if err != nil { return api.GetNewValidatorBondRequirementResponse{}, fmt.Errorf("Could not get new validator bond requirement: %w", err) } @@ -522,3 +570,7 @@ func (c *Client) GetNewValidatorBondRequirement() (api.GetNewValidatorBondRequir } return response, nil } + +// DissolveWithProof and CanDissolveWithProof client methods added above. +// CanDissolveWithProof / DissolveWithProof (also known as DissolveWithProof) are +// already implemented above. diff --git a/shared/services/rocketpool/security.go b/shared/services/rocketpool/security.go index 18a5a34bf..b7d721dc0 100644 --- a/shared/services/rocketpool/security.go +++ b/shared/services/rocketpool/security.go @@ -2,6 +2,7 @@ package rocketpool import ( "fmt" + "net/url" "strings" "github.com/ethereum/go-ethereum/common" @@ -11,7 +12,7 @@ import ( // Get security council status func (c *Client) SecurityStatus() (api.SecurityStatusResponse, error) { - responseBytes, err := c.callAPI("security status") + responseBytes, err := c.callHTTPAPI("GET", "/api/security/status", nil) if err != nil { return api.SecurityStatusResponse{}, fmt.Errorf("Could not get security council status: %w", err) } @@ -27,7 +28,7 @@ func (c *Client) SecurityStatus() (api.SecurityStatusResponse, error) { // Get the security council members func (c *Client) SecurityMembers() (api.SecurityMembersResponse, error) { - responseBytes, err := c.callAPI("security members") + responseBytes, err := c.callHTTPAPI("GET", "/api/security/members", nil) if err != nil { return api.SecurityMembersResponse{}, fmt.Errorf("Could not get security council members: %w", err) } @@ -43,7 +44,7 @@ func (c *Client) SecurityMembers() (api.SecurityMembersResponse, error) { // Get the security council proposals func (c *Client) SecurityProposals() (api.SecurityProposalsResponse, error) { - responseBytes, err := c.callAPI("security proposals") + responseBytes, err := c.callHTTPAPI("GET", "/api/security/proposals", nil) if err != nil { return api.SecurityProposalsResponse{}, fmt.Errorf("Could not get security council proposals: %w", err) } @@ -59,7 +60,7 @@ func (c *Client) SecurityProposals() (api.SecurityProposalsResponse, error) { // Get details of a proposal func (c *Client) SecurityProposal(id uint64) (api.SecurityProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security proposal-details %d", id)) + responseBytes, err := c.callHTTPAPI("GET", "/api/security/proposal-details", url.Values{"id": {fmt.Sprintf("%d", id)}}) if err != nil { return api.SecurityProposalResponse{}, fmt.Errorf("Could not get security council proposal: %w", err) } @@ -73,6 +74,9 @@ func (c *Client) SecurityProposal(id uint64) (api.SecurityProposalResponse, erro return response, nil } +// NOTE: ProposeInvite/ProposeKick/ProposeKickMulti/ProposeReplace do not have +// server-side handlers in the security API package; they remain on callAPI. + // Check whether the node can propose inviting a new member func (c *Client) SecurityCanProposeInvite(memberId string, memberAddress common.Address) (api.SecurityCanProposeInviteResponse, error) { responseBytes, err := c.callAPI("security can-propose-invite", memberId, memberAddress.Hex()) @@ -107,7 +111,7 @@ func (c *Client) SecurityProposeInvite(memberId string, memberAddress common.Add // Check whether the node can propose to leave the security council func (c *Client) SecurityProposeLeave() (api.SecurityProposeLeaveResponse, error) { - responseBytes, err := c.callAPI("security propose-leave") + responseBytes, err := c.callHTTPAPI("POST", "/api/security/propose-leave", nil) if err != nil { return api.SecurityProposeLeaveResponse{}, fmt.Errorf("Could not get security-propose-leave status: %w", err) } @@ -123,7 +127,7 @@ func (c *Client) SecurityProposeLeave() (api.SecurityProposeLeaveResponse, error // Check whether the node can propose leaving the security council func (c *Client) SecurityCanProposeLeave() (api.SecurityCanProposeLeaveResponse, error) { - responseBytes, err := c.callAPI("security can-propose-leave") + responseBytes, err := c.callHTTPAPI("GET", "/api/security/can-propose-leave", nil) if err != nil { return api.SecurityCanProposeLeaveResponse{}, fmt.Errorf("Could not get security-can-propose-leave status: %w", err) } @@ -175,7 +179,6 @@ func (c *Client) SecurityCanProposeKickMulti(addresses []common.Address) (api.Se for i, address := range addresses { addressStrings[i] = address.Hex() } - responseBytes, err := c.callAPI(fmt.Sprintf("security can-propose-kick-multi %s", strings.Join(addressStrings, ","))) if err != nil { return api.SecurityCanProposeKickMultiResponse{}, fmt.Errorf("Could not get security-can-propose-kick-multi status: %w", err) @@ -196,7 +199,6 @@ func (c *Client) SecurityProposeKickMulti(addresses []common.Address) (api.Secur for i, address := range addresses { addressStrings[i] = address.Hex() } - responseBytes, err := c.callAPI(fmt.Sprintf("security propose-kick-multi %s", strings.Join(addressStrings, ","))) if err != nil { return api.SecurityProposeKickMultiResponse{}, fmt.Errorf("Could not propose kicking multiple security council members: %w", err) @@ -211,7 +213,7 @@ func (c *Client) SecurityProposeKickMulti(addresses []common.Address) (api.Secur return response, nil } -// Check whether the node can propose replacing someone on the security council with another member +// Check whether the node can propose replacing someone on the security council func (c *Client) SecurityCanProposeReplace(existingAddress common.Address, newID string, newAddress common.Address) (api.SecurityCanProposeReplaceResponse, error) { responseBytes, err := c.callAPI(fmt.Sprintf("security can-propose-replace-member %s", existingAddress.Hex()), newID, newAddress.Hex()) if err != nil { @@ -219,7 +221,7 @@ func (c *Client) SecurityCanProposeReplace(existingAddress common.Address, newID } var response api.SecurityCanProposeReplaceResponse if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityCanProposeReplaceResponse{}, fmt.Errorf("Could not decode protocol DAO can-propose-replace-member-of-security-council response: %w", err) + return api.SecurityCanProposeReplaceResponse{}, fmt.Errorf("Could not decode security-can-propose-replace response: %w", err) } if response.Error != "" { return api.SecurityCanProposeReplaceResponse{}, fmt.Errorf("Could not get security-can-propose-replace status: %s", response.Error) @@ -227,7 +229,7 @@ func (c *Client) SecurityCanProposeReplace(existingAddress common.Address, newID return response, nil } -// Propose replacing someone on the security council with another member +// Propose replacing someone on the security council func (c *Client) SecurityProposeReplace(existingAddress common.Address, newID string, newAddress common.Address) (api.SecurityProposeReplaceResponse, error) { responseBytes, err := c.callAPI(fmt.Sprintf("security propose-replace-member %s", existingAddress.Hex()), newID, newAddress.Hex()) if err != nil { @@ -245,7 +247,7 @@ func (c *Client) SecurityProposeReplace(existingAddress common.Address, newID st // Check whether the node can cancel a proposal func (c *Client) SecurityCanCancelProposal(proposalId uint64) (api.SecurityCanCancelProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security can-cancel-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/security/can-cancel-proposal", url.Values{"id": {fmt.Sprintf("%d", proposalId)}}) if err != nil { return api.SecurityCanCancelProposalResponse{}, fmt.Errorf("Could not get security-can-cancel-proposal status: %w", err) } @@ -261,7 +263,7 @@ func (c *Client) SecurityCanCancelProposal(proposalId uint64) (api.SecurityCanCa // Cancel a proposal made by the node func (c *Client) SecurityCancelProposal(proposalId uint64) (api.SecurityCancelProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security cancel-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("POST", "/api/security/cancel-proposal", url.Values{"id": {fmt.Sprintf("%d", proposalId)}}) if err != nil { return api.SecurityCancelProposalResponse{}, fmt.Errorf("Could not cancel security council proposal: %w", err) } @@ -277,7 +279,7 @@ func (c *Client) SecurityCancelProposal(proposalId uint64) (api.SecurityCancelPr // Check whether the node can vote on a proposal func (c *Client) SecurityCanVoteOnProposal(proposalId uint64) (api.SecurityCanVoteOnProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security can-vote-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/security/can-vote-proposal", url.Values{"id": {fmt.Sprintf("%d", proposalId)}}) if err != nil { return api.SecurityCanVoteOnProposalResponse{}, fmt.Errorf("Could not get security-can-vote-on-proposal status: %w", err) } @@ -293,7 +295,14 @@ func (c *Client) SecurityCanVoteOnProposal(proposalId uint64) (api.SecurityCanVo // Vote on a proposal func (c *Client) SecurityVoteOnProposal(proposalId uint64, support bool) (api.SecurityVoteOnProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security vote-proposal %d %t", proposalId, support)) + supportStr := "false" + if support { + supportStr = "true" + } + responseBytes, err := c.callHTTPAPI("POST", "/api/security/vote-proposal", url.Values{ + "id": {fmt.Sprintf("%d", proposalId)}, + "support": {supportStr}, + }) if err != nil { return api.SecurityVoteOnProposalResponse{}, fmt.Errorf("Could not vote on security council proposal: %w", err) } @@ -309,7 +318,7 @@ func (c *Client) SecurityVoteOnProposal(proposalId uint64, support bool) (api.Se // Check whether the node can execute a proposal func (c *Client) SecurityCanExecuteProposal(proposalId uint64) (api.SecurityCanExecuteProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security can-execute-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/security/can-execute-proposal", url.Values{"id": {fmt.Sprintf("%d", proposalId)}}) if err != nil { return api.SecurityCanExecuteProposalResponse{}, fmt.Errorf("Could not get security-can-execute-proposal status: %w", err) } @@ -325,7 +334,7 @@ func (c *Client) SecurityCanExecuteProposal(proposalId uint64) (api.SecurityCanE // Execute a proposal func (c *Client) SecurityExecuteProposal(proposalId uint64) (api.SecurityExecuteProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security execute-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("POST", "/api/security/execute-proposal", url.Values{"id": {fmt.Sprintf("%d", proposalId)}}) if err != nil { return api.SecurityExecuteProposalResponse{}, fmt.Errorf("Could not execute security council proposal: %w", err) } @@ -341,7 +350,7 @@ func (c *Client) SecurityExecuteProposal(proposalId uint64) (api.SecurityExecute // Check whether the node can join the security council func (c *Client) SecurityCanJoin() (api.SecurityCanJoinResponse, error) { - responseBytes, err := c.callAPI("security can-join") + responseBytes, err := c.callHTTPAPI("GET", "/api/security/can-join", nil) if err != nil { return api.SecurityCanJoinResponse{}, fmt.Errorf("Could not get security-can-join status: %w", err) } @@ -357,7 +366,7 @@ func (c *Client) SecurityCanJoin() (api.SecurityCanJoinResponse, error) { // Join the security council (requires an executed invite proposal) func (c *Client) SecurityJoin() (api.SecurityJoinResponse, error) { - responseBytes, err := c.callAPI("security join") + responseBytes, err := c.callHTTPAPI("POST", "/api/security/join", nil) if err != nil { return api.SecurityJoinResponse{}, fmt.Errorf("Could not join security council: %w", err) } @@ -373,7 +382,7 @@ func (c *Client) SecurityJoin() (api.SecurityJoinResponse, error) { // Check whether the node can leave the security council func (c *Client) SecurityCanLeave() (api.SecurityCanLeaveResponse, error) { - responseBytes, err := c.callAPI("security can-leave") + responseBytes, err := c.callHTTPAPI("GET", "/api/security/can-leave", nil) if err != nil { return api.SecurityCanLeaveResponse{}, fmt.Errorf("Could not get security-can-leave status: %w", err) } @@ -389,7 +398,7 @@ func (c *Client) SecurityCanLeave() (api.SecurityCanLeaveResponse, error) { // Leave the security council (requires an executed leave proposal) func (c *Client) SecurityLeave() (api.SecurityLeaveResponse, error) { - responseBytes, err := c.callAPI("security leave") + responseBytes, err := c.callHTTPAPI("POST", "/api/security/leave", nil) if err != nil { return api.SecurityLeaveResponse{}, fmt.Errorf("Could not leave security council: %w", err) } @@ -405,7 +414,11 @@ func (c *Client) SecurityLeave() (api.SecurityLeaveResponse, error) { // Check whether the node can propose updating a PDAO setting func (c *Client) SecurityCanProposeSetting(contract string, setting string, value string) (api.SecurityCanProposeSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security can-propose-setting %s %s %s", contract, setting, value)) + responseBytes, err := c.callHTTPAPI("GET", "/api/security/can-propose-setting", url.Values{ + "contractName": {contract}, + "settingName": {setting}, + "value": {value}, + }) if err != nil { return api.SecurityCanProposeSettingResponse{}, fmt.Errorf("Could not get security-can-propose-setting: %w", err) } @@ -421,7 +434,11 @@ func (c *Client) SecurityCanProposeSetting(contract string, setting string, valu // Propose updating a PDAO setting func (c *Client) SecurityProposeSetting(contract string, setting string, value string) (api.SecurityProposeSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security propose-setting %s %s %s", contract, setting, value)) + responseBytes, err := c.callHTTPAPI("POST", "/api/security/propose-setting", url.Values{ + "contractName": {contract}, + "settingName": {setting}, + "value": {value}, + }) if err != nil { return api.SecurityProposeSettingResponse{}, fmt.Errorf("Could not propose security council setting: %w", err) } From 0c53a73aee4826a9399dfa135de813bbf66a7a02 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:18:17 -0300 Subject: [PATCH 05/24] Migrate minipool module to HTTP API Server side: - minipool/routes.go: RegisterRoutes() for all 31 minipool endpoints (status, refund, stake, promote, dissolve, exit, close, delegate-upgrade, set-use-latest-delegate, get-use-latest-delegate, get-delegate, get-effective-delegate, get-previous-delegate, get-vanity-artifacts, begin/can-begin/can-reduce/reduce-bond-amount, distribute-balance, import-key, change-withdrawal-creds, rescue-dissolved, get-bond-reduction-enabled) Client side: - minipool.go: all methods migrated to callHTTPAPI Co-authored-by: Cursor --- rocketpool/api/minipool/routes.go | 365 +++++++++++++++++++++++++ rocketpool/node/routes/routes.go | 2 + shared/services/rocketpool/minipool.go | 67 +++-- 3 files changed, 411 insertions(+), 23 deletions(-) create mode 100644 rocketpool/api/minipool/routes.go diff --git a/rocketpool/api/minipool/routes.go b/rocketpool/api/minipool/routes.go new file mode 100644 index 000000000..8edd3217a --- /dev/null +++ b/rocketpool/api/minipool/routes.go @@ -0,0 +1,365 @@ +package minipool + +import ( + "fmt" + "math/big" + "net/http" + + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the minipool module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/minipool/status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-refund", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canRefundMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/refund", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := refundMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-stake", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canStakeMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/stake", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := stakeMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-promote", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canPromoteMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/promote", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := promoteMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-dissolve", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canDissolveMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/dissolve", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := dissolveMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-exit", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canExitMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/exit", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := exitMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-minipool-close-details-for-node", func(w http.ResponseWriter, r *http.Request) { + resp, err := getMinipoolCloseDetailsForNode(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/close", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := closeMinipool(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-delegate-upgrade", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canDelegateUpgrade(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/delegate-upgrade", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := delegateUpgrade(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-set-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canSetUseLatestDelegate(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/set-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setUseLatestDelegate(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getUseLatestDelegate(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-delegate", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getDelegate(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-effective-delegate", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getEffectiveDelegate(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-previous-delegate", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getPreviousDelegate(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-vanity-artifacts", func(w http.ResponseWriter, r *http.Request) { + depositAmountStr := r.URL.Query().Get("depositAmount") + depositAmount, ok := new(big.Int).SetString(depositAmountStr, 10) + if !ok { + apiutils.WriteErrorResponse(w, fmt.Errorf("invalid depositAmount: %s", depositAmountStr)) + return + } + nodeAddressStr := r.URL.Query().Get("nodeAddress") + resp, err := getVanityArtifacts(c, depositAmount, nodeAddressStr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-begin-reduce-bond-amount", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + amountStr := r.URL.Query().Get("newBondAmountWei") + amount, ok := new(big.Int).SetString(amountStr, 10) + if !ok { + apiutils.WriteErrorResponse(w, fmt.Errorf("invalid newBondAmountWei: %s", amountStr)) + return + } + resp, err := canBeginReduceBondAmount(c, addr, amount) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/begin-reduce-bond-amount", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + amountStr := r.FormValue("newBondAmountWei") + amount, ok := new(big.Int).SetString(amountStr, 10) + if !ok { + apiutils.WriteErrorResponse(w, fmt.Errorf("invalid newBondAmountWei: %s", amountStr)) + return + } + resp, err := beginReduceBondAmount(c, addr, amount) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-reduce-bond-amount", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canReduceBondAmount(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/reduce-bond-amount", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := reduceBondAmount(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-distribute-balance-details", func(w http.ResponseWriter, r *http.Request) { + resp, err := getDistributeBalanceDetails(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/distribute-balance", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := distributeBalance(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/import-key", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + mnemonic := r.FormValue("mnemonic") + resp, err := importKey(c, addr, mnemonic) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/can-change-withdrawal-creds", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + mnemonic := r.URL.Query().Get("mnemonic") + resp, err := canChangeWithdrawalCreds(c, addr, mnemonic) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/change-withdrawal-creds", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + mnemonic := r.FormValue("mnemonic") + resp, err := changeWithdrawalCreds(c, addr, mnemonic) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-rescue-dissolved-details-for-node", func(w http.ResponseWriter, r *http.Request) { + resp, err := getMinipoolRescueDissolvedDetailsForNode(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/rescue-dissolved", func(w http.ResponseWriter, r *http.Request) { + addr, err := parseAddress(r, "address") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + amountStr := r.FormValue("amount") + amount, ok := new(big.Int).SetString(amountStr, 10) + if !ok { + apiutils.WriteErrorResponse(w, fmt.Errorf("invalid amount: %s", amountStr)) + return + } + submit := r.FormValue("submit") == "true" + resp, err := rescueDissolvedMinipool(c, addr, amount, submit) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/minipool/get-bond-reduction-enabled", func(w http.ResponseWriter, r *http.Request) { + resp, err := getBondReductionEnabled(c) + apiutils.WriteResponse(w, resp, err) + }) +} + +func parseAddress(r *http.Request, name string) (common.Address, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + if raw == "" { + return common.Address{}, fmt.Errorf("missing required parameter: %s", name) + } + return common.HexToAddress(raw), nil +} diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index 39b7feb47..ae9572f39 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -7,6 +7,7 @@ import ( auctionroutes "github.com/rocket-pool/smartnode/rocketpool/api/auction" megapoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/megapool" + minipoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/minipool" networkroutes "github.com/rocket-pool/smartnode/rocketpool/api/network" queueroutes "github.com/rocket-pool/smartnode/rocketpool/api/queue" securityroutes "github.com/rocket-pool/smartnode/rocketpool/api/security" @@ -23,6 +24,7 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { auctionroutes.RegisterRoutes(mux, c) megapoolroutes.RegisterRoutes(mux, c) + minipoolroutes.RegisterRoutes(mux, c) networkroutes.RegisterRoutes(mux, c) queueroutes.RegisterRoutes(mux, c) securityroutes.RegisterRoutes(mux, c) diff --git a/shared/services/rocketpool/minipool.go b/shared/services/rocketpool/minipool.go index 54e6bcbca..300e39355 100644 --- a/shared/services/rocketpool/minipool.go +++ b/shared/services/rocketpool/minipool.go @@ -3,6 +3,7 @@ package rocketpool import ( "fmt" "math/big" + "net/url" "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" @@ -12,7 +13,7 @@ import ( // Get minipool status func (c *Client) MinipoolStatus() (api.MinipoolStatusResponse, error) { - responseBytes, err := c.callAPI("minipool status") + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/status", nil) if err != nil { return api.MinipoolStatusResponse{}, fmt.Errorf("Could not get minipool status: %w", err) } @@ -58,7 +59,7 @@ func (c *Client) MinipoolStatus() (api.MinipoolStatusResponse, error) { // Check whether a minipool is eligible for a refund func (c *Client) CanRefundMinipool(address common.Address) (api.CanRefundMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool can-refund %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-refund", url.Values{"address": {address.Hex()}}) if err != nil { return api.CanRefundMinipoolResponse{}, fmt.Errorf("Could not get can refund minipool status: %w", err) } @@ -74,7 +75,7 @@ func (c *Client) CanRefundMinipool(address common.Address) (api.CanRefundMinipoo // Refund ETH from a minipool func (c *Client) RefundMinipool(address common.Address) (api.RefundMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool refund %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/refund", url.Values{"address": {address.Hex()}}) if err != nil { return api.RefundMinipoolResponse{}, fmt.Errorf("Could not refund minipool: %w", err) } @@ -90,7 +91,7 @@ func (c *Client) RefundMinipool(address common.Address) (api.RefundMinipoolRespo // Check whether a minipool is eligible for staking func (c *Client) CanStakeMinipool(address common.Address) (api.CanStakeMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool can-stake %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-stake", url.Values{"address": {address.Hex()}}) if err != nil { return api.CanStakeMinipoolResponse{}, fmt.Errorf("Could not get can stake minipool status: %w", err) } @@ -106,7 +107,7 @@ func (c *Client) CanStakeMinipool(address common.Address) (api.CanStakeMinipoolR // Stake a minipool func (c *Client) StakeMinipool(address common.Address) (api.StakeMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool stake %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/stake", url.Values{"address": {address.Hex()}}) if err != nil { return api.StakeMinipoolResponse{}, fmt.Errorf("Could not stake minipool: %w", err) } @@ -122,7 +123,7 @@ func (c *Client) StakeMinipool(address common.Address) (api.StakeMinipoolRespons // Check whether a minipool can be dissolved func (c *Client) CanDissolveMinipool(address common.Address) (api.CanDissolveMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool can-dissolve %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-dissolve", url.Values{"address": {address.Hex()}}) if err != nil { return api.CanDissolveMinipoolResponse{}, fmt.Errorf("Could not get can dissolve minipool status: %w", err) } @@ -138,7 +139,7 @@ func (c *Client) CanDissolveMinipool(address common.Address) (api.CanDissolveMin // Dissolve a minipool func (c *Client) DissolveMinipool(address common.Address) (api.DissolveMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool dissolve %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/dissolve", url.Values{"address": {address.Hex()}}) if err != nil { return api.DissolveMinipoolResponse{}, fmt.Errorf("Could not dissolve minipool: %w", err) } @@ -154,7 +155,7 @@ func (c *Client) DissolveMinipool(address common.Address) (api.DissolveMinipoolR // Check whether a minipool can be exited func (c *Client) CanExitMinipool(address common.Address) (api.CanExitMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool can-exit %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-exit", url.Values{"address": {address.Hex()}}) if err != nil { return api.CanExitMinipoolResponse{}, fmt.Errorf("Could not get can exit minipool status: %w", err) } @@ -170,7 +171,7 @@ func (c *Client) CanExitMinipool(address common.Address) (api.CanExitMinipoolRes // Exit a minipool func (c *Client) ExitMinipool(address common.Address) (api.ExitMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool exit %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/exit", url.Values{"address": {address.Hex()}}) if err != nil { return api.ExitMinipoolResponse{}, fmt.Errorf("Could not exit minipool: %w", err) } @@ -186,7 +187,7 @@ func (c *Client) ExitMinipool(address common.Address) (api.ExitMinipoolResponse, // Check all of the node's minipools for closure eligibility, and return the details of the closeable ones func (c *Client) GetMinipoolCloseDetailsForNode() (api.GetMinipoolCloseDetailsForNodeResponse, error) { - responseBytes, err := c.callAPI("minipool get-minipool-close-details-for-node") + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/get-minipool-close-details-for-node", nil) if err != nil { return api.GetMinipoolCloseDetailsForNodeResponse{}, fmt.Errorf("Could not get get-minipool-close-details-for-node status: %w", err) } @@ -202,7 +203,7 @@ func (c *Client) GetMinipoolCloseDetailsForNode() (api.GetMinipoolCloseDetailsFo // Close a minipool func (c *Client) CloseMinipool(address common.Address) (api.CloseMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool close %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/close", url.Values{"address": {address.Hex()}}) if err != nil { return api.CloseMinipoolResponse{}, fmt.Errorf("Could not close minipool: %w", err) } @@ -218,7 +219,7 @@ func (c *Client) CloseMinipool(address common.Address) (api.CloseMinipoolRespons // Check whether a minipool can have its delegate upgraded func (c *Client) CanDelegateUpgradeMinipool(address common.Address) (api.CanDelegateUpgradeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool can-delegate-upgrade %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-delegate-upgrade", url.Values{"address": {address.Hex()}}) if err != nil { return api.CanDelegateUpgradeResponse{}, fmt.Errorf("Could not get can delegate upgrade minipool status: %w", err) } @@ -234,7 +235,7 @@ func (c *Client) CanDelegateUpgradeMinipool(address common.Address) (api.CanDele // Upgrade a minipool delegate func (c *Client) DelegateUpgradeMinipool(address common.Address) (api.DelegateUpgradeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool delegate-upgrade %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/delegate-upgrade", url.Values{"address": {address.Hex()}}) if err != nil { return api.DelegateUpgradeResponse{}, fmt.Errorf("Could not upgrade delegate for minipool: %w", err) } @@ -250,7 +251,7 @@ func (c *Client) DelegateUpgradeMinipool(address common.Address) (api.DelegateUp // Check whether a minipool can have its auto-upgrade setting changed func (c *Client) CanSetUseLatestDelegateMinipool(address common.Address) (api.CanSetUseLatestDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool can-set-use-latest-delegate %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-set-use-latest-delegate", url.Values{"address": {address.Hex()}}) if err != nil { return api.CanSetUseLatestDelegateResponse{}, fmt.Errorf("Could not get can set use latest delegate for minipool status: %w", err) } @@ -266,7 +267,7 @@ func (c *Client) CanSetUseLatestDelegateMinipool(address common.Address) (api.Ca // Change a minipool's auto-upgrade setting func (c *Client) SetUseLatestDelegateMinipool(address common.Address) (api.SetUseLatestDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool set-use-latest-delegate %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/set-use-latest-delegate", url.Values{"address": {address.Hex()}}) if err != nil { return api.SetUseLatestDelegateResponse{}, fmt.Errorf("Could not set use latest delegate for minipool: %w", err) } @@ -282,7 +283,10 @@ func (c *Client) SetUseLatestDelegateMinipool(address common.Address) (api.SetUs // Get the artifacts necessary for vanity address searching func (c *Client) GetVanityArtifacts(depositAmount *big.Int, nodeAddress string) (api.GetVanityArtifactsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool get-vanity-artifacts %s %s", depositAmount.String(), nodeAddress)) + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/get-vanity-artifacts", url.Values{ + "depositAmount": {depositAmount.String()}, + "nodeAddress": {nodeAddress}, + }) if err != nil { return api.GetVanityArtifactsResponse{}, fmt.Errorf("Could not get vanity artifacts: %w", err) } @@ -298,7 +302,7 @@ func (c *Client) GetVanityArtifacts(depositAmount *big.Int, nodeAddress string) // Get the balance distribution details for all of the node's minipools func (c *Client) GetDistributeBalanceDetails() (api.GetDistributeBalanceDetailsResponse, error) { - responseBytes, err := c.callAPI("minipool get-distribute-balance-details") + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/get-distribute-balance-details", nil) if err != nil { return api.GetDistributeBalanceDetailsResponse{}, fmt.Errorf("Could not get distribute balance details: %w", err) } @@ -314,7 +318,7 @@ func (c *Client) GetDistributeBalanceDetails() (api.GetDistributeBalanceDetailsR // Distribute a minipool's ETH balance func (c *Client) DistributeBalance(address common.Address) (api.DistributeBalanceResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool distribute-balance %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/distribute-balance", url.Values{"address": {address.Hex()}}) if err != nil { return api.DistributeBalanceResponse{}, fmt.Errorf("Could not get distribute balance status: %w", err) } @@ -330,7 +334,10 @@ func (c *Client) DistributeBalance(address common.Address) (api.DistributeBalanc // Import a validator private key for a vacant minipool func (c *Client) ImportKey(address common.Address, mnemonic string) (api.ChangeWithdrawalCredentialsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool import-key %s", address.Hex()), mnemonic) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/import-key", url.Values{ + "address": {address.Hex()}, + "mnemonic": {mnemonic}, + }) if err != nil { return api.ChangeWithdrawalCredentialsResponse{}, fmt.Errorf("Could not import validator key: %w", err) } @@ -346,7 +353,10 @@ func (c *Client) ImportKey(address common.Address, mnemonic string) (api.ChangeW // Check whether a solo validator's withdrawal creds can be migrated to a minipool address func (c *Client) CanChangeWithdrawalCredentials(address common.Address, mnemonic string) (api.CanChangeWithdrawalCredentialsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool can-change-withdrawal-creds %s", address.Hex()), mnemonic) + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-change-withdrawal-creds", url.Values{ + "address": {address.Hex()}, + "mnemonic": {mnemonic}, + }) if err != nil { return api.CanChangeWithdrawalCredentialsResponse{}, fmt.Errorf("Could not get can-change-withdrawal-creds status: %w", err) } @@ -362,7 +372,10 @@ func (c *Client) CanChangeWithdrawalCredentials(address common.Address, mnemonic // Migrate a solo validator's withdrawal creds to a minipool address func (c *Client) ChangeWithdrawalCredentials(address common.Address, mnemonic string) (api.ChangeWithdrawalCredentialsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool change-withdrawal-creds %s", address.Hex()), mnemonic) + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/change-withdrawal-creds", url.Values{ + "address": {address.Hex()}, + "mnemonic": {mnemonic}, + }) if err != nil { return api.ChangeWithdrawalCredentialsResponse{}, fmt.Errorf("Could not change withdrawal creds: %w", err) } @@ -378,7 +391,7 @@ func (c *Client) ChangeWithdrawalCredentials(address common.Address, mnemonic st // Check all of the node's minipools for rescue eligibility, and return the details of the rescuable ones func (c *Client) GetMinipoolRescueDissolvedDetailsForNode() (api.GetMinipoolRescueDissolvedDetailsForNodeResponse, error) { - responseBytes, err := c.callAPI("minipool get-rescue-dissolved-details-for-node") + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/get-rescue-dissolved-details-for-node", nil) if err != nil { return api.GetMinipoolRescueDissolvedDetailsForNodeResponse{}, fmt.Errorf("Could not get get-minipool-rescue-dissolved-details-for-node status: %w", err) } @@ -394,7 +407,15 @@ func (c *Client) GetMinipoolRescueDissolvedDetailsForNode() (api.GetMinipoolResc // Rescue a dissolved minipool by depositing ETH for it to the Beacon deposit contract func (c *Client) RescueDissolvedMinipool(address common.Address, amount *big.Int, submit bool) (api.RescueDissolvedMinipoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("minipool rescue-dissolved %s %s %t", address.Hex(), amount.String(), submit)) + submitStr := "false" + if submit { + submitStr = "true" + } + responseBytes, err := c.callHTTPAPI("POST", "/api/minipool/rescue-dissolved", url.Values{ + "address": {address.Hex()}, + "amount": {amount.String()}, + "submit": {submitStr}, + }) if err != nil { return api.RescueDissolvedMinipoolResponse{}, fmt.Errorf("Could not rescue dissolved minipool: %w", err) } From 88629035b2048e19c6ba65721a9154c414c5ab21 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:27:35 -0300 Subject: [PATCH 06/24] Migrate odao and pdao modules to HTTP API Server side: - odao/routes.go: RegisterRoutes() for all odao endpoints (status, members, proposals, propose-invite, propose-leave, propose-kick, cancel/vote/execute-proposal, join, leave, member/proposal/minipool-settings, penalise-megapool, all propose-setting variants) Note: can-replace/replace have no server handlers; kept on callAPI - pdao/routes.go: RegisterRoutes() for all pdao endpoints (status, proposals, voting, settings, rewards-percentages, one-time-spend, recurring-spend, security-council operations, claimable-bonds, defeat/finalize-proposal, voting-delegate, signalling-address, allow-listed-controllers) Client side: - odao.go: all methods migrated to callHTTPAPI except CanReplaceTNDAOMember/ReplaceTNDAOMember/CanProposeReplaceTNDAOMember/ ProposeReplaceTNDAOMember (no server handlers) and CanProposeTNDAOSetting (no matching CLI command in odao) - pdao.go: all methods migrated to callHTTPAPI Co-authored-by: Cursor --- rocketpool/api/odao/routes.go | 575 +++++++++++++++++++++++++++ rocketpool/api/pdao/routes.go | 607 +++++++++++++++++++++++++++++ rocketpool/node/routes/routes.go | 4 + shared/services/rocketpool/odao.go | 182 ++++++--- shared/services/rocketpool/pdao.go | 239 +++++++++--- 5 files changed, 1490 insertions(+), 117 deletions(-) create mode 100644 rocketpool/api/odao/routes.go create mode 100644 rocketpool/api/pdao/routes.go diff --git a/rocketpool/api/odao/routes.go b/rocketpool/api/odao/routes.go new file mode 100644 index 000000000..52bc38f24 --- /dev/null +++ b/rocketpool/api/odao/routes.go @@ -0,0 +1,575 @@ +package odao + +import ( + "fmt" + "math/big" + "net/http" + "strconv" + + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the odao module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/odao/status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/members", func(w http.ResponseWriter, r *http.Request) { + resp, err := getMembers(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/proposals", func(w http.ResponseWriter, r *http.Request) { + resp, err := getProposals(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/proposal-details", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-invite", func(w http.ResponseWriter, r *http.Request) { + addr, memberId, memberUrl, err := parseInviteParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeInvite(c, addr, memberId, memberUrl) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-invite", func(w http.ResponseWriter, r *http.Request) { + addr, memberId, memberUrl, err := parseInviteParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeInvite(c, addr, memberId, memberUrl) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-leave", func(w http.ResponseWriter, r *http.Request) { + resp, err := canProposeLeave(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-leave", func(w http.ResponseWriter, r *http.Request) { + resp, err := proposeLeave(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-kick", func(w http.ResponseWriter, r *http.Request) { + addr, fine, err := parseKickParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeKick(c, addr, fine) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-kick", func(w http.ResponseWriter, r *http.Request) { + addr, fine, err := parseKickParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeKick(c, addr, fine) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-cancel-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canCancelProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/cancel-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := cancelProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-vote-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canVoteOnProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/vote-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + supportStr := r.FormValue("support") + support := supportStr == "true" + resp, err := voteOnProposal(c, id, support) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-execute-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canExecuteProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/execute-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := executeProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-join", func(w http.ResponseWriter, r *http.Request) { + resp, err := canJoin(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/join-approve-rpl", func(w http.ResponseWriter, r *http.Request) { + resp, err := approveRpl(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/join", func(w http.ResponseWriter, r *http.Request) { + hashStr := r.FormValue("approvalTxHash") + if hashStr == "" { + apiutils.WriteErrorResponse(w, fmt.Errorf("missing required parameter: approvalTxHash")) + return + } + hash := common.HexToHash(hashStr) + resp, err := waitForApprovalAndJoin(c, hash) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-leave", func(w http.ResponseWriter, r *http.Request) { + resp, err := canLeave(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/leave", func(w http.ResponseWriter, r *http.Request) { + bondRefundStr := r.FormValue("bondRefundAddress") + if bondRefundStr == "" { + apiutils.WriteErrorResponse(w, fmt.Errorf("missing required parameter: bondRefundAddress")) + return + } + resp, err := leave(c, common.HexToAddress(bondRefundStr)) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/get-member-settings", func(w http.ResponseWriter, r *http.Request) { + resp, err := getMemberSettings(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/get-proposal-settings", func(w http.ResponseWriter, r *http.Request) { + resp, err := getProposalSettings(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/get-minipool-settings", func(w http.ResponseWriter, r *http.Request) { + resp, err := getMinipoolSettings(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-penalise-megapool", func(w http.ResponseWriter, r *http.Request) { + megapool, block, amount, err := parsePenaliseParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canPenaliseMegapool(c, megapool, block, amount) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/penalise-megapool", func(w http.ResponseWriter, r *http.Request) { + megapool, block, amount, err := parsePenaliseParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := penaliseMegapool(c, megapool, block, amount) + apiutils.WriteResponse(w, resp, err) + }) + + // propose-settings endpoints + mux.HandleFunc("/api/odao/can-propose-members-quorum", func(w http.ResponseWriter, r *http.Request) { + quorum, err := parseFloat64(r, "quorum") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingMembersQuorum(c, quorum) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-members-quorum", func(w http.ResponseWriter, r *http.Request) { + quorum, err := parseFloat64(r, "quorum") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingMembersQuorum(c, quorum) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-members-rplbond", func(w http.ResponseWriter, r *http.Request) { + bond, err := parseBigInt(r, "bondAmountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingMembersRplBond(c, bond) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-members-rplbond", func(w http.ResponseWriter, r *http.Request) { + bond, err := parseBigInt(r, "bondAmountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingMembersRplBond(c, bond) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-members-minipool-unbonded-max", func(w http.ResponseWriter, r *http.Request) { + max, err := parseUint64(r, "max") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingMinipoolUnbondedMax(c, max) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-members-minipool-unbonded-max", func(w http.ResponseWriter, r *http.Request) { + max, err := parseUint64(r, "max") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingMinipoolUnbondedMax(c, max) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-proposal-cooldown", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingProposalCooldown(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-proposal-cooldown", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalCooldown(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-proposal-vote-timespan", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingProposalVoteTimespan(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-proposal-vote-timespan", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalVoteTimespan(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-proposal-vote-delay-timespan", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingProposalVoteDelayTimespan(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-proposal-vote-delay-timespan", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalVoteDelayTimespan(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-proposal-execute-timespan", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingProposalExecuteTimespan(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-proposal-execute-timespan", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalExecuteTimespan(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-proposal-action-timespan", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingProposalActionTimespan(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-proposal-action-timespan", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalActionTimespan(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-scrub-period", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingScrubPeriod(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-scrub-period", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingScrubPeriod(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-promotion-scrub-period", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingPromotionScrubPeriod(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-promotion-scrub-period", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingPromotionScrubPeriod(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-scrub-penalty-enabled", func(w http.ResponseWriter, r *http.Request) { + enabledStr := r.URL.Query().Get("enabled") + resp, err := canProposeSettingScrubPenaltyEnabled(c, enabledStr == "true") + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-scrub-penalty-enabled", func(w http.ResponseWriter, r *http.Request) { + enabledStr := r.FormValue("enabled") + resp, err := proposeSettingScrubPenaltyEnabled(c, enabledStr == "true") + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-bond-reduction-window-start", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingBondReductionWindowStart(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-bond-reduction-window-start", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingBondReductionWindowStart(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/can-propose-bond-reduction-window-length", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeSettingBondReductionWindowLength(c, val) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/odao/propose-bond-reduction-window-length", func(w http.ResponseWriter, r *http.Request) { + val, err := parseUint64(r, "value") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingBondReductionWindowLength(c, val) + apiutils.WriteResponse(w, resp, err) + }) +} + +func parseUint64(r *http.Request, name string) (uint64, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + val, err := strconv.ParseUint(raw, 10, 64) + if err != nil { + return 0, fmt.Errorf("invalid %s: %s", name, raw) + } + return val, nil +} + +func parseFloat64(r *http.Request, name string) (float64, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + val, err := strconv.ParseFloat(raw, 64) + if err != nil { + return 0, fmt.Errorf("invalid %s: %s", name, raw) + } + return val, nil +} + +func parseBigInt(r *http.Request, name string) (*big.Int, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + val, ok := new(big.Int).SetString(raw, 10) + if !ok { + return nil, fmt.Errorf("invalid %s: %s", name, raw) + } + return val, nil +} + +func parseInviteParams(r *http.Request) (common.Address, string, string, error) { + addrStr := r.URL.Query().Get("address") + if addrStr == "" { + addrStr = r.FormValue("address") + } + if addrStr == "" { + return common.Address{}, "", "", fmt.Errorf("missing required parameter: address") + } + memberId := r.URL.Query().Get("memberId") + if memberId == "" { + memberId = r.FormValue("memberId") + } + memberUrl := r.URL.Query().Get("memberUrl") + if memberUrl == "" { + memberUrl = r.FormValue("memberUrl") + } + return common.HexToAddress(addrStr), memberId, memberUrl, nil +} + +func parseKickParams(r *http.Request) (common.Address, *big.Int, error) { + addrStr := r.URL.Query().Get("address") + if addrStr == "" { + addrStr = r.FormValue("address") + } + if addrStr == "" { + return common.Address{}, nil, fmt.Errorf("missing required parameter: address") + } + fineStr := r.URL.Query().Get("fineAmountWei") + if fineStr == "" { + fineStr = r.FormValue("fineAmountWei") + } + fine, ok := new(big.Int).SetString(fineStr, 10) + if !ok { + return common.Address{}, nil, fmt.Errorf("invalid fineAmountWei: %s", fineStr) + } + return common.HexToAddress(addrStr), fine, nil +} + +func parsePenaliseParams(r *http.Request) (common.Address, *big.Int, *big.Int, error) { + addrStr := r.URL.Query().Get("megapoolAddress") + if addrStr == "" { + addrStr = r.FormValue("megapoolAddress") + } + blockStr := r.URL.Query().Get("block") + if blockStr == "" { + blockStr = r.FormValue("block") + } + amountStr := r.URL.Query().Get("amountWei") + if amountStr == "" { + amountStr = r.FormValue("amountWei") + } + block, ok := new(big.Int).SetString(blockStr, 10) + if !ok { + return common.Address{}, nil, nil, fmt.Errorf("invalid block: %s", blockStr) + } + amount, ok := new(big.Int).SetString(amountStr, 10) + if !ok { + return common.Address{}, nil, nil, fmt.Errorf("invalid amountWei: %s", amountStr) + } + return common.HexToAddress(addrStr), block, amount, nil +} diff --git a/rocketpool/api/pdao/routes.go b/rocketpool/api/pdao/routes.go new file mode 100644 index 000000000..6825c5d10 --- /dev/null +++ b/rocketpool/api/pdao/routes.go @@ -0,0 +1,607 @@ +package pdao + +import ( + "fmt" + "math/big" + "net/http" + "strconv" + "strings" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli" + + bindtypes "github.com/rocket-pool/smartnode/bindings/types" + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" + cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" +) + +// RegisterRoutes registers the pdao module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/pdao/status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/proposals", func(w http.ResponseWriter, r *http.Request) { + resp, err := getProposals(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/proposal-details", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64Param(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-vote-proposal", func(w http.ResponseWriter, r *http.Request) { + id, voteDir, err := parseProposalVoteParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canVoteOnProposal(c, id, voteDir) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/vote-proposal", func(w http.ResponseWriter, r *http.Request) { + id, voteDir, err := parseProposalVoteParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := voteOnProposal(c, id, voteDir) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-override-vote", func(w http.ResponseWriter, r *http.Request) { + id, voteDir, err := parseProposalVoteParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canOverrideVote(c, id, voteDir) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/override-vote", func(w http.ResponseWriter, r *http.Request) { + id, voteDir, err := parseProposalVoteParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := overrideVote(c, id, voteDir) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-execute-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64Param(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canExecuteProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/execute-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64Param(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := executeProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/get-settings", func(w http.ResponseWriter, r *http.Request) { + resp, err := getSettings(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-setting", func(w http.ResponseWriter, r *http.Request) { + contract := paramVal(r, "contract") + setting := paramVal(r, "setting") + value := paramVal(r, "value") + resp, err := canProposeSetting(c, contract, setting, value) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-setting", func(w http.ResponseWriter, r *http.Request) { + contract := paramVal(r, "contract") + setting := paramVal(r, "setting") + value := paramVal(r, "value") + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSetting(c, contract, setting, value, blockNumber) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/get-rewards-percentages", func(w http.ResponseWriter, r *http.Request) { + resp, err := getRewardsPercentages(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-rewards-percentages", func(w http.ResponseWriter, r *http.Request) { + node, odaoAmt, pdaoAmt, err := parseRewardPercentages(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeRewardsPercentages(c, node, odaoAmt, pdaoAmt) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-rewards-percentages", func(w http.ResponseWriter, r *http.Request) { + node, odaoAmt, pdaoAmt, err := parseRewardPercentages(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeRewardsPercentages(c, node, odaoAmt, pdaoAmt, blockNumber) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-one-time-spend", func(w http.ResponseWriter, r *http.Request) { + invoiceID, recipient, amount, customMessage, err := parseOneTimeSpendParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeOneTimeSpend(c, invoiceID, recipient, amount, customMessage) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-one-time-spend", func(w http.ResponseWriter, r *http.Request) { + invoiceID, recipient, amount, customMessage, err := parseOneTimeSpendParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeOneTimeSpend(c, invoiceID, recipient, amount, blockNumber, customMessage) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-recurring-spend", func(w http.ResponseWriter, r *http.Request) { + contractName, recipient, amountPerPeriod, periodLength, startTime, numberOfPeriods, customMessage, err := parseRecurringSpendParams(r, false) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeRecurringSpend(c, contractName, recipient, amountPerPeriod, periodLength, startTime, numberOfPeriods, customMessage) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-recurring-spend", func(w http.ResponseWriter, r *http.Request) { + contractName, recipient, amountPerPeriod, periodLength, startTime, numberOfPeriods, customMessage, err := parseRecurringSpendParams(r, false) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeRecurringSpend(c, contractName, recipient, amountPerPeriod, periodLength, startTime, numberOfPeriods, blockNumber, customMessage) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-recurring-spend-update", func(w http.ResponseWriter, r *http.Request) { + contractName, recipient, amountPerPeriod, periodLength, _, numberOfPeriods, customMessage, err := parseRecurringSpendParams(r, true) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeRecurringSpendUpdate(c, contractName, recipient, amountPerPeriod, periodLength, numberOfPeriods, customMessage) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-recurring-spend-update", func(w http.ResponseWriter, r *http.Request) { + contractName, recipient, amountPerPeriod, periodLength, _, numberOfPeriods, customMessage, err := parseRecurringSpendParams(r, true) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeRecurringSpendUpdate(c, contractName, recipient, amountPerPeriod, periodLength, numberOfPeriods, blockNumber, customMessage) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-invite-to-security-council", func(w http.ResponseWriter, r *http.Request) { + id := paramVal(r, "id") + addr := common.HexToAddress(paramVal(r, "address")) + resp, err := canProposeInviteToSecurityCouncil(c, id, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-invite-to-security-council", func(w http.ResponseWriter, r *http.Request) { + id := paramVal(r, "id") + addr := common.HexToAddress(paramVal(r, "address")) + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeInviteToSecurityCouncil(c, id, addr, blockNumber) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-kick-from-security-council", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(paramVal(r, "address")) + resp, err := canProposeKickFromSecurityCouncil(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-kick-from-security-council", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(paramVal(r, "address")) + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeKickFromSecurityCouncil(c, addr, blockNumber) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-kick-multi-from-security-council", func(w http.ResponseWriter, r *http.Request) { + addresses, err := parseAddressList(r, "addresses") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canProposeKickMultiFromSecurityCouncil(c, addresses) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-kick-multi-from-security-council", func(w http.ResponseWriter, r *http.Request) { + addresses, err := parseAddressList(r, "addresses") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeKickMultiFromSecurityCouncil(c, addresses, blockNumber) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-replace-member-of-security-council", func(w http.ResponseWriter, r *http.Request) { + existing := common.HexToAddress(paramVal(r, "existingAddress")) + newID := paramVal(r, "newId") + newAddr := common.HexToAddress(paramVal(r, "newAddress")) + resp, err := canProposeReplaceMemberOfSecurityCouncil(c, existing, newID, newAddr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-replace-member-of-security-council", func(w http.ResponseWriter, r *http.Request) { + existing := common.HexToAddress(paramVal(r, "existingAddress")) + newID := paramVal(r, "newId") + newAddr := common.HexToAddress(paramVal(r, "newAddress")) + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeReplaceMemberOfSecurityCouncil(c, existing, newID, newAddr, blockNumber) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/get-claimable-bonds", func(w http.ResponseWriter, r *http.Request) { + resp, err := getClaimableBonds(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-claim-bonds", func(w http.ResponseWriter, r *http.Request) { + proposalID, indices, err := parseClaimBondsParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canClaimBonds(c, proposalID, indices) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/claim-bonds", func(w http.ResponseWriter, r *http.Request) { + proposalID, indices, err := parseClaimBondsParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + isProposer := paramVal(r, "isProposer") == "true" + resp, err := claimBonds(c, isProposer, proposalID, indices) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-defeat-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64Param(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + index, err := parseUint64Param(r, "index") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canDefeatProposal(c, id, index) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/defeat-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64Param(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + index, err := parseUint64Param(r, "index") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := defeatProposal(c, id, index) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-finalize-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64Param(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canFinalizeProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/finalize-proposal", func(w http.ResponseWriter, r *http.Request) { + id, err := parseUint64Param(r, "id") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := finalizeProposal(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/estimate-set-voting-delegate-gas", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(paramVal(r, "address")) + resp, err := estimateSetVotingDelegateGas(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/set-voting-delegate", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(paramVal(r, "address")) + resp, err := setVotingDelegate(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/get-current-voting-delegate", func(w http.ResponseWriter, r *http.Request) { + resp, err := getCurrentVotingDelegate(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-set-signalling-address", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(paramVal(r, "address")) + sig := paramVal(r, "signature") + resp, err := canSetSignallingAddress(c, addr, sig) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/set-signalling-address", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(paramVal(r, "address")) + sig := paramVal(r, "signature") + resp, err := setSignallingAddress(c, addr, sig) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-clear-signalling-address", func(w http.ResponseWriter, r *http.Request) { + resp, err := canClearSignallingAddress(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/clear-signalling-address", func(w http.ResponseWriter, r *http.Request) { + resp, err := clearSignallingAddress(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/can-propose-allow-listed-controllers", func(w http.ResponseWriter, r *http.Request) { + addressList := paramVal(r, "addressList") + addresses, err := parseAddressList(r, "addressList") + if err != nil { + // Fall back to the raw comma-separated string if address parsing fails + addresses = parseRawAddressList(addressList) + } + resp, err := canProposeAllowListedControllers(c, addresses) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/pdao/propose-allow-listed-controllers", func(w http.ResponseWriter, r *http.Request) { + addressList := paramVal(r, "addressList") + addresses, err := parseAddressList(r, "addressList") + if err != nil { + addresses = parseRawAddressList(addressList) + } + blockNumber, err := parseUint32Param(r, "blockNumber") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeAllowListedControllers(c, addresses, blockNumber) + apiutils.WriteResponse(w, resp, err) + }) +} + +func paramVal(r *http.Request, name string) string { + v := r.URL.Query().Get(name) + if v == "" { + v = r.FormValue(name) + } + return v +} + +func parseUint64Param(r *http.Request, name string) (uint64, error) { + raw := paramVal(r, name) + val, err := strconv.ParseUint(raw, 10, 64) + if err != nil { + return 0, fmt.Errorf("invalid %s: %s", name, raw) + } + return val, nil +} + +func parseUint32Param(r *http.Request, name string) (uint32, error) { + raw := paramVal(r, name) + val, err := strconv.ParseUint(raw, 10, 32) + if err != nil { + return 0, fmt.Errorf("invalid %s: %s", name, raw) + } + return uint32(val), nil +} + +func parseProposalVoteParams(r *http.Request) (uint64, bindtypes.VoteDirection, error) { + id, err := parseUint64Param(r, "id") + if err != nil { + return 0, 0, err + } + dirStr := paramVal(r, "voteDirection") + dir, err := cliutils.ValidateVoteDirection("voteDirection", dirStr) + if err != nil { + return 0, 0, err + } + return id, dir, nil +} + +func parseRewardPercentages(r *http.Request) (*big.Int, *big.Int, *big.Int, error) { + nodeStr := paramVal(r, "node") + odaoStr := paramVal(r, "odao") + pdaoStr := paramVal(r, "pdao") + + node, ok := new(big.Int).SetString(nodeStr, 10) + if !ok { + return nil, nil, nil, fmt.Errorf("invalid node percentage: %s", nodeStr) + } + odaoAmt, ok := new(big.Int).SetString(odaoStr, 10) + if !ok { + return nil, nil, nil, fmt.Errorf("invalid odao percentage: %s", odaoStr) + } + pdaoAmt, ok := new(big.Int).SetString(pdaoStr, 10) + if !ok { + return nil, nil, nil, fmt.Errorf("invalid pdao percentage: %s", pdaoStr) + } + return node, odaoAmt, pdaoAmt, nil +} + +func parseOneTimeSpendParams(r *http.Request) (string, common.Address, *big.Int, string, error) { + invoiceID := paramVal(r, "invoiceId") + recipient := common.HexToAddress(paramVal(r, "recipient")) + amountStr := paramVal(r, "amount") + amount, ok := new(big.Int).SetString(amountStr, 10) + if !ok { + return "", common.Address{}, nil, "", fmt.Errorf("invalid amount: %s", amountStr) + } + customMessage := paramVal(r, "customMessage") + return invoiceID, recipient, amount, customMessage, nil +} + +// parseRecurringSpendParams parses recurring spend parameters. +// If skipStartTime is true, the startTime is omitted (for update operations). +func parseRecurringSpendParams(r *http.Request, skipStartTime bool) (string, common.Address, *big.Int, time.Duration, time.Time, uint64, string, error) { + contractName := paramVal(r, "contractName") + recipient := common.HexToAddress(paramVal(r, "recipient")) + + amountStr := paramVal(r, "amountPerPeriod") + amount, ok := new(big.Int).SetString(amountStr, 10) + if !ok { + return "", common.Address{}, nil, 0, time.Time{}, 0, "", fmt.Errorf("invalid amountPerPeriod: %s", amountStr) + } + + periodLengthStr := paramVal(r, "periodLength") + periodLength, err := time.ParseDuration(periodLengthStr) + if err != nil { + return "", common.Address{}, nil, 0, time.Time{}, 0, "", fmt.Errorf("invalid periodLength: %s", periodLengthStr) + } + + var startTime time.Time + if !skipStartTime { + startTimeStr := paramVal(r, "startTime") + startTimeUnix, err := strconv.ParseInt(startTimeStr, 10, 64) + if err != nil { + return "", common.Address{}, nil, 0, time.Time{}, 0, "", fmt.Errorf("invalid startTime: %s", startTimeStr) + } + startTime = time.Unix(startTimeUnix, 0) + } + + numberOfPeriodsStr := paramVal(r, "numberOfPeriods") + numberOfPeriods, err := strconv.ParseUint(numberOfPeriodsStr, 10, 64) + if err != nil { + return "", common.Address{}, nil, 0, time.Time{}, 0, "", fmt.Errorf("invalid numberOfPeriods: %s", numberOfPeriodsStr) + } + + customMessage := paramVal(r, "customMessage") + return contractName, recipient, amount, periodLength, startTime, numberOfPeriods, customMessage, nil +} + +func parseAddressList(r *http.Request, name string) ([]common.Address, error) { + raw := paramVal(r, name) + if raw == "" { + return nil, fmt.Errorf("missing required parameter: %s", name) + } + return parseRawAddressList(raw), nil +} + +func parseRawAddressList(raw string) []common.Address { + parts := strings.Split(raw, ",") + addresses := make([]common.Address, 0, len(parts)) + for _, p := range parts { + p = strings.TrimSpace(p) + if p != "" { + addresses = append(addresses, common.HexToAddress(p)) + } + } + return addresses +} + +func parseClaimBondsParams(r *http.Request) (uint64, []uint64, error) { + proposalID, err := parseUint64Param(r, "proposalId") + if err != nil { + return 0, nil, err + } + indicesStr := paramVal(r, "indices") + parts := strings.Split(indicesStr, ",") + indices := make([]uint64, 0, len(parts)) + for _, p := range parts { + p = strings.TrimSpace(p) + if p == "" { + continue + } + idx, err := strconv.ParseUint(p, 10, 64) + if err != nil { + return 0, nil, fmt.Errorf("invalid index: %s", p) + } + indices = append(indices, idx) + } + return proposalID, indices, nil +} diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index ae9572f39..50e312d50 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -9,6 +9,8 @@ import ( megapoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/megapool" minipoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/minipool" networkroutes "github.com/rocket-pool/smartnode/rocketpool/api/network" + odaoroutes "github.com/rocket-pool/smartnode/rocketpool/api/odao" + pdaoroutes "github.com/rocket-pool/smartnode/rocketpool/api/pdao" queueroutes "github.com/rocket-pool/smartnode/rocketpool/api/queue" securityroutes "github.com/rocket-pool/smartnode/rocketpool/api/security" serviceroutes "github.com/rocket-pool/smartnode/rocketpool/api/service" @@ -26,6 +28,8 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { megapoolroutes.RegisterRoutes(mux, c) minipoolroutes.RegisterRoutes(mux, c) networkroutes.RegisterRoutes(mux, c) + odaoroutes.RegisterRoutes(mux, c) + pdaoroutes.RegisterRoutes(mux, c) queueroutes.RegisterRoutes(mux, c) securityroutes.RegisterRoutes(mux, c) serviceroutes.RegisterRoutes(mux, c) diff --git a/shared/services/rocketpool/odao.go b/shared/services/rocketpool/odao.go index 37934877b..757296487 100644 --- a/shared/services/rocketpool/odao.go +++ b/shared/services/rocketpool/odao.go @@ -3,6 +3,7 @@ package rocketpool import ( "fmt" "math/big" + "net/url" "strconv" "github.com/ethereum/go-ethereum/common" @@ -13,7 +14,7 @@ import ( // Get oracle DAO status func (c *Client) TNDAOStatus() (api.TNDAOStatusResponse, error) { - responseBytes, err := c.callAPI("odao status") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/status", nil) if err != nil { return api.TNDAOStatusResponse{}, fmt.Errorf("Could not get oracle DAO status: %w", err) } @@ -29,7 +30,7 @@ func (c *Client) TNDAOStatus() (api.TNDAOStatusResponse, error) { // Get oracle DAO members func (c *Client) TNDAOMembers() (api.TNDAOMembersResponse, error) { - responseBytes, err := c.callAPI("odao members") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/members", nil) if err != nil { return api.TNDAOMembersResponse{}, fmt.Errorf("Could not get oracle DAO members: %w", err) } @@ -51,7 +52,7 @@ func (c *Client) TNDAOMembers() (api.TNDAOMembersResponse, error) { // Get oracle DAO proposals func (c *Client) TNDAOProposals() (api.TNDAOProposalsResponse, error) { - responseBytes, err := c.callAPI("odao proposals") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/proposals", nil) if err != nil { return api.TNDAOProposalsResponse{}, fmt.Errorf("Could not get oracle DAO proposals: %w", err) } @@ -67,7 +68,7 @@ func (c *Client) TNDAOProposals() (api.TNDAOProposalsResponse, error) { // Get a single oracle DAO proposal func (c *Client) TNDAOProposal(id uint64) (api.TNDAOProposalResponse, error) { - responseBytes, err := c.callAPI("odao proposal-details", strconv.FormatUint(id, 10)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/proposal-details", url.Values{"id": {strconv.FormatUint(id, 10)}}) if err != nil { return api.TNDAOProposalResponse{}, fmt.Errorf("Could not get oracle DAO proposal: %w", err) } @@ -83,7 +84,11 @@ func (c *Client) TNDAOProposal(id uint64) (api.TNDAOProposalResponse, error) { // Check whether the node can propose inviting a new member func (c *Client) CanProposeInviteToTNDAO(memberAddress common.Address, memberId, memberUrl string) (api.CanProposeTNDAOInviteResponse, error) { - responseBytes, err := c.callAPI("odao can-propose-invite", memberAddress.Hex(), memberId, memberUrl) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-invite", url.Values{ + "address": {memberAddress.Hex()}, + "memberId": {memberId}, + "memberUrl": {memberUrl}, + }) if err != nil { return api.CanProposeTNDAOInviteResponse{}, fmt.Errorf("Could not get can propose oracle DAO invite status: %w", err) } @@ -99,7 +104,11 @@ func (c *Client) CanProposeInviteToTNDAO(memberAddress common.Address, memberId, // Propose inviting a new member func (c *Client) ProposeInviteToTNDAO(memberAddress common.Address, memberId, memberUrl string) (api.ProposeTNDAOInviteResponse, error) { - responseBytes, err := c.callAPI("odao propose-invite", memberAddress.Hex(), memberId, memberUrl) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-invite", url.Values{ + "address": {memberAddress.Hex()}, + "memberId": {memberId}, + "memberUrl": {memberUrl}, + }) if err != nil { return api.ProposeTNDAOInviteResponse{}, fmt.Errorf("Could not propose oracle DAO invite: %w", err) } @@ -115,7 +124,7 @@ func (c *Client) ProposeInviteToTNDAO(memberAddress common.Address, memberId, me // Check whether the node can propose leaving the oracle DAO func (c *Client) CanProposeLeaveTNDAO() (api.CanProposeTNDAOLeaveResponse, error) { - responseBytes, err := c.callAPI("odao can-propose-leave") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-leave", nil) if err != nil { return api.CanProposeTNDAOLeaveResponse{}, fmt.Errorf("Could not get can propose leaving oracle DAO status: %w", err) } @@ -131,7 +140,7 @@ func (c *Client) CanProposeLeaveTNDAO() (api.CanProposeTNDAOLeaveResponse, error // Propose leaving the oracle DAO func (c *Client) ProposeLeaveTNDAO() (api.ProposeTNDAOLeaveResponse, error) { - responseBytes, err := c.callAPI("odao propose-leave") + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-leave", nil) if err != nil { return api.ProposeTNDAOLeaveResponse{}, fmt.Errorf("Could not propose leaving oracle DAO: %w", err) } @@ -146,6 +155,7 @@ func (c *Client) ProposeLeaveTNDAO() (api.ProposeTNDAOLeaveResponse, error) { } // Check whether the node can propose replacing its position with a new member +// No server-side handler exists for this command; kept on callAPI. func (c *Client) CanProposeReplaceTNDAOMember(memberAddress common.Address, memberId, memberUrl string) (api.CanProposeTNDAOReplaceResponse, error) { responseBytes, err := c.callAPI("odao can-propose-replace", memberAddress.Hex(), memberId, memberUrl) if err != nil { @@ -162,6 +172,7 @@ func (c *Client) CanProposeReplaceTNDAOMember(memberAddress common.Address, memb } // Propose replacing the node's position with a new member +// No server-side handler exists for this command; kept on callAPI. func (c *Client) ProposeReplaceTNDAOMember(memberAddress common.Address, memberId, memberUrl string) (api.ProposeTNDAOReplaceResponse, error) { responseBytes, err := c.callAPI("odao propose-replace", memberAddress.Hex(), memberId, memberUrl) if err != nil { @@ -179,7 +190,10 @@ func (c *Client) ProposeReplaceTNDAOMember(memberAddress common.Address, memberI // Check whether the node can propose kicking a member func (c *Client) CanProposeKickFromTNDAO(memberAddress common.Address, fineAmountWei *big.Int) (api.CanProposeTNDAOKickResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-kick %s %s", memberAddress.Hex(), fineAmountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-kick", url.Values{ + "address": {memberAddress.Hex()}, + "fineAmountWei": {fineAmountWei.String()}, + }) if err != nil { return api.CanProposeTNDAOKickResponse{}, fmt.Errorf("Could not get can propose kicking oracle DAO member status: %w", err) } @@ -195,7 +209,10 @@ func (c *Client) CanProposeKickFromTNDAO(memberAddress common.Address, fineAmoun // Propose kicking a member func (c *Client) ProposeKickFromTNDAO(memberAddress common.Address, fineAmountWei *big.Int) (api.ProposeTNDAOKickResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-kick %s %s", memberAddress.Hex(), fineAmountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-kick", url.Values{ + "address": {memberAddress.Hex()}, + "fineAmountWei": {fineAmountWei.String()}, + }) if err != nil { return api.ProposeTNDAOKickResponse{}, fmt.Errorf("Could not propose kicking oracle DAO member: %w", err) } @@ -211,7 +228,7 @@ func (c *Client) ProposeKickFromTNDAO(memberAddress common.Address, fineAmountWe // Check whether the node can cancel a proposal func (c *Client) CanCancelTNDAOProposal(proposalId uint64) (api.CanCancelTNDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-cancel-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-cancel-proposal", url.Values{"id": {strconv.FormatUint(proposalId, 10)}}) if err != nil { return api.CanCancelTNDAOProposalResponse{}, fmt.Errorf("Could not get can cancel oracle DAO proposal status: %w", err) } @@ -227,7 +244,7 @@ func (c *Client) CanCancelTNDAOProposal(proposalId uint64) (api.CanCancelTNDAOPr // Cancel a proposal made by the node func (c *Client) CancelTNDAOProposal(proposalId uint64) (api.CancelTNDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao cancel-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/cancel-proposal", url.Values{"id": {strconv.FormatUint(proposalId, 10)}}) if err != nil { return api.CancelTNDAOProposalResponse{}, fmt.Errorf("Could not cancel oracle DAO proposal: %w", err) } @@ -243,7 +260,7 @@ func (c *Client) CancelTNDAOProposal(proposalId uint64) (api.CancelTNDAOProposal // Check whether the node can vote on a proposal func (c *Client) CanVoteOnTNDAOProposal(proposalId uint64) (api.CanVoteOnTNDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-vote-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-vote-proposal", url.Values{"id": {strconv.FormatUint(proposalId, 10)}}) if err != nil { return api.CanVoteOnTNDAOProposalResponse{}, fmt.Errorf("Could not get can vote on oracle DAO proposal status: %w", err) } @@ -259,7 +276,14 @@ func (c *Client) CanVoteOnTNDAOProposal(proposalId uint64) (api.CanVoteOnTNDAOPr // Vote on a proposal func (c *Client) VoteOnTNDAOProposal(proposalId uint64, support bool) (api.VoteOnTNDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao vote-proposal %d %t", proposalId, support)) + supportStr := "false" + if support { + supportStr = "true" + } + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/vote-proposal", url.Values{ + "id": {strconv.FormatUint(proposalId, 10)}, + "support": {supportStr}, + }) if err != nil { return api.VoteOnTNDAOProposalResponse{}, fmt.Errorf("Could not vote on oracle DAO proposal: %w", err) } @@ -275,7 +299,7 @@ func (c *Client) VoteOnTNDAOProposal(proposalId uint64, support bool) (api.VoteO // Check whether the node can execute a proposal func (c *Client) CanExecuteTNDAOProposal(proposalId uint64) (api.CanExecuteTNDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-execute-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-execute-proposal", url.Values{"id": {strconv.FormatUint(proposalId, 10)}}) if err != nil { return api.CanExecuteTNDAOProposalResponse{}, fmt.Errorf("Could not get can execute oracle DAO proposal status: %w", err) } @@ -291,7 +315,7 @@ func (c *Client) CanExecuteTNDAOProposal(proposalId uint64) (api.CanExecuteTNDAO // Execute a proposal func (c *Client) ExecuteTNDAOProposal(proposalId uint64) (api.ExecuteTNDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao execute-proposal %d", proposalId)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/execute-proposal", url.Values{"id": {strconv.FormatUint(proposalId, 10)}}) if err != nil { return api.ExecuteTNDAOProposalResponse{}, fmt.Errorf("Could not execute oracle DAO proposal: %w", err) } @@ -307,7 +331,7 @@ func (c *Client) ExecuteTNDAOProposal(proposalId uint64) (api.ExecuteTNDAOPropos // Check whether the node can join the oracle DAO func (c *Client) CanJoinTNDAO() (api.CanJoinTNDAOResponse, error) { - responseBytes, err := c.callAPI("odao can-join") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-join", nil) if err != nil { return api.CanJoinTNDAOResponse{}, fmt.Errorf("Could not get can join oracle DAO status: %w", err) } @@ -321,9 +345,9 @@ func (c *Client) CanJoinTNDAO() (api.CanJoinTNDAOResponse, error) { return response, nil } -// Join the oracle DAO (requires an executed invite proposal) +// Approve RPL for joining the oracle DAO func (c *Client) ApproveRPLToJoinTNDAO() (api.JoinTNDAOApproveResponse, error) { - responseBytes, err := c.callAPI("odao join-approve-rpl") + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/join-approve-rpl", nil) if err != nil { return api.JoinTNDAOApproveResponse{}, fmt.Errorf("Could not approve RPL for joining oracle DAO: %w", err) } @@ -339,7 +363,7 @@ func (c *Client) ApproveRPLToJoinTNDAO() (api.JoinTNDAOApproveResponse, error) { // Join the oracle DAO (requires an executed invite proposal) func (c *Client) JoinTNDAO(approvalTxHash common.Hash) (api.JoinTNDAOJoinResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao join %s", approvalTxHash.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/join", url.Values{"approvalTxHash": {approvalTxHash.String()}}) if err != nil { return api.JoinTNDAOJoinResponse{}, fmt.Errorf("Could not join oracle DAO: %w", err) } @@ -355,7 +379,7 @@ func (c *Client) JoinTNDAO(approvalTxHash common.Hash) (api.JoinTNDAOJoinRespons // Check whether the node can leave the oracle DAO func (c *Client) CanLeaveTNDAO() (api.CanLeaveTNDAOResponse, error) { - responseBytes, err := c.callAPI("odao can-leave") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-leave", nil) if err != nil { return api.CanLeaveTNDAOResponse{}, fmt.Errorf("Could not get can leave oracle DAO status: %w", err) } @@ -371,7 +395,7 @@ func (c *Client) CanLeaveTNDAO() (api.CanLeaveTNDAOResponse, error) { // Leave the oracle DAO (requires an executed leave proposal) func (c *Client) LeaveTNDAO(bondRefundAddress common.Address) (api.LeaveTNDAOResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao leave %s", bondRefundAddress.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/leave", url.Values{"bondRefundAddress": {bondRefundAddress.Hex()}}) if err != nil { return api.LeaveTNDAOResponse{}, fmt.Errorf("Could not leave oracle DAO: %w", err) } @@ -386,6 +410,7 @@ func (c *Client) LeaveTNDAO(bondRefundAddress common.Address) (api.LeaveTNDAORes } // Check whether the node can replace its position in the oracle DAO +// No server-side handler exists for this command; kept on callAPI. func (c *Client) CanReplaceTNDAOMember() (api.CanReplaceTNDAOPositionResponse, error) { responseBytes, err := c.callAPI("odao can-replace") if err != nil { @@ -402,6 +427,7 @@ func (c *Client) CanReplaceTNDAOMember() (api.CanReplaceTNDAOPositionResponse, e } // Replace the node's position in the oracle DAO (requires an executed replace proposal) +// No server-side handler exists for this command; kept on callAPI. func (c *Client) ReplaceTNDAOMember() (api.ReplaceTNDAOPositionResponse, error) { responseBytes, err := c.callAPI("odao replace") if err != nil { @@ -417,7 +443,8 @@ func (c *Client) ReplaceTNDAOMember() (api.ReplaceTNDAOPositionResponse, error) return response, nil } -// Check whether the node can propose a setting update +// Check whether the node can propose a setting update (generic) +// No server-side handler for the no-argument "can-propose-setting" command; kept on callAPI. func (c *Client) CanProposeTNDAOSetting() (api.CanProposeTNDAOSettingResponse, error) { responseBytes, err := c.callAPI("odao can-propose-setting") if err != nil { @@ -432,8 +459,9 @@ func (c *Client) CanProposeTNDAOSetting() (api.CanProposeTNDAOSettingResponse, e } return response, nil } + func (c *Client) CanProposeTNDAOSettingMembersQuorum(quorum float64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-members-quorum %f", quorum)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-members-quorum", url.Values{"quorum": {strconv.FormatFloat(quorum, 'f', -1, 64)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting members.quorum: %w", err) } @@ -446,8 +474,9 @@ func (c *Client) CanProposeTNDAOSettingMembersQuorum(quorum float64) (api.CanPro } return response, nil } + func (c *Client) CanProposeTNDAOSettingMembersRplBond(bondAmountWei *big.Int) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-members-rplbond %s", bondAmountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-members-rplbond", url.Values{"bondAmountWei": {bondAmountWei.String()}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting members.rplbond: %w", err) } @@ -460,8 +489,9 @@ func (c *Client) CanProposeTNDAOSettingMembersRplBond(bondAmountWei *big.Int) (a } return response, nil } + func (c *Client) CanProposeTNDAOSettingMinipoolUnbondedMax(unbondedMinipoolMax uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-members-minipool-unbonded-max %d", unbondedMinipoolMax)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-members-minipool-unbonded-max", url.Values{"max": {strconv.FormatUint(unbondedMinipoolMax, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting members.minipool.unbonded.max: %w", err) } @@ -474,8 +504,9 @@ func (c *Client) CanProposeTNDAOSettingMinipoolUnbondedMax(unbondedMinipoolMax u } return response, nil } + func (c *Client) CanProposeTNDAOSettingProposalCooldown(proposalCooldownTimespan uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-proposal-cooldown %d", proposalCooldownTimespan)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-proposal-cooldown", url.Values{"value": {strconv.FormatUint(proposalCooldownTimespan, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting proposal.cooldown.time: %w", err) } @@ -488,8 +519,9 @@ func (c *Client) CanProposeTNDAOSettingProposalCooldown(proposalCooldownTimespan } return response, nil } + func (c *Client) CanProposeTNDAOSettingProposalVoteTimespan(proposalVoteTimespan uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-proposal-vote-timespan %d", proposalVoteTimespan)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-proposal-vote-timespan", url.Values{"value": {strconv.FormatUint(proposalVoteTimespan, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting proposal.vote.time: %w", err) } @@ -502,8 +534,9 @@ func (c *Client) CanProposeTNDAOSettingProposalVoteTimespan(proposalVoteTimespan } return response, nil } + func (c *Client) CanProposeTNDAOSettingProposalVoteDelayTimespan(proposalDelayTimespan uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-proposal-vote-delay-timespan %d", proposalDelayTimespan)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-proposal-vote-delay-timespan", url.Values{"value": {strconv.FormatUint(proposalDelayTimespan, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting proposal.vote.delay.time: %w", err) } @@ -516,8 +549,9 @@ func (c *Client) CanProposeTNDAOSettingProposalVoteDelayTimespan(proposalDelayTi } return response, nil } + func (c *Client) CanProposeTNDAOSettingProposalExecuteTimespan(proposalExecuteTimespan uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-proposal-execute-timespan %d", proposalExecuteTimespan)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-proposal-execute-timespan", url.Values{"value": {strconv.FormatUint(proposalExecuteTimespan, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting proposal.execute.time: %w", err) } @@ -530,8 +564,9 @@ func (c *Client) CanProposeTNDAOSettingProposalExecuteTimespan(proposalExecuteTi } return response, nil } + func (c *Client) CanProposeTNDAOSettingProposalActionTimespan(proposalActionTimespan uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-proposal-action-timespan %d", proposalActionTimespan)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-proposal-action-timespan", url.Values{"value": {strconv.FormatUint(proposalActionTimespan, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting proposal.action.time: %w", err) } @@ -544,8 +579,9 @@ func (c *Client) CanProposeTNDAOSettingProposalActionTimespan(proposalActionTime } return response, nil } + func (c *Client) CanProposeTNDAOSettingScrubPeriod(scrubPeriod uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-scrub-period %d", scrubPeriod)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-scrub-period", url.Values{"value": {strconv.FormatUint(scrubPeriod, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting minipool.scrub.period: %w", err) } @@ -558,8 +594,9 @@ func (c *Client) CanProposeTNDAOSettingScrubPeriod(scrubPeriod uint64) (api.CanP } return response, nil } + func (c *Client) CanProposeTNDAOSettingPromotionScrubPeriod(scrubPeriod uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-promotion-scrub-period %d", scrubPeriod)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-promotion-scrub-period", url.Values{"value": {strconv.FormatUint(scrubPeriod, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting minipool.promotion.scrub.period: %w", err) } @@ -572,8 +609,13 @@ func (c *Client) CanProposeTNDAOSettingPromotionScrubPeriod(scrubPeriod uint64) } return response, nil } + func (c *Client) CanProposeTNDAOSettingScrubPenaltyEnabled(enabled bool) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-scrub-penalty-enabled %t", enabled)) + enabledStr := "false" + if enabled { + enabledStr = "true" + } + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-scrub-penalty-enabled", url.Values{"enabled": {enabledStr}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting minipool.scrub.penalty.enabled: %w", err) } @@ -586,8 +628,9 @@ func (c *Client) CanProposeTNDAOSettingScrubPenaltyEnabled(enabled bool) (api.Ca } return response, nil } + func (c *Client) CanProposeTNDAOSettingBondReductionWindowStart(windowStart uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-bond-reduction-window-start %d", windowStart)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-bond-reduction-window-start", url.Values{"value": {strconv.FormatUint(windowStart, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting minipool.bond.reduction.window.start: %w", err) } @@ -600,8 +643,9 @@ func (c *Client) CanProposeTNDAOSettingBondReductionWindowStart(windowStart uint } return response, nil } + func (c *Client) CanProposeTNDAOSettingBondReductionWindowLength(windowLength uint64) (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-propose-bond-reduction-window-length %d", windowLength)) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-bond-reduction-window-length", url.Values{"value": {strconv.FormatUint(windowLength, 10)}}) if err != nil { return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting minipool.bond.reduction.window.length: %w", err) } @@ -617,7 +661,7 @@ func (c *Client) CanProposeTNDAOSettingBondReductionWindowLength(windowLength ui // Propose a setting update func (c *Client) ProposeTNDAOSettingMembersQuorum(quorum float64) (api.ProposeTNDAOSettingMembersQuorumResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-members-quorum %f", quorum)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-members-quorum", url.Values{"quorum": {strconv.FormatFloat(quorum, 'f', -1, 64)}}) if err != nil { return api.ProposeTNDAOSettingMembersQuorumResponse{}, fmt.Errorf("Could not propose oracle DAO setting members.quorum: %w", err) } @@ -630,8 +674,9 @@ func (c *Client) ProposeTNDAOSettingMembersQuorum(quorum float64) (api.ProposeTN } return response, nil } + func (c *Client) ProposeTNDAOSettingMembersRplBond(bondAmountWei *big.Int) (api.ProposeTNDAOSettingMembersRplBondResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-members-rplbond %s", bondAmountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-members-rplbond", url.Values{"bondAmountWei": {bondAmountWei.String()}}) if err != nil { return api.ProposeTNDAOSettingMembersRplBondResponse{}, fmt.Errorf("Could not propose oracle DAO setting members.rplbond: %w", err) } @@ -644,8 +689,9 @@ func (c *Client) ProposeTNDAOSettingMembersRplBond(bondAmountWei *big.Int) (api. } return response, nil } + func (c *Client) ProposeTNDAOSettingMinipoolUnbondedMax(unbondedMinipoolMax uint64) (api.ProposeTNDAOSettingMinipoolUnbondedMaxResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-members-minipool-unbonded-max %d", unbondedMinipoolMax)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-members-minipool-unbonded-max", url.Values{"max": {strconv.FormatUint(unbondedMinipoolMax, 10)}}) if err != nil { return api.ProposeTNDAOSettingMinipoolUnbondedMaxResponse{}, fmt.Errorf("Could not propose oracle DAO setting members.minipool.unbonded.max: %w", err) } @@ -658,8 +704,9 @@ func (c *Client) ProposeTNDAOSettingMinipoolUnbondedMax(unbondedMinipoolMax uint } return response, nil } + func (c *Client) ProposeTNDAOSettingProposalCooldown(proposalCooldownTimespan uint64) (api.ProposeTNDAOSettingProposalCooldownResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-proposal-cooldown %d", proposalCooldownTimespan)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-proposal-cooldown", url.Values{"value": {strconv.FormatUint(proposalCooldownTimespan, 10)}}) if err != nil { return api.ProposeTNDAOSettingProposalCooldownResponse{}, fmt.Errorf("Could not propose oracle DAO setting proposal.cooldown.time: %w", err) } @@ -672,8 +719,9 @@ func (c *Client) ProposeTNDAOSettingProposalCooldown(proposalCooldownTimespan ui } return response, nil } + func (c *Client) ProposeTNDAOSettingProposalVoteTimespan(proposalVoteTimespan uint64) (api.ProposeTNDAOSettingProposalVoteTimespanResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-proposal-vote-timespan %d", proposalVoteTimespan)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-proposal-vote-timespan", url.Values{"value": {strconv.FormatUint(proposalVoteTimespan, 10)}}) if err != nil { return api.ProposeTNDAOSettingProposalVoteTimespanResponse{}, fmt.Errorf("Could not propose oracle DAO setting proposal.vote.time: %w", err) } @@ -686,8 +734,9 @@ func (c *Client) ProposeTNDAOSettingProposalVoteTimespan(proposalVoteTimespan ui } return response, nil } + func (c *Client) ProposeTNDAOSettingProposalVoteDelayTimespan(proposalDelayTimespan uint64) (api.ProposeTNDAOSettingProposalVoteDelayTimespanResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-proposal-vote-delay-timespan %d", proposalDelayTimespan)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-proposal-vote-delay-timespan", url.Values{"value": {strconv.FormatUint(proposalDelayTimespan, 10)}}) if err != nil { return api.ProposeTNDAOSettingProposalVoteDelayTimespanResponse{}, fmt.Errorf("Could not propose oracle DAO setting proposal.vote.delay.time: %w", err) } @@ -700,8 +749,9 @@ func (c *Client) ProposeTNDAOSettingProposalVoteDelayTimespan(proposalDelayTimes } return response, nil } + func (c *Client) ProposeTNDAOSettingProposalExecuteTimespan(proposalExecuteTimespan uint64) (api.ProposeTNDAOSettingProposalExecuteTimespanResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-proposal-execute-timespan %d", proposalExecuteTimespan)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-proposal-execute-timespan", url.Values{"value": {strconv.FormatUint(proposalExecuteTimespan, 10)}}) if err != nil { return api.ProposeTNDAOSettingProposalExecuteTimespanResponse{}, fmt.Errorf("Could not propose oracle DAO setting proposal.execute.time: %w", err) } @@ -714,8 +764,9 @@ func (c *Client) ProposeTNDAOSettingProposalExecuteTimespan(proposalExecuteTimes } return response, nil } + func (c *Client) ProposeTNDAOSettingProposalActionTimespan(proposalActionTimespan uint64) (api.ProposeTNDAOSettingProposalActionTimespanResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-proposal-action-timespan %d", proposalActionTimespan)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-proposal-action-timespan", url.Values{"value": {strconv.FormatUint(proposalActionTimespan, 10)}}) if err != nil { return api.ProposeTNDAOSettingProposalActionTimespanResponse{}, fmt.Errorf("Could not propose oracle DAO setting proposal.action.time: %w", err) } @@ -728,8 +779,9 @@ func (c *Client) ProposeTNDAOSettingProposalActionTimespan(proposalActionTimespa } return response, nil } + func (c *Client) ProposeTNDAOSettingScrubPeriod(scrubPeriod uint64) (api.ProposeTNDAOSettingScrubPeriodResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-scrub-period %d", scrubPeriod)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-scrub-period", url.Values{"value": {strconv.FormatUint(scrubPeriod, 10)}}) if err != nil { return api.ProposeTNDAOSettingScrubPeriodResponse{}, fmt.Errorf("Could not propose oracle DAO setting minipool.scrub.period: %w", err) } @@ -742,8 +794,9 @@ func (c *Client) ProposeTNDAOSettingScrubPeriod(scrubPeriod uint64) (api.Propose } return response, nil } + func (c *Client) ProposeTNDAOSettingPromotionScrubPeriod(scrubPeriod uint64) (api.ProposeTNDAOSettingPromotionScrubPeriodResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-promotion-scrub-period %d", scrubPeriod)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-promotion-scrub-period", url.Values{"value": {strconv.FormatUint(scrubPeriod, 10)}}) if err != nil { return api.ProposeTNDAOSettingPromotionScrubPeriodResponse{}, fmt.Errorf("Could not propose oracle DAO setting minipool.promotion.scrub.period: %w", err) } @@ -756,8 +809,13 @@ func (c *Client) ProposeTNDAOSettingPromotionScrubPeriod(scrubPeriod uint64) (ap } return response, nil } + func (c *Client) ProposeTNDAOSettingScrubPenaltyEnabled(enabled bool) (api.ProposeTNDAOSettingScrubPenaltyEnabledResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-scrub-penalty-enabled %t", enabled)) + enabledStr := "false" + if enabled { + enabledStr = "true" + } + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-scrub-penalty-enabled", url.Values{"enabled": {enabledStr}}) if err != nil { return api.ProposeTNDAOSettingScrubPenaltyEnabledResponse{}, fmt.Errorf("Could not propose oracle DAO setting minipool.scrub.penalty.enabled: %w", err) } @@ -770,8 +828,9 @@ func (c *Client) ProposeTNDAOSettingScrubPenaltyEnabled(enabled bool) (api.Propo } return response, nil } + func (c *Client) ProposeTNDAOSettingBondReductionWindowStart(windowStart uint64) (api.ProposeTNDAOSettingBondReductionWindowStartResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-bond-reduction-window-start %d", windowStart)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-bond-reduction-window-start", url.Values{"value": {strconv.FormatUint(windowStart, 10)}}) if err != nil { return api.ProposeTNDAOSettingBondReductionWindowStartResponse{}, fmt.Errorf("Could not propose oracle DAO setting minipool.bond.reduction.window.start: %w", err) } @@ -784,8 +843,9 @@ func (c *Client) ProposeTNDAOSettingBondReductionWindowStart(windowStart uint64) } return response, nil } + func (c *Client) ProposeTNDAOSettingBondReductionWindowLength(windowLength uint64) (api.ProposeTNDAOSettingBondReductionWindowLengthResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao propose-bond-reduction-window-length %d", windowLength)) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-bond-reduction-window-length", url.Values{"value": {strconv.FormatUint(windowLength, 10)}}) if err != nil { return api.ProposeTNDAOSettingBondReductionWindowLengthResponse{}, fmt.Errorf("Could not propose oracle DAO setting minipool.bond.reduction.window.length: %w", err) } @@ -801,7 +861,7 @@ func (c *Client) ProposeTNDAOSettingBondReductionWindowLength(windowLength uint6 // Get the member settings func (c *Client) GetTNDAOMemberSettings() (api.GetTNDAOMemberSettingsResponse, error) { - responseBytes, err := c.callAPI("odao get-member-settings") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/get-member-settings", nil) if err != nil { return api.GetTNDAOMemberSettingsResponse{}, fmt.Errorf("Could not get oracle DAO member settings: %w", err) } @@ -823,7 +883,7 @@ func (c *Client) GetTNDAOMemberSettings() (api.GetTNDAOMemberSettingsResponse, e // Get the proposal settings func (c *Client) GetTNDAOProposalSettings() (api.GetTNDAOProposalSettingsResponse, error) { - responseBytes, err := c.callAPI("odao get-proposal-settings") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/get-proposal-settings", nil) if err != nil { return api.GetTNDAOProposalSettingsResponse{}, fmt.Errorf("Could not get oracle DAO proposal settings: %w", err) } @@ -837,9 +897,9 @@ func (c *Client) GetTNDAOProposalSettings() (api.GetTNDAOProposalSettingsRespons return response, nil } -// Get the proposal settings +// Get the minipool settings func (c *Client) GetTNDAOMinipoolSettings() (api.GetTNDAOMinipoolSettingsResponse, error) { - responseBytes, err := c.callAPI("odao get-minipool-settings") + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/get-minipool-settings", nil) if err != nil { return api.GetTNDAOMinipoolSettingsResponse{}, fmt.Errorf("Could not get oracle DAO minipool settings: %w", err) } @@ -855,7 +915,11 @@ func (c *Client) GetTNDAOMinipoolSettings() (api.GetTNDAOMinipoolSettingsRespons // Check whether the node can penalise a megapool func (c *Client) CanPenaliseMegapool(megapoolAddress common.Address, block *big.Int, amountWei *big.Int) (api.CanPenaliseMegapoolResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao can-penalise-megapool %s %s %s", megapoolAddress.String(), block.String(), amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-penalise-megapool", url.Values{ + "megapoolAddress": {megapoolAddress.Hex()}, + "block": {block.String()}, + "amountWei": {amountWei.String()}, + }) if err != nil { return api.CanPenaliseMegapoolResponse{}, fmt.Errorf("Could not get can penalise megapool status: %w", err) } @@ -871,16 +935,20 @@ func (c *Client) CanPenaliseMegapool(megapoolAddress common.Address, block *big. // Penalise a megapool func (c *Client) PenaliseMegapool(megapoolAddress common.Address, block *big.Int, amountWei *big.Int) (api.RepayDebtResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("odao penalise-megapool %s %s %s", megapoolAddress.String(), block.String(), amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/odao/penalise-megapool", url.Values{ + "megapoolAddress": {megapoolAddress.Hex()}, + "block": {block.String()}, + "amountWei": {amountWei.String()}, + }) if err != nil { - return api.RepayDebtResponse{}, fmt.Errorf("Could not penalise megapool : %w", err) + return api.RepayDebtResponse{}, fmt.Errorf("Could not penalise megapool: %w", err) } var response api.RepayDebtResponse if err := json.Unmarshal(responseBytes, &response); err != nil { return api.RepayDebtResponse{}, fmt.Errorf("Could not decode penalise megapool response: %w", err) } if response.Error != "" { - return api.RepayDebtResponse{}, fmt.Errorf("Could not penalise megapool : %s", response.Error) + return api.RepayDebtResponse{}, fmt.Errorf("Could not penalise megapool: %s", response.Error) } return response, nil } diff --git a/shared/services/rocketpool/pdao.go b/shared/services/rocketpool/pdao.go index 2f5eed4d3..7854690ff 100644 --- a/shared/services/rocketpool/pdao.go +++ b/shared/services/rocketpool/pdao.go @@ -3,6 +3,8 @@ package rocketpool import ( "fmt" "math/big" + "net/url" + "strconv" "strings" "time" @@ -29,7 +31,7 @@ func getVoteDirectionString(direction types.VoteDirection) string { // Get protocol DAO proposals func (c *Client) PDAOProposals() (api.PDAOProposalsResponse, error) { - responseBytes, err := c.callAPI("pdao proposals") + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/proposals", nil) if err != nil { return api.PDAOProposalsResponse{}, fmt.Errorf("Could not get protocol DAO proposals: %w", err) } @@ -45,7 +47,7 @@ func (c *Client) PDAOProposals() (api.PDAOProposalsResponse, error) { // Get protocol DAO proposal details func (c *Client) PDAOProposalDetails(proposalID uint64) (api.PDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao proposal-details %d", proposalID)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/proposal-details", url.Values{"id": {strconv.FormatUint(proposalID, 10)}}) if err != nil { return api.PDAOProposalResponse{}, fmt.Errorf("Could not get protocol DAO proposal: %w", err) } @@ -61,7 +63,10 @@ func (c *Client) PDAOProposalDetails(proposalID uint64) (api.PDAOProposalRespons // Check whether the node can vote on a proposal func (c *Client) PDAOCanVoteProposal(proposalID uint64, voteDirection types.VoteDirection) (api.CanVoteOnPDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-vote-proposal %d %s", proposalID, getVoteDirectionString(voteDirection))) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-vote-proposal", url.Values{ + "id": {strconv.FormatUint(proposalID, 10)}, + "voteDirection": {getVoteDirectionString(voteDirection)}, + }) if err != nil { return api.CanVoteOnPDAOProposalResponse{}, fmt.Errorf("Could not get protocol DAO can-vote-proposal: %w", err) } @@ -77,7 +82,10 @@ func (c *Client) PDAOCanVoteProposal(proposalID uint64, voteDirection types.Vote // Vote on a proposal func (c *Client) PDAOVoteProposal(proposalID uint64, voteDirection types.VoteDirection) (api.VoteOnPDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao vote-proposal %d %s", proposalID, getVoteDirectionString(voteDirection))) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/vote-proposal", url.Values{ + "id": {strconv.FormatUint(proposalID, 10)}, + "voteDirection": {getVoteDirectionString(voteDirection)}, + }) if err != nil { return api.VoteOnPDAOProposalResponse{}, fmt.Errorf("Could not get protocol DAO vote-proposal: %w", err) } @@ -93,7 +101,10 @@ func (c *Client) PDAOVoteProposal(proposalID uint64, voteDirection types.VoteDir // Check whether the node can override the delegate's vote on a proposal func (c *Client) PDAOCanOverrideVote(proposalID uint64, voteDirection types.VoteDirection) (api.CanVoteOnPDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-override-vote %d %s", proposalID, getVoteDirectionString(voteDirection))) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-override-vote", url.Values{ + "id": {strconv.FormatUint(proposalID, 10)}, + "voteDirection": {getVoteDirectionString(voteDirection)}, + }) if err != nil { return api.CanVoteOnPDAOProposalResponse{}, fmt.Errorf("Could not get protocol DAO can-override-vote: %w", err) } @@ -109,7 +120,10 @@ func (c *Client) PDAOCanOverrideVote(proposalID uint64, voteDirection types.Vote // Override the delegate's vote on a proposal func (c *Client) PDAOOverrideVote(proposalID uint64, voteDirection types.VoteDirection) (api.VoteOnPDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao override-vote %d %s", proposalID, getVoteDirectionString(voteDirection))) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/override-vote", url.Values{ + "id": {strconv.FormatUint(proposalID, 10)}, + "voteDirection": {getVoteDirectionString(voteDirection)}, + }) if err != nil { return api.VoteOnPDAOProposalResponse{}, fmt.Errorf("Could not get protocol DAO override-vote: %w", err) } @@ -125,7 +139,7 @@ func (c *Client) PDAOOverrideVote(proposalID uint64, voteDirection types.VoteDir // Check whether the node can execute a proposal func (c *Client) PDAOCanExecuteProposal(proposalID uint64) (api.CanExecutePDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-execute-proposal %d", proposalID)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-execute-proposal", url.Values{"id": {strconv.FormatUint(proposalID, 10)}}) if err != nil { return api.CanExecutePDAOProposalResponse{}, fmt.Errorf("Could not get protocol DAO can-execute-proposal: %w", err) } @@ -141,7 +155,7 @@ func (c *Client) PDAOCanExecuteProposal(proposalID uint64) (api.CanExecutePDAOPr // Execute a proposal func (c *Client) PDAOExecuteProposal(proposalID uint64) (api.ExecutePDAOProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao execute-proposal %d", proposalID)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/execute-proposal", url.Values{"id": {strconv.FormatUint(proposalID, 10)}}) if err != nil { return api.ExecutePDAOProposalResponse{}, fmt.Errorf("Could not get protocol DAO execute-proposal: %w", err) } @@ -157,7 +171,7 @@ func (c *Client) PDAOExecuteProposal(proposalID uint64) (api.ExecutePDAOProposal // Get protocol DAO settings func (c *Client) PDAOGetSettings() (api.GetPDAOSettingsResponse, error) { - responseBytes, err := c.callAPI("pdao get-settings") + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/get-settings", nil) if err != nil { return api.GetPDAOSettingsResponse{}, fmt.Errorf("Could not get protocol DAO get-settings: %w", err) } @@ -173,7 +187,11 @@ func (c *Client) PDAOGetSettings() (api.GetPDAOSettingsResponse, error) { // Check whether the node can propose updating a PDAO setting func (c *Client) PDAOCanProposeSetting(contract string, setting string, value string) (api.CanProposePDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-setting %s %s %s", contract, setting, value)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-setting", url.Values{ + "contract": {contract}, + "setting": {setting}, + "value": {value}, + }) if err != nil { return api.CanProposePDAOSettingResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-setting: %w", err) } @@ -187,9 +205,14 @@ func (c *Client) PDAOCanProposeSetting(contract string, setting string, value st return response, nil } -// Propose updating a PDAO setting (use can-propose-setting to get the pollard) +// Propose updating a PDAO setting func (c *Client) PDAOProposeSetting(contract string, setting string, value string, blockNumber uint32) (api.ProposePDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-setting %s %s %s %d", contract, setting, value, blockNumber)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-setting", url.Values{ + "contract": {contract}, + "setting": {setting}, + "value": {value}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + }) if err != nil { return api.ProposePDAOSettingResponse{}, fmt.Errorf("Could not get protocol DAO propose-setting: %w", err) } @@ -203,9 +226,9 @@ func (c *Client) PDAOProposeSetting(contract string, setting string, value strin return response, nil } -// Get the allocation percentages of RPL rewards for the Oracle DAO, the Protocol DAO, and the node operators +// Get the allocation percentages of RPL rewards func (c *Client) PDAOGetRewardsPercentages() (api.PDAOGetRewardsPercentagesResponse, error) { - responseBytes, err := c.callAPI("pdao get-rewards-percentages") + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/get-rewards-percentages", nil) if err != nil { return api.PDAOGetRewardsPercentagesResponse{}, fmt.Errorf("Could not get protocol DAO get-rewards-percentages: %w", err) } @@ -219,9 +242,13 @@ func (c *Client) PDAOGetRewardsPercentages() (api.PDAOGetRewardsPercentagesRespo return response, nil } -// Check whether the node can propose new RPL rewards allocation percentages for the Oracle DAO, the Protocol DAO, and the node operators +// Check whether the node can propose new RPL rewards allocation percentages func (c *Client) PDAOCanProposeRewardsPercentages(node *big.Int, odao *big.Int, pdao *big.Int) (api.PDAOCanProposeRewardsPercentagesResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-rewards-percentages %s %s %s", node.String(), odao.String(), pdao.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-rewards-percentages", url.Values{ + "node": {node.String()}, + "odao": {odao.String()}, + "pdao": {pdao.String()}, + }) if err != nil { return api.PDAOCanProposeRewardsPercentagesResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-rewards-percentages: %w", err) } @@ -235,9 +262,14 @@ func (c *Client) PDAOCanProposeRewardsPercentages(node *big.Int, odao *big.Int, return response, nil } -// Propose new RPL rewards allocation percentages for the Oracle DAO, the Protocol DAO, and the node operators +// Propose new RPL rewards allocation percentages func (c *Client) PDAOProposeRewardsPercentages(node *big.Int, odao *big.Int, pdao *big.Int, blockNumber uint32) (api.ProposePDAOSettingResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-rewards-percentages %s %s %s %d", node, odao, pdao, blockNumber)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-rewards-percentages", url.Values{ + "node": {node.String()}, + "odao": {odao.String()}, + "pdao": {pdao.String()}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + }) if err != nil { return api.ProposePDAOSettingResponse{}, fmt.Errorf("Could not get protocol DAO propose-rewards-percentages: %w", err) } @@ -253,7 +285,12 @@ func (c *Client) PDAOProposeRewardsPercentages(node *big.Int, odao *big.Int, pda // Check whether the node can propose a one-time spend of the Protocol DAO's treasury func (c *Client) PDAOCanProposeOneTimeSpend(invoiceID string, recipient common.Address, amount *big.Int, customMessage string) (api.PDAOCanProposeOneTimeSpendResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-one-time-spend %s %s %s %s", invoiceID, recipient.Hex(), amount.String(), customMessage)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-one-time-spend", url.Values{ + "invoiceId": {invoiceID}, + "recipient": {recipient.Hex()}, + "amount": {amount.String()}, + "customMessage": {customMessage}, + }) if err != nil { return api.PDAOCanProposeOneTimeSpendResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-one-time-spend: %w", err) } @@ -269,7 +306,13 @@ func (c *Client) PDAOCanProposeOneTimeSpend(invoiceID string, recipient common.A // Propose a one-time spend of the Protocol DAO's treasury func (c *Client) PDAOProposeOneTimeSpend(invoiceID string, recipient common.Address, amount *big.Int, blockNumber uint32, customMessage string) (api.PDAOProposeOneTimeSpendResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-one-time-spend %s %s %s %d %s", invoiceID, recipient.Hex(), amount.String(), blockNumber, customMessage)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-one-time-spend", url.Values{ + "invoiceId": {invoiceID}, + "recipient": {recipient.Hex()}, + "amount": {amount.String()}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + "customMessage": {customMessage}, + }) if err != nil { return api.PDAOProposeOneTimeSpendResponse{}, fmt.Errorf("Could not get protocol DAO propose-one-time-spend: %w", err) } @@ -285,7 +328,15 @@ func (c *Client) PDAOProposeOneTimeSpend(invoiceID string, recipient common.Addr // Check whether the node can propose a recurring spend of the Protocol DAO's treasury func (c *Client) PDAOCanProposeRecurringSpend(contractName string, recipient common.Address, amountPerPeriod *big.Int, periodLength time.Duration, startTime time.Time, numberOfPeriods uint64, customMessage string) (api.PDAOCanProposeRecurringSpendResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-recurring-spend %s %s %s %s %d %d %s", contractName, recipient.Hex(), amountPerPeriod.String(), periodLength.String(), startTime.Unix(), numberOfPeriods, customMessage)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-recurring-spend", url.Values{ + "contractName": {contractName}, + "recipient": {recipient.Hex()}, + "amountPerPeriod": {amountPerPeriod.String()}, + "periodLength": {periodLength.String()}, + "startTime": {strconv.FormatInt(startTime.Unix(), 10)}, + "numberOfPeriods": {strconv.FormatUint(numberOfPeriods, 10)}, + "customMessage": {customMessage}, + }) if err != nil { return api.PDAOCanProposeRecurringSpendResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-recurring-spend: %w", err) } @@ -301,7 +352,16 @@ func (c *Client) PDAOCanProposeRecurringSpend(contractName string, recipient com // Propose a recurring spend of the Protocol DAO's treasury func (c *Client) PDAOProposeRecurringSpend(contractName string, recipient common.Address, amountPerPeriod *big.Int, periodLength time.Duration, startTime time.Time, numberOfPeriods uint64, blockNumber uint32, customMessage string) (api.PDAOProposeRecurringSpendResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-recurring-spend %s %s %s %s %d %d %d %s", contractName, recipient.Hex(), amountPerPeriod.String(), periodLength.String(), startTime.Unix(), numberOfPeriods, blockNumber, customMessage)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-recurring-spend", url.Values{ + "contractName": {contractName}, + "recipient": {recipient.Hex()}, + "amountPerPeriod": {amountPerPeriod.String()}, + "periodLength": {periodLength.String()}, + "startTime": {strconv.FormatInt(startTime.Unix(), 10)}, + "numberOfPeriods": {strconv.FormatUint(numberOfPeriods, 10)}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + "customMessage": {customMessage}, + }) if err != nil { return api.PDAOProposeRecurringSpendResponse{}, fmt.Errorf("Could not get protocol DAO propose-recurring-spend: %w", err) } @@ -317,7 +377,14 @@ func (c *Client) PDAOProposeRecurringSpend(contractName string, recipient common // Check whether the node can propose an update to an existing recurring spend plan func (c *Client) PDAOCanProposeRecurringSpendUpdate(contractName string, recipient common.Address, amountPerPeriod *big.Int, periodLength time.Duration, numberOfPeriods uint64, customMessage string) (api.PDAOCanProposeRecurringSpendUpdateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-recurring-spend-update %s %s %s %s %d %s", contractName, recipient.Hex(), amountPerPeriod.String(), periodLength.String(), numberOfPeriods, customMessage)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-recurring-spend-update", url.Values{ + "contractName": {contractName}, + "recipient": {recipient.Hex()}, + "amountPerPeriod": {amountPerPeriod.String()}, + "periodLength": {periodLength.String()}, + "numberOfPeriods": {strconv.FormatUint(numberOfPeriods, 10)}, + "customMessage": {customMessage}, + }) if err != nil { return api.PDAOCanProposeRecurringSpendUpdateResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-recurring-spend-update: %w", err) } @@ -333,7 +400,15 @@ func (c *Client) PDAOCanProposeRecurringSpendUpdate(contractName string, recipie // Propose an update to an existing recurring spend plan func (c *Client) PDAOProposeRecurringSpendUpdate(contractName string, recipient common.Address, amountPerPeriod *big.Int, periodLength time.Duration, numberOfPeriods uint64, blockNumber uint32, customMessage string) (api.PDAOProposeRecurringSpendUpdateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-recurring-spend-update %s %s %s %s %d %d %s", contractName, recipient.Hex(), amountPerPeriod.String(), periodLength.String(), numberOfPeriods, blockNumber, customMessage)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-recurring-spend-update", url.Values{ + "contractName": {contractName}, + "recipient": {recipient.Hex()}, + "amountPerPeriod": {amountPerPeriod.String()}, + "periodLength": {periodLength.String()}, + "numberOfPeriods": {strconv.FormatUint(numberOfPeriods, 10)}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + "customMessage": {customMessage}, + }) if err != nil { return api.PDAOProposeRecurringSpendUpdateResponse{}, fmt.Errorf("Could not get protocol DAO propose-recurring-spend-update: %w", err) } @@ -349,7 +424,10 @@ func (c *Client) PDAOProposeRecurringSpendUpdate(contractName string, recipient // Check whether the node can invite someone to the security council func (c *Client) PDAOCanProposeInviteToSecurityCouncil(id string, address common.Address) (api.PDAOCanProposeInviteToSecurityCouncilResponse, error) { - responseBytes, err := c.callAPI("pdao can-propose-invite-to-security-council", id, address.Hex()) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-invite-to-security-council", url.Values{ + "id": {id}, + "address": {address.Hex()}, + }) if err != nil { return api.PDAOCanProposeInviteToSecurityCouncilResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-invite-to-security-council: %w", err) } @@ -365,7 +443,11 @@ func (c *Client) PDAOCanProposeInviteToSecurityCouncil(id string, address common // Propose inviting someone to the security council func (c *Client) PDAOProposeInviteToSecurityCouncil(id string, address common.Address, blockNumber uint32) (api.PDAOProposeInviteToSecurityCouncilResponse, error) { - responseBytes, err := c.callAPI("pdao propose-invite-to-security-council", id, address.Hex(), fmt.Sprint(blockNumber)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-invite-to-security-council", url.Values{ + "id": {id}, + "address": {address.Hex()}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + }) if err != nil { return api.PDAOProposeInviteToSecurityCouncilResponse{}, fmt.Errorf("Could not get protocol DAO propose-invite-to-security-council: %w", err) } @@ -381,7 +463,7 @@ func (c *Client) PDAOProposeInviteToSecurityCouncil(id string, address common.Ad // Check whether the node can kick someone from the security council func (c *Client) PDAOCanProposeKickFromSecurityCouncil(address common.Address) (api.PDAOCanProposeKickFromSecurityCouncilResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-kick-from-security-council %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-kick-from-security-council", url.Values{"address": {address.Hex()}}) if err != nil { return api.PDAOCanProposeKickFromSecurityCouncilResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-kick-from-security-council: %w", err) } @@ -397,7 +479,10 @@ func (c *Client) PDAOCanProposeKickFromSecurityCouncil(address common.Address) ( // Propose kicking someone from the security council func (c *Client) PDAOProposeKickFromSecurityCouncil(address common.Address, blockNumber uint32) (api.PDAOProposeKickFromSecurityCouncilResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-kick-from-security-council %s %d", address.Hex(), blockNumber)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-kick-from-security-council", url.Values{ + "address": {address.Hex()}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + }) if err != nil { return api.PDAOProposeKickFromSecurityCouncilResponse{}, fmt.Errorf("Could not get protocol DAO propose-kick-from-security-council: %w", err) } @@ -417,8 +502,7 @@ func (c *Client) PDAOCanProposeKickMultiFromSecurityCouncil(addresses []common.A for i, address := range addresses { addressStrings[i] = address.Hex() } - - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-kick-multi-from-security-council %s", strings.Join(addressStrings, ","))) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-kick-multi-from-security-council", url.Values{"addresses": {strings.Join(addressStrings, ",")}}) if err != nil { return api.PDAOCanProposeKickMultiFromSecurityCouncilResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-kick-multi-from-security-council: %w", err) } @@ -438,8 +522,10 @@ func (c *Client) PDAOProposeKickMultiFromSecurityCouncil(addresses []common.Addr for i, address := range addresses { addressStrings[i] = address.Hex() } - - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-kick-multi-from-security-council %s %d", strings.Join(addressStrings, ","), blockNumber)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-kick-multi-from-security-council", url.Values{ + "addresses": {strings.Join(addressStrings, ",")}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + }) if err != nil { return api.PDAOProposeKickMultiFromSecurityCouncilResponse{}, fmt.Errorf("Could not get protocol DAO propose-kick-multi-from-security-council: %w", err) } @@ -453,9 +539,13 @@ func (c *Client) PDAOProposeKickMultiFromSecurityCouncil(addresses []common.Addr return response, nil } -// Check whether the node can propose replacing someone on the security council with another member +// Check whether the node can propose replacing someone on the security council func (c *Client) PDAOCanProposeReplaceMemberOfSecurityCouncil(existingAddress common.Address, newID string, newAddress common.Address) (api.PDAOCanProposeReplaceMemberOfSecurityCouncilResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-replace-member-of-security-council %s", existingAddress.Hex()), newID, newAddress.Hex()) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-replace-member-of-security-council", url.Values{ + "existingAddress": {existingAddress.Hex()}, + "newId": {newID}, + "newAddress": {newAddress.Hex()}, + }) if err != nil { return api.PDAOCanProposeReplaceMemberOfSecurityCouncilResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-replace-member-of-security-council: %w", err) } @@ -469,9 +559,14 @@ func (c *Client) PDAOCanProposeReplaceMemberOfSecurityCouncil(existingAddress co return response, nil } -// Propose replacing someone on the security council with another member +// Propose replacing someone on the security council func (c *Client) PDAOProposeReplaceMemberOfSecurityCouncil(existingAddress common.Address, newID string, newAddress common.Address, blockNumber uint32) (api.PDAOProposeReplaceMemberOfSecurityCouncilResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-replace-member-of-security-council %s", existingAddress.Hex()), newID, newAddress.Hex(), fmt.Sprint(blockNumber)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-replace-member-of-security-council", url.Values{ + "existingAddress": {existingAddress.Hex()}, + "newId": {newID}, + "newAddress": {newAddress.Hex()}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + }) if err != nil { return api.PDAOProposeReplaceMemberOfSecurityCouncilResponse{}, fmt.Errorf("Could not get protocol DAO propose-replace-member-of-security-council: %w", err) } @@ -485,9 +580,9 @@ func (c *Client) PDAOProposeReplaceMemberOfSecurityCouncil(existingAddress commo return response, nil } -// Get the list of proposals with claimable / rewardable bonds, and the relevant indices for each one +// Get the list of proposals with claimable / rewardable bonds func (c *Client) PDAOGetClaimableBonds() (api.PDAOGetClaimableBondsResponse, error) { - responseBytes, err := c.callAPI("pdao get-claimable-bonds") + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/get-claimable-bonds", nil) if err != nil { return api.PDAOGetClaimableBondsResponse{}, fmt.Errorf("Could not get protocol DAO get-claimable-bonds: %w", err) } @@ -505,10 +600,12 @@ func (c *Client) PDAOGetClaimableBonds() (api.PDAOGetClaimableBondsResponse, err func (c *Client) PDAOCanClaimBonds(proposalID uint64, indices []uint64) (api.PDAOCanClaimBondsResponse, error) { indicesStrings := make([]string, len(indices)) for i, index := range indices { - indicesStrings[i] = fmt.Sprint(index) + indicesStrings[i] = strconv.FormatUint(index, 10) } - - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-claim-bonds %d %s", proposalID, strings.Join(indicesStrings, ","))) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-claim-bonds", url.Values{ + "proposalId": {strconv.FormatUint(proposalID, 10)}, + "indices": {strings.Join(indicesStrings, ",")}, + }) if err != nil { return api.PDAOCanClaimBondsResponse{}, fmt.Errorf("Could not get protocol DAO can-claim-bonds: %w", err) } @@ -526,10 +623,17 @@ func (c *Client) PDAOCanClaimBonds(proposalID uint64, indices []uint64) (api.PDA func (c *Client) PDAOClaimBonds(isProposer bool, proposalID uint64, indices []uint64) (api.PDAOClaimBondsResponse, error) { indicesStrings := make([]string, len(indices)) for i, index := range indices { - indicesStrings[i] = fmt.Sprint(index) + indicesStrings[i] = strconv.FormatUint(index, 10) } - - responseBytes, err := c.callAPI(fmt.Sprintf("pdao claim-bonds %t %d %s", isProposer, proposalID, strings.Join(indicesStrings, ","))) + isProposerStr := "false" + if isProposer { + isProposerStr = "true" + } + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/claim-bonds", url.Values{ + "isProposer": {isProposerStr}, + "proposalId": {strconv.FormatUint(proposalID, 10)}, + "indices": {strings.Join(indicesStrings, ",")}, + }) if err != nil { return api.PDAOClaimBondsResponse{}, fmt.Errorf("Could not get protocol DAO claim-bonds: %w", err) } @@ -545,7 +649,10 @@ func (c *Client) PDAOClaimBonds(isProposer bool, proposalID uint64, indices []ui // Check whether the node can defeat a proposal func (c *Client) PDAOCanDefeatProposal(proposalID uint64, index uint64) (api.PDAOCanDefeatProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-defeat-proposal %d %d", proposalID, index)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-defeat-proposal", url.Values{ + "id": {strconv.FormatUint(proposalID, 10)}, + "index": {strconv.FormatUint(index, 10)}, + }) if err != nil { return api.PDAOCanDefeatProposalResponse{}, fmt.Errorf("Could not get protocol DAO can-defeat-proposal: %w", err) } @@ -561,7 +668,10 @@ func (c *Client) PDAOCanDefeatProposal(proposalID uint64, index uint64) (api.PDA // Defeat a proposal func (c *Client) PDAODefeatProposal(proposalID uint64, index uint64) (api.PDAODefeatProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao defeat-proposal %d %d", proposalID, index)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/defeat-proposal", url.Values{ + "id": {strconv.FormatUint(proposalID, 10)}, + "index": {strconv.FormatUint(index, 10)}, + }) if err != nil { return api.PDAODefeatProposalResponse{}, fmt.Errorf("Could not get protocol DAO defeat-proposal: %w", err) } @@ -577,7 +687,7 @@ func (c *Client) PDAODefeatProposal(proposalID uint64, index uint64) (api.PDAODe // Check whether the node can finalize a proposal func (c *Client) PDAOCanFinalizeProposal(proposalID uint64) (api.PDAOCanFinalizeProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-finalize-proposal %d", proposalID)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-finalize-proposal", url.Values{"id": {strconv.FormatUint(proposalID, 10)}}) if err != nil { return api.PDAOCanFinalizeProposalResponse{}, fmt.Errorf("Could not get protocol DAO can-finalize-proposal: %w", err) } @@ -593,7 +703,7 @@ func (c *Client) PDAOCanFinalizeProposal(proposalID uint64) (api.PDAOCanFinalize // Finalize a proposal func (c *Client) PDAOFinalizeProposal(proposalID uint64) (api.PDAOFinalizeProposalResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao finalize-proposal %d", proposalID)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/finalize-proposal", url.Values{"id": {strconv.FormatUint(proposalID, 10)}}) if err != nil { return api.PDAOFinalizeProposalResponse{}, fmt.Errorf("Could not get protocol DAO finalize-proposal: %w", err) } @@ -609,7 +719,7 @@ func (c *Client) PDAOFinalizeProposal(proposalID uint64) (api.PDAOFinalizePropos // EstimateSetVotingDelegateGas estimates the gas required to set an on-chain voting delegate func (c *Client) EstimateSetVotingDelegateGas(address common.Address) (api.PDAOCanSetVotingDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao estimate-set-voting-delegate-gas %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/estimate-set-voting-delegate-gas", url.Values{"address": {address.Hex()}}) if err != nil { return api.PDAOCanSetVotingDelegateResponse{}, fmt.Errorf("could not call estimate-set-voting-delegate-gas: %w", err) } @@ -623,9 +733,9 @@ func (c *Client) EstimateSetVotingDelegateGas(address common.Address) (api.PDAOC return response, nil } -// SetVotingDelegate set an on-chain voting delegate for the node +// SetVotingDelegate sets an on-chain voting delegate for the node func (c *Client) SetVotingDelegate(address common.Address) (api.PDAOSetVotingDelegateResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao set-voting-delegate %s", address.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/set-voting-delegate", url.Values{"address": {address.Hex()}}) if err != nil { return api.PDAOSetVotingDelegateResponse{}, fmt.Errorf("could not call set-voting-delegate: %w", err) } @@ -641,7 +751,7 @@ func (c *Client) SetVotingDelegate(address common.Address) (api.PDAOSetVotingDel // GetCurrentVotingDelegate gets the node current on-chain voting delegate func (c *Client) GetCurrentVotingDelegate() (api.PDAOCurrentVotingDelegateResponse, error) { - responseBytes, err := c.callAPI("pdao get-current-voting-delegate") + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/get-current-voting-delegate", nil) if err != nil { return api.PDAOCurrentVotingDelegateResponse{}, fmt.Errorf("could not request get-current-voting-delegate: %w", err) } @@ -657,7 +767,10 @@ func (c *Client) GetCurrentVotingDelegate() (api.PDAOCurrentVotingDelegateRespon // CanSetSignallingAddress fetches gas info and if a node can set the signalling address func (c *Client) CanSetSignallingAddress(signallingAddress common.Address, signature string) (api.PDAOCanSetSignallingAddressResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-set-signalling-address %s %s", signallingAddress.Hex(), signature)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-set-signalling-address", url.Values{ + "address": {signallingAddress.Hex()}, + "signature": {signature}, + }) if err != nil { return api.PDAOCanSetSignallingAddressResponse{}, fmt.Errorf("could not call can-set-signalling-address: %w", err) } @@ -673,7 +786,10 @@ func (c *Client) CanSetSignallingAddress(signallingAddress common.Address, signa // SetSignallingAddress sets the node's signalling address func (c *Client) SetSignallingAddress(signallingAddress common.Address, signature string) (api.PDAOSetSignallingAddressResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao set-signalling-address %s %s", signallingAddress.Hex(), signature)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/set-signalling-address", url.Values{ + "address": {signallingAddress.Hex()}, + "signature": {signature}, + }) if err != nil { return api.PDAOSetSignallingAddressResponse{}, fmt.Errorf("could not call set-signalling-address: %w", err) } @@ -689,7 +805,7 @@ func (c *Client) SetSignallingAddress(signallingAddress common.Address, signatur // CanClearSignallingAddress fetches gas info and if a node can clear a signalling address func (c *Client) CanClearSignallingAddress() (api.PDAOCanClearSignallingAddressResponse, error) { - responseBytes, err := c.callAPI("pdao can-clear-signalling-address") + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-clear-signalling-address", nil) if err != nil { return api.PDAOCanClearSignallingAddressResponse{}, fmt.Errorf("could not call can-clear-signalling-address: %w", err) } @@ -703,9 +819,9 @@ func (c *Client) CanClearSignallingAddress() (api.PDAOCanClearSignallingAddressR return response, nil } -// ClearSignallingAddress sets the node's signalling address +// ClearSignallingAddress clears the node's signalling address func (c *Client) ClearSignallingAddress() (api.PDAOSetSignallingAddressResponse, error) { - responseBytes, err := c.callAPI("pdao clear-signalling-address") + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/clear-signalling-address", nil) if err != nil { return api.PDAOSetSignallingAddressResponse{}, fmt.Errorf("could not call clear-signalling-address: %w", err) } @@ -721,7 +837,7 @@ func (c *Client) ClearSignallingAddress() (api.PDAOSetSignallingAddressResponse, // Check whether the node can propose a list of addresses that can update commission share parameters func (c *Client) PDAOCanProposeAllowListedControllers(addressList string) (api.PDAOACanProposeAllowListedControllersResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao can-propose-allow-listed-controllers %s", addressList)) + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/can-propose-allow-listed-controllers", url.Values{"addressList": {addressList}}) if err != nil { return api.PDAOACanProposeAllowListedControllersResponse{}, fmt.Errorf("Could not get protocol DAO can-propose-allow-listed-controllers: %w", err) } @@ -737,7 +853,10 @@ func (c *Client) PDAOCanProposeAllowListedControllers(addressList string) (api.P // Propose a list of addresses that can update commission share parameters func (c *Client) PDAOProposeAllowListedControllers(addressList string, blockNumber uint32) (api.PDAOProposeAllowListedControllersResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("pdao propose-allow-listed-controllers %s %d", addressList, blockNumber)) + responseBytes, err := c.callHTTPAPI("POST", "/api/pdao/propose-allow-listed-controllers", url.Values{ + "addressList": {addressList}, + "blockNumber": {strconv.FormatUint(uint64(blockNumber), 10)}, + }) if err != nil { return api.PDAOProposeAllowListedControllersResponse{}, fmt.Errorf("Could not get protocol DAO propose-allow-listed-controllers: %w", err) } @@ -753,7 +872,7 @@ func (c *Client) PDAOProposeAllowListedControllers(addressList string, blockNumb // Get PDAO Status func (c *Client) PDAOStatus() (api.PDAOStatusResponse, error) { - responseBytes, err := c.callAPI("pdao status") + responseBytes, err := c.callHTTPAPI("GET", "/api/pdao/status", nil) if err != nil { return api.PDAOStatusResponse{}, fmt.Errorf("could not call get pdao status: %w", err) } From 6433ea088a0fbfacb2e8e5109a4aea4e03acd133 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:34:24 -0300 Subject: [PATCH 07/24] Migrate node module to HTTP API Server side: - node/routes.go: RegisterRoutes() for all node endpoints (status, alerts, sync, eth-balance, check-collateral, rewards, deposit-contract-info, register, set-timezone, primary/rpl withdrawal addresses, swap/stake/ unstake rpl, rpl locking, withdraw rpl/eth/credit, deposit, send/burn, claim-rpl, fee-distributor, interval rewards, smoothing-pool, ens, sign, sign-message, vacant-minipool, send-message, express-tickets, unclaimed-rewards, bond-requirement) - node/routes/routes.go: add noderoutes.RegisterRoutes Client side: - node.go: all methods migrated to callHTTPAPI Co-authored-by: Cursor --- rocketpool/api/node/routes.go | 826 +++++++++++++++++++++++++++++ rocketpool/node/routes/routes.go | 2 + shared/services/rocketpool/node.go | 255 +++++---- 3 files changed, 990 insertions(+), 93 deletions(-) create mode 100644 rocketpool/api/node/routes.go diff --git a/rocketpool/api/node/routes.go b/rocketpool/api/node/routes.go new file mode 100644 index 000000000..ea0edfc1d --- /dev/null +++ b/rocketpool/api/node/routes.go @@ -0,0 +1,826 @@ +package node + +import ( + "encoding/hex" + "fmt" + "math/big" + "net/http" + "strconv" + + "github.com/ethereum/go-ethereum/common" + rptypes "github.com/rocket-pool/smartnode/bindings/types" + "github.com/urfave/cli" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterRoutes registers the node module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/node/status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/alerts", func(w http.ResponseWriter, r *http.Request) { + resp, err := getAlerts(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/sync", func(w http.ResponseWriter, r *http.Request) { + resp, err := getSyncProgress(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/get-eth-balance", func(w http.ResponseWriter, r *http.Request) { + resp, err := getNodeEthBalance(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/check-collateral", func(w http.ResponseWriter, r *http.Request) { + resp, err := checkCollateral(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/rewards", func(w http.ResponseWriter, r *http.Request) { + resp, err := getRewards(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/deposit-contract-info", func(w http.ResponseWriter, r *http.Request) { + resp, err := getDepositContractInfo(c) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Register --- + + mux.HandleFunc("/api/node/can-register", func(w http.ResponseWriter, r *http.Request) { + tz := r.URL.Query().Get("timezoneLocation") + resp, err := canRegisterNode(c, tz) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/register", func(w http.ResponseWriter, r *http.Request) { + tz := r.FormValue("timezoneLocation") + resp, err := registerNode(c, tz) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Timezone --- + + mux.HandleFunc("/api/node/can-set-timezone", func(w http.ResponseWriter, r *http.Request) { + tz := r.URL.Query().Get("timezoneLocation") + resp, err := canSetTimezoneLocation(c, tz) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/set-timezone", func(w http.ResponseWriter, r *http.Request) { + tz := r.FormValue("timezoneLocation") + resp, err := setTimezoneLocation(c, tz) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Primary withdrawal address --- + + mux.HandleFunc("/api/node/can-set-primary-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(r.URL.Query().Get("address")) + confirm := r.URL.Query().Get("confirm") == "true" + resp, err := canSetPrimaryWithdrawalAddress(c, addr, confirm) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/set-primary-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(r.FormValue("address")) + confirm := r.FormValue("confirm") == "true" + resp, err := setPrimaryWithdrawalAddress(c, addr, confirm) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-confirm-primary-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { + resp, err := canConfirmPrimaryWithdrawalAddress(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/confirm-primary-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { + resp, err := confirmPrimaryWithdrawalAddress(c) + apiutils.WriteResponse(w, resp, err) + }) + + // --- RPL withdrawal address --- + + mux.HandleFunc("/api/node/can-set-rpl-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(r.URL.Query().Get("address")) + confirm := r.URL.Query().Get("confirm") == "true" + resp, err := canSetRPLWithdrawalAddress(c, addr, confirm) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/set-rpl-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(r.FormValue("address")) + confirm := r.FormValue("confirm") == "true" + resp, err := setRPLWithdrawalAddress(c, addr, confirm) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-confirm-rpl-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { + resp, err := canConfirmRPLWithdrawalAddress(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/confirm-rpl-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { + resp, err := confirmRPLWithdrawalAddress(c) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Swap RPL --- + + mux.HandleFunc("/api/node/swap-rpl-allowance", func(w http.ResponseWriter, r *http.Request) { + resp, err := allowanceFsRpl(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-swap-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNodeSwapRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/get-swap-rpl-approval-gas", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getSwapApprovalGas(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/swap-rpl-approve-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := approveFsRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/wait-and-swap-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + hash := common.HexToHash(r.FormValue("approvalTxHash")) + resp, err := waitForApprovalAndSwapFsRpl(c, amountWei, hash) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/swap-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := swapRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Stake RPL --- + + mux.HandleFunc("/api/node/stake-rpl-allowance", func(w http.ResponseWriter, r *http.Request) { + resp, err := allowanceRpl(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-stake-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNodeStakeRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/get-stake-rpl-approval-gas", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := getStakeApprovalGas(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/stake-rpl-approve-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := approveRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/wait-and-stake-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + hash := common.HexToHash(r.FormValue("approvalTxHash")) + resp, err := waitForApprovalAndStakeRpl(c, amountWei, hash) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/stake-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := stakeRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + // --- RPL locking --- + + mux.HandleFunc("/api/node/can-set-rpl-locking-allowed", func(w http.ResponseWriter, r *http.Request) { + allowed := r.URL.Query().Get("allowed") == "true" + resp, err := canSetRplLockAllowed(c, allowed) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/set-rpl-locking-allowed", func(w http.ResponseWriter, r *http.Request) { + allowed := r.FormValue("allowed") == "true" + resp, err := setRplLockAllowed(c, allowed) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Stake RPL for allowed --- + + mux.HandleFunc("/api/node/can-set-stake-rpl-for-allowed", func(w http.ResponseWriter, r *http.Request) { + caller := common.HexToAddress(r.URL.Query().Get("caller")) + allowed := r.URL.Query().Get("allowed") == "true" + resp, err := canSetStakeRplForAllowed(c, caller, allowed) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/set-stake-rpl-for-allowed", func(w http.ResponseWriter, r *http.Request) { + caller := common.HexToAddress(r.FormValue("caller")) + allowed := r.FormValue("allowed") == "true" + resp, err := setStakeRplForAllowed(c, caller, allowed) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Withdraw RPL --- + + mux.HandleFunc("/api/node/can-withdraw-rpl", func(w http.ResponseWriter, r *http.Request) { + resp, err := canNodeWithdrawRpl(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/withdraw-rpl", func(w http.ResponseWriter, r *http.Request) { + resp, err := nodeWithdrawRpl(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-unstake-legacy-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNodeUnstakeLegacyRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/unstake-legacy-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeUnstakeLegacyRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-withdraw-rpl-v131", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNodeWithdrawRplv1_3_1(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/withdraw-rpl-v131", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeWithdrawRplv1_3_1(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-unstake-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNodeUnstakeRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/unstake-rpl", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeUnstakeRpl(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Withdraw ETH / credit --- + + mux.HandleFunc("/api/node/can-withdraw-eth", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNodeWithdrawEth(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/withdraw-eth", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeWithdrawEth(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-withdraw-credit", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNodeWithdrawCredit(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/withdraw-credit", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeWithdrawCredit(c, amountWei) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Deposit --- + + mux.HandleFunc("/api/node/can-deposit", func(w http.ResponseWriter, r *http.Request) { + params, err := parseDepositParams(r, false) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canNodeDeposits(c, params.count, params.amountWei, params.minFee, params.salt, params.expressTickets) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/deposit", func(w http.ResponseWriter, r *http.Request) { + params, err := parseDepositParams(r, true) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeDeposits(c, params.count, params.amountWei, params.minFee, params.salt, params.useCreditBalance, params.expressTickets, params.submit) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Send / burn --- + + mux.HandleFunc("/api/node/can-send", func(w http.ResponseWriter, r *http.Request) { + amountRaw, err := parseNodeFloat64(r, "amountRaw") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + token := r.URL.Query().Get("token") + to := common.HexToAddress(r.URL.Query().Get("to")) + resp, err := canNodeSend(c, amountRaw, token, to) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/send", func(w http.ResponseWriter, r *http.Request) { + amountRaw, err := parseNodeFloat64(r, "amountRaw") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + token := r.FormValue("token") + to := common.HexToAddress(r.FormValue("to")) + resp, err := nodeSend(c, amountRaw, token, to) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/send-all", func(w http.ResponseWriter, r *http.Request) { + token := r.FormValue("token") + to := common.HexToAddress(r.FormValue("to")) + resp, err := nodeSendAllTokens(c, token, to) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-burn", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + token := r.URL.Query().Get("token") + resp, err := canNodeBurn(c, amountWei, token) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/burn", func(w http.ResponseWriter, r *http.Request) { + amountWei, err := parseNodeBigInt(r, "amountWei") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + token := r.FormValue("token") + resp, err := nodeBurn(c, amountWei, token) + apiutils.WriteResponse(w, resp, err) + }) + + // --- RPL claim --- + + mux.HandleFunc("/api/node/can-claim-rpl-rewards", func(w http.ResponseWriter, r *http.Request) { + resp, err := canNodeClaimRpl(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/claim-rpl-rewards", func(w http.ResponseWriter, r *http.Request) { + resp, err := nodeClaimRpl(c) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Fee distributor --- + + mux.HandleFunc("/api/node/is-fee-distributor-initialized", func(w http.ResponseWriter, r *http.Request) { + resp, err := isFeeDistributorInitialized(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/get-initialize-fee-distributor-gas", func(w http.ResponseWriter, r *http.Request) { + resp, err := getInitializeFeeDistributorGas(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/initialize-fee-distributor", func(w http.ResponseWriter, r *http.Request) { + resp, err := initializeFeeDistributor(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-distribute", func(w http.ResponseWriter, r *http.Request) { + resp, err := canDistribute(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/distribute", func(w http.ResponseWriter, r *http.Request) { + resp, err := distribute(c) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Interval rewards --- + + mux.HandleFunc("/api/node/get-rewards-info", func(w http.ResponseWriter, r *http.Request) { + resp, err := getRewardsInfo(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-claim-rewards", func(w http.ResponseWriter, r *http.Request) { + indices := r.URL.Query().Get("indices") + resp, err := canClaimRewards(c, indices) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/claim-rewards", func(w http.ResponseWriter, r *http.Request) { + indices := r.FormValue("indices") + resp, err := claimRewards(c, indices) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-claim-and-stake-rewards", func(w http.ResponseWriter, r *http.Request) { + indices := r.URL.Query().Get("indices") + stakeAmount, err := parseNodeBigInt(r, "stakeAmount") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canClaimAndStakeRewards(c, indices, stakeAmount) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/claim-and-stake-rewards", func(w http.ResponseWriter, r *http.Request) { + indices := r.FormValue("indices") + stakeAmount, err := parseNodeBigInt(r, "stakeAmount") + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := claimAndStakeRewards(c, indices, stakeAmount) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Smoothing pool --- + + mux.HandleFunc("/api/node/get-smoothing-pool-registration-status", func(w http.ResponseWriter, r *http.Request) { + resp, err := getSmoothingPoolRegistrationStatus(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-set-smoothing-pool-status", func(w http.ResponseWriter, r *http.Request) { + status := r.URL.Query().Get("status") == "true" + resp, err := canSetSmoothingPoolStatus(c, status) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/set-smoothing-pool-status", func(w http.ResponseWriter, r *http.Request) { + status := r.FormValue("status") == "true" + resp, err := setSmoothingPoolStatus(c, status) + apiutils.WriteResponse(w, resp, err) + }) + + // --- ENS --- + + mux.HandleFunc("/api/node/resolve-ens-name", func(w http.ResponseWriter, r *http.Request) { + name := r.URL.Query().Get("name") + resp, err := resolveEnsName(c, name) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/reverse-resolve-ens-name", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(r.URL.Query().Get("address")) + resp, err := reverseResolveEnsName(c, addr) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Sign --- + + mux.HandleFunc("/api/node/sign-message", func(w http.ResponseWriter, r *http.Request) { + message := r.FormValue("message") + resp, err := signMessage(c, message) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/sign", func(w http.ResponseWriter, r *http.Request) { + serializedTx := r.FormValue("serializedTx") + resp, err := sign(c, serializedTx) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Vacant minipool --- + + mux.HandleFunc("/api/node/can-create-vacant-minipool", func(w http.ResponseWriter, r *http.Request) { + params, err := parseVacantMinipoolParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := canCreateVacantMinipool(c, params.amountWei, params.minFee, params.salt, params.pubkey) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/create-vacant-minipool", func(w http.ResponseWriter, r *http.Request) { + params, err := parseVacantMinipoolParams(r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := createVacantMinipool(c, params.amountWei, params.minFee, params.salt, params.pubkey) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Send message --- + + mux.HandleFunc("/api/node/can-send-message", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(r.URL.Query().Get("address")) + msgBytes, err := hex.DecodeString(r.URL.Query().Get("message")) + if err != nil { + apiutils.WriteErrorResponse(w, fmt.Errorf("invalid message hex: %w", err)) + return + } + resp, err := canSendMessage(c, addr, msgBytes) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/send-message", func(w http.ResponseWriter, r *http.Request) { + addr := common.HexToAddress(r.FormValue("address")) + msgBytes, err := hex.DecodeString(r.FormValue("message")) + if err != nil { + apiutils.WriteErrorResponse(w, fmt.Errorf("invalid message hex: %w", err)) + return + } + resp, err := sendMessage(c, addr, msgBytes) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Express tickets --- + + mux.HandleFunc("/api/node/get-express-ticket-count", func(w http.ResponseWriter, r *http.Request) { + resp, err := getExpressTicketCount(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/get-express-tickets-provisioned", func(w http.ResponseWriter, r *http.Request) { + resp, err := getExpressTicketsProvisioned(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/can-provision-express-tickets", func(w http.ResponseWriter, r *http.Request) { + resp, err := canProvisionExpressTickets(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/provision-express-tickets", func(w http.ResponseWriter, r *http.Request) { + resp, err := provisionExpressTickets(c) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Unclaimed rewards --- + + mux.HandleFunc("/api/node/can-claim-unclaimed-rewards", func(w http.ResponseWriter, r *http.Request) { + nodeAddr := common.HexToAddress(r.URL.Query().Get("nodeAddress")) + resp, err := canClaimUnclaimedRewards(c, nodeAddr) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/node/claim-unclaimed-rewards", func(w http.ResponseWriter, r *http.Request) { + nodeAddr := common.HexToAddress(r.FormValue("nodeAddress")) + resp, err := claimUnclaimedRewards(c, nodeAddr) + apiutils.WriteResponse(w, resp, err) + }) + + // --- Bond requirement --- + + mux.HandleFunc("/api/node/get-bond-requirement", func(w http.ResponseWriter, r *http.Request) { + numValidators, err := strconv.ParseUint(r.URL.Query().Get("numValidators"), 10, 64) + if err != nil { + apiutils.WriteErrorResponse(w, fmt.Errorf("invalid numValidators: %w", err)) + return + } + resp, err := getBondRequirement(c, numValidators) + apiutils.WriteResponse(w, resp, err) + }) +} + +// --- Helper types and functions --- + +type depositParams struct { + count uint64 + amountWei *big.Int + minFee float64 + salt *big.Int + expressTickets int64 + useCreditBalance bool + submit bool +} + +func parseDepositParams(r *http.Request, includeExecuteParams bool) (depositParams, error) { + var p depositParams + var err error + + p.amountWei, err = parseNodeBigInt(r, "amountWei") + if err != nil { + return p, fmt.Errorf("invalid amountWei: %w", err) + } + + minFeeStr := r.URL.Query().Get("minFee") + if minFeeStr == "" { + minFeeStr = r.FormValue("minFee") + } + p.minFee, err = strconv.ParseFloat(minFeeStr, 64) + if err != nil { + return p, fmt.Errorf("invalid minFee: %w", err) + } + + p.salt, err = parseNodeBigInt(r, "salt") + if err != nil { + return p, fmt.Errorf("invalid salt: %w", err) + } + + expressStr := r.URL.Query().Get("expressTickets") + if expressStr == "" { + expressStr = r.FormValue("expressTickets") + } + p.expressTickets, err = strconv.ParseInt(expressStr, 10, 64) + if err != nil { + return p, fmt.Errorf("invalid expressTickets: %w", err) + } + + countStr := r.URL.Query().Get("count") + if countStr == "" { + countStr = r.FormValue("count") + } + p.count, err = strconv.ParseUint(countStr, 10, 64) + if err != nil { + return p, fmt.Errorf("invalid count: %w", err) + } + + if includeExecuteParams { + p.useCreditBalance = r.FormValue("useCreditBalance") == "true" + p.submit = r.FormValue("submit") == "true" + } + + return p, nil +} + +type vacantMinipoolParams struct { + amountWei *big.Int + minFee float64 + salt *big.Int + pubkey rptypes.ValidatorPubkey +} + +func parseVacantMinipoolParams(r *http.Request) (vacantMinipoolParams, error) { + var p vacantMinipoolParams + var err error + + raw := r.URL.Query().Get("amountWei") + if raw == "" { + raw = r.FormValue("amountWei") + } + p.amountWei, _ = new(big.Int).SetString(raw, 10) + if p.amountWei == nil { + return p, fmt.Errorf("invalid amountWei: %s", raw) + } + + minFeeStr := r.URL.Query().Get("minFee") + if minFeeStr == "" { + minFeeStr = r.FormValue("minFee") + } + p.minFee, err = strconv.ParseFloat(minFeeStr, 64) + if err != nil { + return p, fmt.Errorf("invalid minFee: %w", err) + } + + saltStr := r.URL.Query().Get("salt") + if saltStr == "" { + saltStr = r.FormValue("salt") + } + p.salt, _ = new(big.Int).SetString(saltStr, 10) + if p.salt == nil { + return p, fmt.Errorf("invalid salt: %s", saltStr) + } + + pubkeyStr := r.URL.Query().Get("pubkey") + if pubkeyStr == "" { + pubkeyStr = r.FormValue("pubkey") + } + pubkeyBytes, err := hex.DecodeString(pubkeyStr) + if err != nil { + return p, fmt.Errorf("invalid pubkey hex: %w", err) + } + if len(pubkeyBytes) != len(p.pubkey) { + return p, fmt.Errorf("pubkey must be %d bytes, got %d", len(p.pubkey), len(pubkeyBytes)) + } + copy(p.pubkey[:], pubkeyBytes) + + return p, nil +} + +func parseNodeBigInt(r *http.Request, name string) (*big.Int, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + v, ok := new(big.Int).SetString(raw, 10) + if !ok { + return nil, fmt.Errorf("invalid %s: %s", name, raw) + } + return v, nil +} + +func parseNodeFloat64(r *http.Request, name string) (float64, error) { + raw := r.URL.Query().Get(name) + if raw == "" { + raw = r.FormValue(name) + } + return strconv.ParseFloat(raw, 64) +} diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index 50e312d50..a1844deeb 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -9,6 +9,7 @@ import ( megapoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/megapool" minipoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/minipool" networkroutes "github.com/rocket-pool/smartnode/rocketpool/api/network" + noderoutes "github.com/rocket-pool/smartnode/rocketpool/api/node" odaoroutes "github.com/rocket-pool/smartnode/rocketpool/api/odao" pdaoroutes "github.com/rocket-pool/smartnode/rocketpool/api/pdao" queueroutes "github.com/rocket-pool/smartnode/rocketpool/api/queue" @@ -28,6 +29,7 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { megapoolroutes.RegisterRoutes(mux, c) minipoolroutes.RegisterRoutes(mux, c) networkroutes.RegisterRoutes(mux, c) + noderoutes.RegisterRoutes(mux, c) odaoroutes.RegisterRoutes(mux, c) pdaoroutes.RegisterRoutes(mux, c) queueroutes.RegisterRoutes(mux, c) diff --git a/shared/services/rocketpool/node.go b/shared/services/rocketpool/node.go index d425e4b40..c27b903da 100644 --- a/shared/services/rocketpool/node.go +++ b/shared/services/rocketpool/node.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "math/big" + "net/url" "strconv" "strings" @@ -16,7 +17,7 @@ import ( // Get node status func (c *Client) NodeStatus() (api.NodeStatusResponse, error) { - responseBytes, err := c.callAPI("node status") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/status", nil) if err != nil { return api.NodeStatusResponse{}, fmt.Errorf("Could not get node status: %w", err) } @@ -56,7 +57,7 @@ func (c *Client) NodeStatus() (api.NodeStatusResponse, error) { // Get active alerts from Alertmanager func (c *Client) NodeAlerts() (api.NodeAlertsResponse, error) { - responseBytes, err := c.callAPI("node alerts") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/alerts", nil) if err != nil { return api.NodeAlertsResponse{}, fmt.Errorf("could not get node alerts: %w", err) } @@ -72,7 +73,7 @@ func (c *Client) NodeAlerts() (api.NodeAlertsResponse, error) { // Check whether the node can be registered func (c *Client) CanRegisterNode(timezoneLocation string) (api.CanRegisterNodeResponse, error) { - responseBytes, err := c.callAPI("node can-register", timezoneLocation) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-register", url.Values{"timezoneLocation": {timezoneLocation}}) if err != nil { return api.CanRegisterNodeResponse{}, fmt.Errorf("Could not get can register node status: %w", err) } @@ -88,7 +89,7 @@ func (c *Client) CanRegisterNode(timezoneLocation string) (api.CanRegisterNodeRe // Register the node func (c *Client) RegisterNode(timezoneLocation string) (api.RegisterNodeResponse, error) { - responseBytes, err := c.callAPI("node register", timezoneLocation) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/register", url.Values{"timezoneLocation": {timezoneLocation}}) if err != nil { return api.RegisterNodeResponse{}, fmt.Errorf("Could not register node: %w", err) } @@ -104,7 +105,10 @@ func (c *Client) RegisterNode(timezoneLocation string) (api.RegisterNodeResponse // Checks if the node's primary withdrawal address can be set func (c *Client) CanSetNodePrimaryWithdrawalAddress(withdrawalAddress common.Address, confirm bool) (api.CanSetNodePrimaryWithdrawalAddressResponse, error) { - responseBytes, err := c.callAPI("node can-set-primary-withdrawal-address", withdrawalAddress.Hex(), strconv.FormatBool(confirm)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-set-primary-withdrawal-address", url.Values{ + "address": {withdrawalAddress.Hex()}, + "confirm": {strconv.FormatBool(confirm)}, + }) if err != nil { return api.CanSetNodePrimaryWithdrawalAddressResponse{}, fmt.Errorf("Could not get can set node primary withdrawal address: %w", err) } @@ -120,7 +124,10 @@ func (c *Client) CanSetNodePrimaryWithdrawalAddress(withdrawalAddress common.Add // Set the node's primary withdrawal address func (c *Client) SetNodePrimaryWithdrawalAddress(withdrawalAddress common.Address, confirm bool) (api.SetNodePrimaryWithdrawalAddressResponse, error) { - responseBytes, err := c.callAPI("node set-primary-withdrawal-address", withdrawalAddress.Hex(), strconv.FormatBool(confirm)) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/set-primary-withdrawal-address", url.Values{ + "address": {withdrawalAddress.Hex()}, + "confirm": {strconv.FormatBool(confirm)}, + }) if err != nil { return api.SetNodePrimaryWithdrawalAddressResponse{}, fmt.Errorf("Could not set node primary withdrawal address: %w", err) } @@ -136,7 +143,7 @@ func (c *Client) SetNodePrimaryWithdrawalAddress(withdrawalAddress common.Addres // Checks if the node's primary withdrawal address can be confirmed func (c *Client) CanConfirmNodePrimaryWithdrawalAddress() (api.CanSetNodePrimaryWithdrawalAddressResponse, error) { - responseBytes, err := c.callAPI("node can-confirm-primary-withdrawal-address") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-confirm-primary-withdrawal-address", nil) if err != nil { return api.CanSetNodePrimaryWithdrawalAddressResponse{}, fmt.Errorf("Could not get can confirm node primary withdrawal address: %w", err) } @@ -152,7 +159,7 @@ func (c *Client) CanConfirmNodePrimaryWithdrawalAddress() (api.CanSetNodePrimary // Confirm the node's primary withdrawal address func (c *Client) ConfirmNodePrimaryWithdrawalAddress() (api.SetNodePrimaryWithdrawalAddressResponse, error) { - responseBytes, err := c.callAPI("node confirm-primary-withdrawal-address") + responseBytes, err := c.callHTTPAPI("POST", "/api/node/confirm-primary-withdrawal-address", nil) if err != nil { return api.SetNodePrimaryWithdrawalAddressResponse{}, fmt.Errorf("Could not confirm node primary withdrawal address: %w", err) } @@ -168,7 +175,10 @@ func (c *Client) ConfirmNodePrimaryWithdrawalAddress() (api.SetNodePrimaryWithdr // Checks if the node's RPL withdrawal address can be set func (c *Client) CanSetNodeRPLWithdrawalAddress(withdrawalAddress common.Address, confirm bool) (api.CanSetNodeRPLWithdrawalAddressResponse, error) { - responseBytes, err := c.callAPI("node can-set-rpl-withdrawal-address", withdrawalAddress.Hex(), strconv.FormatBool(confirm)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-set-rpl-withdrawal-address", url.Values{ + "address": {withdrawalAddress.Hex()}, + "confirm": {strconv.FormatBool(confirm)}, + }) if err != nil { return api.CanSetNodeRPLWithdrawalAddressResponse{}, fmt.Errorf("Could not get can set node RPL withdrawal address: %w", err) } @@ -184,7 +194,10 @@ func (c *Client) CanSetNodeRPLWithdrawalAddress(withdrawalAddress common.Address // Set the node's RPL withdrawal address func (c *Client) SetNodeRPLWithdrawalAddress(withdrawalAddress common.Address, confirm bool) (api.SetNodeRPLWithdrawalAddressResponse, error) { - responseBytes, err := c.callAPI("node set-rpl-withdrawal-address", withdrawalAddress.Hex(), strconv.FormatBool(confirm)) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/set-rpl-withdrawal-address", url.Values{ + "address": {withdrawalAddress.Hex()}, + "confirm": {strconv.FormatBool(confirm)}, + }) if err != nil { return api.SetNodeRPLWithdrawalAddressResponse{}, fmt.Errorf("Could not set node RPL withdrawal address: %w", err) } @@ -200,7 +213,7 @@ func (c *Client) SetNodeRPLWithdrawalAddress(withdrawalAddress common.Address, c // Checks if the node's RPL withdrawal address can be confirmed func (c *Client) CanConfirmNodeRPLWithdrawalAddress() (api.CanSetNodeRPLWithdrawalAddressResponse, error) { - responseBytes, err := c.callAPI("node can-confirm-rpl-withdrawal-address") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-confirm-rpl-withdrawal-address", nil) if err != nil { return api.CanSetNodeRPLWithdrawalAddressResponse{}, fmt.Errorf("Could not get can confirm node RPL withdrawal address: %w", err) } @@ -216,7 +229,7 @@ func (c *Client) CanConfirmNodeRPLWithdrawalAddress() (api.CanSetNodeRPLWithdraw // Confirm the node's RPL withdrawal address func (c *Client) ConfirmNodeRPLWithdrawalAddress() (api.SetNodeRPLWithdrawalAddressResponse, error) { - responseBytes, err := c.callAPI("node confirm-rpl-withdrawal-address") + responseBytes, err := c.callHTTPAPI("POST", "/api/node/confirm-rpl-withdrawal-address", nil) if err != nil { return api.SetNodeRPLWithdrawalAddressResponse{}, fmt.Errorf("Could not confirm node RPL withdrawal address: %w", err) } @@ -232,7 +245,7 @@ func (c *Client) ConfirmNodeRPLWithdrawalAddress() (api.SetNodeRPLWithdrawalAddr // Checks if the node's timezone location can be set func (c *Client) CanSetNodeTimezone(timezoneLocation string) (api.CanSetNodeTimezoneResponse, error) { - responseBytes, err := c.callAPI("node can-set-timezone", timezoneLocation) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-set-timezone", url.Values{"timezoneLocation": {timezoneLocation}}) if err != nil { return api.CanSetNodeTimezoneResponse{}, fmt.Errorf("Could not get can set node timezone: %w", err) } @@ -248,7 +261,7 @@ func (c *Client) CanSetNodeTimezone(timezoneLocation string) (api.CanSetNodeTime // Set the node's timezone location func (c *Client) SetNodeTimezone(timezoneLocation string) (api.SetNodeTimezoneResponse, error) { - responseBytes, err := c.callAPI("node set-timezone", timezoneLocation) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/set-timezone", url.Values{"timezoneLocation": {timezoneLocation}}) if err != nil { return api.SetNodeTimezoneResponse{}, fmt.Errorf("Could not set node timezone: %w", err) } @@ -264,7 +277,7 @@ func (c *Client) SetNodeTimezone(timezoneLocation string) (api.SetNodeTimezoneRe // Check whether the node can swap RPL tokens func (c *Client) CanNodeSwapRpl(amountWei *big.Int) (api.CanNodeSwapRplResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-swap-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-swap-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanNodeSwapRplResponse{}, fmt.Errorf("Could not get can node swap RPL status: %w", err) } @@ -280,7 +293,7 @@ func (c *Client) CanNodeSwapRpl(amountWei *big.Int) (api.CanNodeSwapRplResponse, // Get the gas estimate for approving legacy RPL interaction func (c *Client) NodeSwapRplApprovalGas(amountWei *big.Int) (api.NodeSwapRplApproveGasResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node get-swap-rpl-approval-gas %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-swap-rpl-approval-gas", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeSwapRplApproveGasResponse{}, fmt.Errorf("Could not get old RPL approval gas: %w", err) } @@ -296,7 +309,7 @@ func (c *Client) NodeSwapRplApprovalGas(amountWei *big.Int) (api.NodeSwapRplAppr // Approves old RPL for a token swap func (c *Client) NodeSwapRplApprove(amountWei *big.Int) (api.NodeSwapRplApproveResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node swap-rpl-approve-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/swap-rpl-approve-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeSwapRplApproveResponse{}, fmt.Errorf("Could not approve old RPL: %w", err) } @@ -312,7 +325,10 @@ func (c *Client) NodeSwapRplApprove(amountWei *big.Int) (api.NodeSwapRplApproveR // Swap node's old RPL tokens for new RPL tokens, waiting for the approval to be included in a block first func (c *Client) NodeWaitAndSwapRpl(amountWei *big.Int, approvalTxHash common.Hash) (api.NodeSwapRplSwapResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node wait-and-swap-rpl %s %s", amountWei.String(), approvalTxHash.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/wait-and-swap-rpl", url.Values{ + "amountWei": {amountWei.String()}, + "approvalTxHash": {approvalTxHash.Hex()}, + }) if err != nil { return api.NodeSwapRplSwapResponse{}, fmt.Errorf("Could not swap node's RPL tokens: %w", err) } @@ -328,7 +344,7 @@ func (c *Client) NodeWaitAndSwapRpl(amountWei *big.Int, approvalTxHash common.Ha // Swap node's old RPL tokens for new RPL tokens func (c *Client) NodeSwapRpl(amountWei *big.Int) (api.NodeSwapRplSwapResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node swap-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/swap-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeSwapRplSwapResponse{}, fmt.Errorf("Could not swap node's RPL tokens: %w", err) } @@ -344,7 +360,7 @@ func (c *Client) NodeSwapRpl(amountWei *big.Int) (api.NodeSwapRplSwapResponse, e // Get a node's legacy RPL allowance for swapping on the new RPL contract func (c *Client) GetNodeSwapRplAllowance() (api.NodeSwapRplAllowanceResponse, error) { - responseBytes, err := c.callAPI("node swap-rpl-allowance") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/swap-rpl-allowance", nil) if err != nil { return api.NodeSwapRplAllowanceResponse{}, fmt.Errorf("Could not get node swap RPL allowance: %w", err) } @@ -360,7 +376,7 @@ func (c *Client) GetNodeSwapRplAllowance() (api.NodeSwapRplAllowanceResponse, er // Check whether the node can stake RPL func (c *Client) CanNodeStakeRpl(amountWei *big.Int) (api.CanNodeStakeRplResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-stake-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-stake-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanNodeStakeRplResponse{}, fmt.Errorf("Could not get can node stake RPL status: %w", err) } @@ -376,7 +392,7 @@ func (c *Client) CanNodeStakeRpl(amountWei *big.Int) (api.CanNodeStakeRplRespons // Get the gas estimate for approving new RPL interaction func (c *Client) NodeStakeRplApprovalGas(amountWei *big.Int) (api.NodeStakeRplApproveGasResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node get-stake-rpl-approval-gas %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-stake-rpl-approval-gas", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeStakeRplApproveGasResponse{}, fmt.Errorf("Could not get new RPL approval gas: %w", err) } @@ -392,7 +408,7 @@ func (c *Client) NodeStakeRplApprovalGas(amountWei *big.Int) (api.NodeStakeRplAp // Approve RPL for staking against the node func (c *Client) NodeStakeRplApprove(amountWei *big.Int) (api.NodeStakeRplApproveResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node stake-rpl-approve-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/stake-rpl-approve-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeStakeRplApproveResponse{}, fmt.Errorf("Could not approve RPL for staking: %w", err) } @@ -408,7 +424,10 @@ func (c *Client) NodeStakeRplApprove(amountWei *big.Int) (api.NodeStakeRplApprov // Stake RPL against the node waiting for approvalTxHash to be included in a block first func (c *Client) NodeWaitAndStakeRpl(amountWei *big.Int, approvalTxHash common.Hash) (api.NodeStakeRplStakeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node wait-and-stake-rpl %s %s", amountWei.String(), approvalTxHash.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/wait-and-stake-rpl", url.Values{ + "amountWei": {amountWei.String()}, + "approvalTxHash": {approvalTxHash.Hex()}, + }) if err != nil { return api.NodeStakeRplStakeResponse{}, fmt.Errorf("Could not stake node RPL: %w", err) } @@ -424,7 +443,7 @@ func (c *Client) NodeWaitAndStakeRpl(amountWei *big.Int, approvalTxHash common.H // Stake RPL against the node func (c *Client) NodeStakeRpl(amountWei *big.Int) (api.NodeStakeRplStakeResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node stake-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/stake-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeStakeRplStakeResponse{}, fmt.Errorf("Could not stake node RPL: %w", err) } @@ -440,7 +459,7 @@ func (c *Client) NodeStakeRpl(amountWei *big.Int) (api.NodeStakeRplStakeResponse // Get a node's RPL allowance for the staking contract func (c *Client) GetNodeStakeRplAllowance() (api.NodeStakeRplAllowanceResponse, error) { - responseBytes, err := c.callAPI("node stake-rpl-allowance") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/stake-rpl-allowance", nil) if err != nil { return api.NodeStakeRplAllowanceResponse{}, fmt.Errorf("Could not get node stake RPL allowance: %w", err) } @@ -456,7 +475,7 @@ func (c *Client) GetNodeStakeRplAllowance() (api.NodeStakeRplAllowanceResponse, // Checks if the node operator can set RPL locking allowed func (c *Client) CanSetRPLLockingAllowed(allowed bool) (api.CanSetRplLockingAllowedResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-set-rpl-locking-allowed %t", allowed)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-set-rpl-locking-allowed", url.Values{"allowed": {strconv.FormatBool(allowed)}}) if err != nil { return api.CanSetRplLockingAllowedResponse{}, fmt.Errorf("Could not get can set RPL locking allowed: %w", err) } @@ -472,7 +491,7 @@ func (c *Client) CanSetRPLLockingAllowed(allowed bool) (api.CanSetRplLockingAllo // Sets the allow state for the node to lock RPL func (c *Client) SetRPLLockingAllowed(allowed bool) (api.SetRplLockingAllowedResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node set-rpl-locking-allowed %t", allowed)) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/set-rpl-locking-allowed", url.Values{"allowed": {strconv.FormatBool(allowed)}}) if err != nil { return api.SetRplLockingAllowedResponse{}, fmt.Errorf("Could not set RPL locking allowed: %w", err) } @@ -488,7 +507,10 @@ func (c *Client) SetRPLLockingAllowed(allowed bool) (api.SetRplLockingAllowedRes // Checks if the node operator can set RPL stake for allowed func (c *Client) CanSetStakeRPLForAllowed(caller common.Address, allowed bool) (api.CanSetStakeRplForAllowedResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-set-stake-rpl-for-allowed %s %t", caller.Hex(), allowed)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-set-stake-rpl-for-allowed", url.Values{ + "caller": {caller.Hex()}, + "allowed": {strconv.FormatBool(allowed)}, + }) if err != nil { return api.CanSetStakeRplForAllowedResponse{}, fmt.Errorf("Could not get can set stake RPL for allowed: %w", err) } @@ -504,7 +526,10 @@ func (c *Client) CanSetStakeRPLForAllowed(caller common.Address, allowed bool) ( // Sets the allow state of another address staking on behalf of the node func (c *Client) SetStakeRPLForAllowed(caller common.Address, allowed bool) (api.SetStakeRplForAllowedResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node set-stake-rpl-for-allowed %s %t", caller.Hex(), allowed)) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/set-stake-rpl-for-allowed", url.Values{ + "caller": {caller.Hex()}, + "allowed": {strconv.FormatBool(allowed)}, + }) if err != nil { return api.SetStakeRplForAllowedResponse{}, fmt.Errorf("Could not set stake RPL for allowed: %w", err) } @@ -520,7 +545,7 @@ func (c *Client) SetStakeRPLForAllowed(caller common.Address, allowed bool) (api // Check whether the node can withdraw RPL func (c *Client) CanNodeWithdrawRpl() (api.CanNodeWithdrawRplResponse, error) { - responseBytes, err := c.callAPI("node can-withdraw-rpl") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-withdraw-rpl", nil) if err != nil { return api.CanNodeWithdrawRplResponse{}, fmt.Errorf("Could not get can node withdraw RPL status: %w", err) } @@ -536,7 +561,7 @@ func (c *Client) CanNodeWithdrawRpl() (api.CanNodeWithdrawRplResponse, error) { // Withdraw RPL staked against the node func (c *Client) NodeWithdrawRpl() (api.NodeWithdrawRplResponse, error) { - responseBytes, err := c.callAPI("node withdraw-rpl") + responseBytes, err := c.callHTTPAPI("POST", "/api/node/withdraw-rpl", nil) if err != nil { return api.NodeWithdrawRplResponse{}, fmt.Errorf("Could not withdraw node RPL: %w", err) } @@ -552,7 +577,7 @@ func (c *Client) NodeWithdrawRpl() (api.NodeWithdrawRplResponse, error) { // Check whether the node can unstake legacy RPL func (c *Client) CanNodeUnstakeLegacyRpl(amountWei *big.Int) (api.CanNodeUnstakeLegacyRplResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-unstake-legacy-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-unstake-legacy-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanNodeUnstakeLegacyRplResponse{}, fmt.Errorf("Could not get can node unstake legacy RPL status: %w", err) } @@ -568,7 +593,7 @@ func (c *Client) CanNodeUnstakeLegacyRpl(amountWei *big.Int) (api.CanNodeUnstake // Unstake legacy RPL staked against the node func (c *Client) NodeUnstakeLegacyRpl(amountWei *big.Int) (api.NodeUnstakeLegacyRplResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node unstake-legacy-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/unstake-legacy-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeUnstakeLegacyRplResponse{}, fmt.Errorf("Could not unstake node legacy RPL: %w", err) } @@ -585,7 +610,7 @@ func (c *Client) NodeUnstakeLegacyRpl(amountWei *big.Int) (api.NodeUnstakeLegacy // Check whether the node can withdraw RPL // Used if saturn is not deployed (v1.3.1) func (c *Client) CanNodeWithdrawRplV1_3_1(amountWei *big.Int) (api.CanNodeWithdrawRplv1_3_1Response, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-withdraw-rpl-v131 %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-withdraw-rpl-v131", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanNodeWithdrawRplv1_3_1Response{}, fmt.Errorf("Could not get can node withdraw RPL status: %w", err) } @@ -602,7 +627,7 @@ func (c *Client) CanNodeWithdrawRplV1_3_1(amountWei *big.Int) (api.CanNodeWithdr // Withdraw RPL staked against the node // Used if saturn is not deployed (v1.3.1) func (c *Client) NodeWithdrawRplV1_3_1(amountWei *big.Int) (api.NodeWithdrawRplResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node withdraw-rpl-v131 %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/withdraw-rpl-v131", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeWithdrawRplResponse{}, fmt.Errorf("Could not withdraw node RPL: %w", err) } @@ -618,7 +643,7 @@ func (c *Client) NodeWithdrawRplV1_3_1(amountWei *big.Int) (api.NodeWithdrawRplR // Check whether the node can unstake RPL func (c *Client) CanNodeUnstakeRpl(amountWei *big.Int) (api.CanNodeUnstakeRplResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-unstake-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-unstake-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanNodeUnstakeRplResponse{}, fmt.Errorf("Could not get can node unstake RPL status: %w", err) } @@ -634,7 +659,7 @@ func (c *Client) CanNodeUnstakeRpl(amountWei *big.Int) (api.CanNodeUnstakeRplRes // Unstake RPL staked against the node func (c *Client) NodeUnstakeRpl(amountWei *big.Int) (api.NodeUnstakeRplResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node unstake-rpl %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/unstake-rpl", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeUnstakeRplResponse{}, fmt.Errorf("Could not unstake node RPL: %w", err) } @@ -650,7 +675,7 @@ func (c *Client) NodeUnstakeRpl(amountWei *big.Int) (api.NodeUnstakeRplResponse, // Check whether we can withdraw ETH staked on behalf of the node func (c *Client) CanNodeWithdrawEth(amountWei *big.Int) (api.CanNodeWithdrawEthResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-withdraw-eth %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-withdraw-eth", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanNodeWithdrawEthResponse{}, fmt.Errorf("Could not get can node withdraw ETH status: %w", err) } @@ -666,7 +691,7 @@ func (c *Client) CanNodeWithdrawEth(amountWei *big.Int) (api.CanNodeWithdrawEthR // Withdraw ETH staked on behalf of the node func (c *Client) NodeWithdrawEth(amountWei *big.Int) (api.NodeWithdrawEthResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node withdraw-eth %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/withdraw-eth", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeWithdrawEthResponse{}, fmt.Errorf("Could not withdraw node ETH: %w", err) } @@ -682,7 +707,7 @@ func (c *Client) NodeWithdrawEth(amountWei *big.Int) (api.NodeWithdrawEthRespons // Check whether we can withdraw credit from the node func (c *Client) CanNodeWithdrawCredit(amountWei *big.Int) (api.CanNodeWithdrawCreditResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-withdraw-credit %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-withdraw-credit", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.CanNodeWithdrawCreditResponse{}, fmt.Errorf("Could not get can node withdraw credit status: %w", err) } @@ -698,7 +723,7 @@ func (c *Client) CanNodeWithdrawCredit(amountWei *big.Int) (api.CanNodeWithdrawC // Withdraw credit from the node as rETH func (c *Client) NodeWithdrawCredit(amountWei *big.Int) (api.NodeWithdrawCreditResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node withdraw-credit %s", amountWei.String())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/withdraw-credit", url.Values{"amountWei": {amountWei.String()}}) if err != nil { return api.NodeWithdrawCreditResponse{}, fmt.Errorf("Could not withdraw credit: %w", err) } @@ -714,7 +739,13 @@ func (c *Client) NodeWithdrawCredit(amountWei *big.Int) (api.NodeWithdrawCreditR // Check whether the node can make multiple deposits func (c *Client) CanNodeDeposits(count uint64, amountWei *big.Int, minFee float64, salt *big.Int, expressTickets uint64) (api.CanNodeDepositsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-deposit %s %f %s %d %d", amountWei.String(), minFee, salt.String(), expressTickets, count)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-deposit", url.Values{ + "count": {strconv.FormatUint(count, 10)}, + "amountWei": {amountWei.String()}, + "minFee": {strconv.FormatFloat(minFee, 'f', -1, 64)}, + "salt": {salt.String()}, + "expressTickets": {strconv.FormatUint(expressTickets, 10)}, + }) if err != nil { return api.CanNodeDepositsResponse{}, fmt.Errorf("Could not get can node deposits status: %w", err) } @@ -730,7 +761,15 @@ func (c *Client) CanNodeDeposits(count uint64, amountWei *big.Int, minFee float6 // Make multiple node deposits func (c *Client) NodeDeposits(count uint64, amountWei *big.Int, minFee float64, salt *big.Int, useCreditBalance bool, expressTickets uint64, submit bool) (api.NodeDepositsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node deposit %s %f %s %t %d %t %d", amountWei.String(), minFee, salt.String(), useCreditBalance, expressTickets, submit, count)) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/deposit", url.Values{ + "count": {strconv.FormatUint(count, 10)}, + "amountWei": {amountWei.String()}, + "minFee": {strconv.FormatFloat(minFee, 'f', -1, 64)}, + "salt": {salt.String()}, + "expressTickets": {strconv.FormatUint(expressTickets, 10)}, + "useCreditBalance": {strconv.FormatBool(useCreditBalance)}, + "submit": {strconv.FormatBool(submit)}, + }) if err != nil { return api.NodeDepositsResponse{}, fmt.Errorf("Could not make node deposits: %w", err) } @@ -746,7 +785,11 @@ func (c *Client) NodeDeposits(count uint64, amountWei *big.Int, minFee float64, // Check whether the node can send tokens func (c *Client) CanNodeSend(amountRaw float64, token string, toAddress common.Address) (api.CanNodeSendResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-send %.10f %s %s", amountRaw, token, toAddress.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-send", url.Values{ + "amountRaw": {strconv.FormatFloat(amountRaw, 'f', 10, 64)}, + "token": {token}, + "to": {toAddress.Hex()}, + }) if err != nil { return api.CanNodeSendResponse{}, fmt.Errorf("Could not get can node send status: %w", err) } @@ -762,7 +805,11 @@ func (c *Client) CanNodeSend(amountRaw float64, token string, toAddress common.A // Send tokens from the node to an address func (c *Client) NodeSend(amountRaw float64, token string, toAddress common.Address) (api.NodeSendResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node send %.10f %s %s", amountRaw, token, toAddress.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/send", url.Values{ + "amountRaw": {strconv.FormatFloat(amountRaw, 'f', 10, 64)}, + "token": {token}, + "to": {toAddress.Hex()}, + }) if err != nil { return api.NodeSendResponse{}, fmt.Errorf("Could not send tokens from node: %w", err) } @@ -779,7 +826,10 @@ func (c *Client) NodeSend(amountRaw float64, token string, toAddress common.Addr // Send all tokens of the given type from the node to an address. // Uses the exact on-chain *big.Int balance to avoid float64 rounding errors. func (c *Client) NodeSendAll(token string, toAddress common.Address) (api.NodeSendResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node send-all %s %s", token, toAddress.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/send-all", url.Values{ + "token": {token}, + "to": {toAddress.Hex()}, + }) if err != nil { return api.NodeSendResponse{}, fmt.Errorf("Could not send tokens from node: %w", err) } @@ -795,7 +845,10 @@ func (c *Client) NodeSendAll(token string, toAddress common.Address) (api.NodeSe // Check whether the node can burn tokens func (c *Client) CanNodeBurn(amountWei *big.Int, token string) (api.CanNodeBurnResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-burn %s %s", amountWei.String(), token)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-burn", url.Values{ + "amountWei": {amountWei.String()}, + "token": {token}, + }) if err != nil { return api.CanNodeBurnResponse{}, fmt.Errorf("Could not get can node burn status: %w", err) } @@ -811,7 +864,10 @@ func (c *Client) CanNodeBurn(amountWei *big.Int, token string) (api.CanNodeBurnR // Burn tokens owned by the node for ETH func (c *Client) NodeBurn(amountWei *big.Int, token string) (api.NodeBurnResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node burn %s %s", amountWei.String(), token)) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/burn", url.Values{ + "amountWei": {amountWei.String()}, + "token": {token}, + }) if err != nil { return api.NodeBurnResponse{}, fmt.Errorf("Could not burn tokens owned by node: %w", err) } @@ -827,7 +883,7 @@ func (c *Client) NodeBurn(amountWei *big.Int, token string) (api.NodeBurnRespons // Get node sync progress func (c *Client) NodeSync() (api.NodeSyncProgressResponse, error) { - responseBytes, err := c.callAPI("node sync") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/sync", nil) if err != nil { return api.NodeSyncProgressResponse{}, fmt.Errorf("Could not get node sync: %w", err) } @@ -843,7 +899,7 @@ func (c *Client) NodeSync() (api.NodeSyncProgressResponse, error) { // Check whether the node has RPL rewards available to claim func (c *Client) CanNodeClaimRpl() (api.CanNodeClaimRplResponse, error) { - responseBytes, err := c.callAPI("node can-claim-rpl-rewards") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-claim-rpl-rewards", nil) if err != nil { return api.CanNodeClaimRplResponse{}, fmt.Errorf("Could not get can node claim rpl rewards status: %w", err) } @@ -859,7 +915,7 @@ func (c *Client) CanNodeClaimRpl() (api.CanNodeClaimRplResponse, error) { // Claim available RPL rewards func (c *Client) NodeClaimRpl() (api.NodeClaimRplResponse, error) { - responseBytes, err := c.callAPI("node claim-rpl-rewards") + responseBytes, err := c.callHTTPAPI("POST", "/api/node/claim-rpl-rewards", nil) if err != nil { return api.NodeClaimRplResponse{}, fmt.Errorf("Could not claim rpl rewards: %w", err) } @@ -875,7 +931,7 @@ func (c *Client) NodeClaimRpl() (api.NodeClaimRplResponse, error) { // Get node RPL rewards status func (c *Client) NodeRewards() (api.NodeRewardsResponse, error) { - responseBytes, err := c.callAPI("node rewards") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/rewards", nil) if err != nil { return api.NodeRewardsResponse{}, fmt.Errorf("Could not get node rewards: %w", err) } @@ -891,7 +947,7 @@ func (c *Client) NodeRewards() (api.NodeRewardsResponse, error) { // Get the deposit contract info for Rocket Pool and the Beacon Client func (c *Client) DepositContractInfo() (api.DepositContractInfoResponse, error) { - responseBytes, err := c.callAPI("node deposit-contract-info") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/deposit-contract-info", nil) if err != nil { return api.DepositContractInfoResponse{}, fmt.Errorf("Could not get deposit contract info: %w", err) } @@ -907,7 +963,7 @@ func (c *Client) DepositContractInfo() (api.DepositContractInfoResponse, error) // Get the initialization status of the fee distributor contract func (c *Client) IsFeeDistributorInitialized() (api.NodeIsFeeDistributorInitializedResponse, error) { - responseBytes, err := c.callAPI("node is-fee-distributor-initialized") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/is-fee-distributor-initialized", nil) if err != nil { return api.NodeIsFeeDistributorInitializedResponse{}, fmt.Errorf("Could not get fee distributor initialization status: %w", err) } @@ -923,7 +979,7 @@ func (c *Client) IsFeeDistributorInitialized() (api.NodeIsFeeDistributorInitiali // Get the gas cost for initializing the fee distributor contract func (c *Client) GetInitializeFeeDistributorGas() (api.NodeInitializeFeeDistributorGasResponse, error) { - responseBytes, err := c.callAPI("node get-initialize-fee-distributor-gas") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-initialize-fee-distributor-gas", nil) if err != nil { return api.NodeInitializeFeeDistributorGasResponse{}, fmt.Errorf("Could not get initialize fee distributor gas: %w", err) } @@ -939,7 +995,7 @@ func (c *Client) GetInitializeFeeDistributorGas() (api.NodeInitializeFeeDistribu // Initialize the fee distributor contract func (c *Client) InitializeFeeDistributor() (api.NodeInitializeFeeDistributorResponse, error) { - responseBytes, err := c.callAPI("node initialize-fee-distributor") + responseBytes, err := c.callHTTPAPI("POST", "/api/node/initialize-fee-distributor", nil) if err != nil { return api.NodeInitializeFeeDistributorResponse{}, fmt.Errorf("Could not initialize fee distributor: %w", err) } @@ -955,7 +1011,7 @@ func (c *Client) InitializeFeeDistributor() (api.NodeInitializeFeeDistributorRes // Check if distributing ETH from the node's fee distributor is possible func (c *Client) CanDistribute() (api.NodeCanDistributeResponse, error) { - responseBytes, err := c.callAPI("node can-distribute") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-distribute", nil) if err != nil { return api.NodeCanDistributeResponse{}, fmt.Errorf("Could not get can distribute: %w", err) } @@ -971,7 +1027,7 @@ func (c *Client) CanDistribute() (api.NodeCanDistributeResponse, error) { // Distribute ETH from the node's fee distributor func (c *Client) Distribute() (api.NodeDistributeResponse, error) { - responseBytes, err := c.callAPI("node distribute") + responseBytes, err := c.callHTTPAPI("POST", "/api/node/distribute", nil) if err != nil { return api.NodeDistributeResponse{}, fmt.Errorf("Could not distribute ETH: %w", err) } @@ -987,7 +1043,7 @@ func (c *Client) Distribute() (api.NodeDistributeResponse, error) { // Get info about your eligible rewards periods, including balances and Merkle proofs func (c *Client) GetRewardsInfo() (api.NodeGetRewardsInfoResponse, error) { - responseBytes, err := c.callAPI("node get-rewards-info") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-rewards-info", nil) if err != nil { return api.NodeGetRewardsInfoResponse{}, fmt.Errorf("Could not get rewards info: %w", err) } @@ -1003,11 +1059,11 @@ func (c *Client) GetRewardsInfo() (api.NodeGetRewardsInfoResponse, error) { // Check if the rewards for the given intervals can be claimed func (c *Client) CanNodeClaimRewards(indices []uint64) (api.CanNodeClaimRewardsResponse, error) { - indexStrings := []string{} - for _, index := range indices { - indexStrings = append(indexStrings, fmt.Sprint(index)) + indexStrings := make([]string, len(indices)) + for i, idx := range indices { + indexStrings[i] = strconv.FormatUint(idx, 10) } - responseBytes, err := c.callAPI("node can-claim-rewards", strings.Join(indexStrings, ",")) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-claim-rewards", url.Values{"indices": {strings.Join(indexStrings, ",")}}) if err != nil { return api.CanNodeClaimRewardsResponse{}, fmt.Errorf("Could not check if can claim rewards: %w", err) } @@ -1023,11 +1079,11 @@ func (c *Client) CanNodeClaimRewards(indices []uint64) (api.CanNodeClaimRewardsR // Claim rewards for the given reward intervals func (c *Client) NodeClaimRewards(indices []uint64) (api.NodeClaimRewardsResponse, error) { - indexStrings := []string{} - for _, index := range indices { - indexStrings = append(indexStrings, fmt.Sprint(index)) + indexStrings := make([]string, len(indices)) + for i, idx := range indices { + indexStrings[i] = strconv.FormatUint(idx, 10) } - responseBytes, err := c.callAPI("node claim-rewards", strings.Join(indexStrings, ",")) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/claim-rewards", url.Values{"indices": {strings.Join(indexStrings, ",")}}) if err != nil { return api.NodeClaimRewardsResponse{}, fmt.Errorf("Could not claim rewards: %w", err) } @@ -1043,11 +1099,14 @@ func (c *Client) NodeClaimRewards(indices []uint64) (api.NodeClaimRewardsRespons // Check if the rewards for the given intervals can be claimed, and RPL restaked automatically func (c *Client) CanNodeClaimAndStakeRewards(indices []uint64, stakeAmountWei *big.Int) (api.CanNodeClaimAndStakeRewardsResponse, error) { - indexStrings := []string{} - for _, index := range indices { - indexStrings = append(indexStrings, fmt.Sprint(index)) + indexStrings := make([]string, len(indices)) + for i, idx := range indices { + indexStrings[i] = strconv.FormatUint(idx, 10) } - responseBytes, err := c.callAPI("node can-claim-and-stake-rewards", strings.Join(indexStrings, ","), stakeAmountWei.String()) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-claim-and-stake-rewards", url.Values{ + "indices": {strings.Join(indexStrings, ",")}, + "stakeAmount": {stakeAmountWei.String()}, + }) if err != nil { return api.CanNodeClaimAndStakeRewardsResponse{}, fmt.Errorf("Could not check if can claim and stake rewards: %w", err) } @@ -1063,11 +1122,14 @@ func (c *Client) CanNodeClaimAndStakeRewards(indices []uint64, stakeAmountWei *b // Claim rewards for the given reward intervals and restake RPL automatically func (c *Client) NodeClaimAndStakeRewards(indices []uint64, stakeAmountWei *big.Int) (api.NodeClaimAndStakeRewardsResponse, error) { - indexStrings := []string{} - for _, index := range indices { - indexStrings = append(indexStrings, fmt.Sprint(index)) + indexStrings := make([]string, len(indices)) + for i, idx := range indices { + indexStrings[i] = strconv.FormatUint(idx, 10) } - responseBytes, err := c.callAPI("node claim-and-stake-rewards", strings.Join(indexStrings, ","), stakeAmountWei.String()) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/claim-and-stake-rewards", url.Values{ + "indices": {strings.Join(indexStrings, ",")}, + "stakeAmount": {stakeAmountWei.String()}, + }) if err != nil { return api.NodeClaimAndStakeRewardsResponse{}, fmt.Errorf("Could not claim and stake rewards: %w", err) } @@ -1083,7 +1145,7 @@ func (c *Client) NodeClaimAndStakeRewards(indices []uint64, stakeAmountWei *big. // Check whether or not the node is opted into the Smoothing Pool func (c *Client) NodeGetSmoothingPoolRegistrationStatus() (api.GetSmoothingPoolRegistrationStatusResponse, error) { - responseBytes, err := c.callAPI("node get-smoothing-pool-registration-status") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-smoothing-pool-registration-status", nil) if err != nil { return api.GetSmoothingPoolRegistrationStatusResponse{}, fmt.Errorf("Could not get smoothing pool registration status: %w", err) } @@ -1099,7 +1161,7 @@ func (c *Client) NodeGetSmoothingPoolRegistrationStatus() (api.GetSmoothingPoolR // Check if the node's Smoothing Pool status can be changed func (c *Client) CanNodeSetSmoothingPoolStatus(status bool) (api.CanSetSmoothingPoolRegistrationStatusResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-set-smoothing-pool-status %t", status)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-set-smoothing-pool-status", url.Values{"status": {strconv.FormatBool(status)}}) if err != nil { return api.CanSetSmoothingPoolRegistrationStatusResponse{}, fmt.Errorf("Could not get can-set-smoothing-pool-status: %w", err) } @@ -1115,7 +1177,7 @@ func (c *Client) CanNodeSetSmoothingPoolStatus(status bool) (api.CanSetSmoothing // Sets the node's Smoothing Pool opt-in status func (c *Client) NodeSetSmoothingPoolStatus(status bool) (api.SetSmoothingPoolRegistrationStatusResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node set-smoothing-pool-status %t", status)) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/set-smoothing-pool-status", url.Values{"status": {strconv.FormatBool(status)}}) if err != nil { return api.SetSmoothingPoolRegistrationStatusResponse{}, fmt.Errorf("Could not set smoothing pool status: %w", err) } @@ -1130,7 +1192,7 @@ func (c *Client) NodeSetSmoothingPoolStatus(status bool) (api.SetSmoothingPoolRe } func (c *Client) ResolveEnsName(name string) (api.ResolveEnsNameResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node resolve-ens-name %s", name)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/resolve-ens-name", url.Values{"name": {name}}) if err != nil { return api.ResolveEnsNameResponse{}, fmt.Errorf("Could not resolve ENS name: %w", err) } @@ -1143,8 +1205,9 @@ func (c *Client) ResolveEnsName(name string) (api.ResolveEnsNameResponse, error) } return response, nil } + func (c *Client) ReverseResolveEnsName(name string) (api.ResolveEnsNameResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node reverse-resolve-ens-name %s", name)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/reverse-resolve-ens-name", url.Values{"address": {name}}) if err != nil { return api.ResolveEnsNameResponse{}, fmt.Errorf("Could not reverse resolve ENS name: %w", err) } @@ -1162,7 +1225,7 @@ func (c *Client) ReverseResolveEnsName(name string) (api.ResolveEnsNameResponse, func (c *Client) SignMessage(message string) (api.NodeSignResponse, error) { // Ignore sync status so we can sign messages even without ready clients c.ignoreSyncCheck = true - responseBytes, err := c.callAPI("node sign-message", message) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/sign-message", url.Values{"message": {message}}) if err != nil { return api.NodeSignResponse{}, fmt.Errorf("Could not sign message: %w", err) } @@ -1179,7 +1242,7 @@ func (c *Client) SignMessage(message string) (api.NodeSignResponse, error) { // Get the node's collateral info, including pending bond reductions func (c *Client) CheckCollateral() (api.CheckCollateralResponse, error) { - responseBytes, err := c.callAPI("node check-collateral") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/check-collateral", nil) if err != nil { return api.CheckCollateralResponse{}, fmt.Errorf("Could not get check-collateral status: %w", err) } @@ -1195,7 +1258,7 @@ func (c *Client) CheckCollateral() (api.CheckCollateralResponse, error) { // Get the ETH balance of the node address func (c *Client) GetEthBalance() (api.NodeEthBalanceResponse, error) { - responseBytes, err := c.callAPI("node get-eth-balance") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-eth-balance", nil) if err != nil { return api.NodeEthBalanceResponse{}, fmt.Errorf("Could not get get-eth-balance status: %w", err) } @@ -1211,7 +1274,10 @@ func (c *Client) GetEthBalance() (api.NodeEthBalanceResponse, error) { // Estimates the gas for sending a zero-value message with a payload func (c *Client) CanSendMessage(address common.Address, message []byte) (api.CanNodeSendMessageResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-send-message %s %s", address.Hex(), hex.EncodeToString(message))) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-send-message", url.Values{ + "address": {address.Hex()}, + "message": {hex.EncodeToString(message)}, + }) if err != nil { return api.CanNodeSendMessageResponse{}, fmt.Errorf("Could not get can-send-message response: %w", err) } @@ -1227,7 +1293,10 @@ func (c *Client) CanSendMessage(address common.Address, message []byte) (api.Can // Sends a zero-value message with a payload func (c *Client) SendMessage(address common.Address, message []byte) (api.NodeSendMessageResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node send-message %s %s", address.Hex(), hex.EncodeToString(message))) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/send-message", url.Values{ + "address": {address.Hex()}, + "message": {hex.EncodeToString(message)}, + }) if err != nil { return api.NodeSendMessageResponse{}, fmt.Errorf("Could not get send-message response: %w", err) } @@ -1243,7 +1312,7 @@ func (c *Client) SendMessage(address common.Address, message []byte) (api.NodeSe // Get the number of express tickets available for the node func (c *Client) GetExpressTicketCount() (api.GetExpressTicketCountResponse, error) { - responseBytes, err := c.callAPI("node get-express-ticket-count") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-express-ticket-count", nil) if err != nil { return api.GetExpressTicketCountResponse{}, fmt.Errorf("Could not get express ticket count: %w", err) } @@ -1259,7 +1328,7 @@ func (c *Client) GetExpressTicketCount() (api.GetExpressTicketCountResponse, err // Check if the node's express tickets have been provisioned func (c *Client) GetExpressTicketsProvisioned() (api.GetExpressTicketsProvisionedResponse, error) { - responseBytes, err := c.callAPI("node get-express-tickets-provisioned") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-express-tickets-provisioned", nil) if err != nil { return api.GetExpressTicketsProvisionedResponse{}, fmt.Errorf("Could not get express tickets provisioned: %w", err) } @@ -1274,7 +1343,7 @@ func (c *Client) GetExpressTicketsProvisioned() (api.GetExpressTicketsProvisione } func (c *Client) CanProvisionExpressTickets() (api.CanProvisionExpressTicketsResponse, error) { - responseBytes, err := c.callAPI("node can-provision-express-tickets") + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-provision-express-tickets", nil) if err != nil { return api.CanProvisionExpressTicketsResponse{}, fmt.Errorf("Could not get can-provision-express-tickets response: %w", err) } @@ -1289,7 +1358,7 @@ func (c *Client) CanProvisionExpressTickets() (api.CanProvisionExpressTicketsRes } func (c *Client) ProvisionExpressTickets() (api.ProvisionExpressTicketsResponse, error) { - responseBytes, err := c.callAPI("node provision-express-tickets") + responseBytes, err := c.callHTTPAPI("POST", "/api/node/provision-express-tickets", nil) if err != nil { return api.ProvisionExpressTicketsResponse{}, fmt.Errorf("Could not get provision-express-tickets response: %w", err) } @@ -1305,7 +1374,7 @@ func (c *Client) ProvisionExpressTickets() (api.ProvisionExpressTicketsResponse, // Check whether the node can claim unclaimed rewards func (c *Client) CanClaimUnclaimedRewards(nodeAddress common.Address) (api.CanClaimUnclaimedRewardsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node can-claim-unclaimed-rewards %s", nodeAddress.Hex())) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/can-claim-unclaimed-rewards", url.Values{"nodeAddress": {nodeAddress.Hex()}}) if err != nil { return api.CanClaimUnclaimedRewardsResponse{}, fmt.Errorf("Could not get can-claim-unclaimed-rewards response: %w", err) } @@ -1321,7 +1390,7 @@ func (c *Client) CanClaimUnclaimedRewards(nodeAddress common.Address) (api.CanCl // Send unclaimed rewards to a node operator's withdrawal address func (c *Client) ClaimUnclaimedRewards(nodeAddress common.Address) (api.ClaimUnclaimedRewardsResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node claim-unclaimed-rewards %s", nodeAddress.Hex())) + responseBytes, err := c.callHTTPAPI("POST", "/api/node/claim-unclaimed-rewards", url.Values{"nodeAddress": {nodeAddress.Hex()}}) if err != nil { return api.ClaimUnclaimedRewardsResponse{}, fmt.Errorf("Could not get claim-unclaimed-rewards response: %w", err) } @@ -1337,7 +1406,7 @@ func (c *Client) ClaimUnclaimedRewards(nodeAddress common.Address) (api.ClaimUnc // Get the bond requirement for a number of validators func (c *Client) GetBondRequirement(numValidators uint64) (api.GetBondRequirementResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("node get-bond-requirement %d", numValidators)) + responseBytes, err := c.callHTTPAPI("GET", "/api/node/get-bond-requirement", url.Values{"numValidators": {strconv.FormatUint(numValidators, 10)}}) if err != nil { return api.GetBondRequirementResponse{}, fmt.Errorf("Could not get get-bond-requirement response: %w", err) } From e097fab54e59903e774f31515f7d8634753560aa Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:31:11 -0300 Subject: [PATCH 08/24] Remove old commands --- rocketpool/api/api.go | 115 -- rocketpool/api/auction/commands.go | 235 --- rocketpool/api/debug/commands.go | 100 -- rocketpool/api/megapool/commands.go | 730 ---------- rocketpool/api/minipool/commands.go | 596 -------- rocketpool/api/network/commands.go | 203 --- rocketpool/api/node/commands.go | 1820 ------------------------ rocketpool/api/odao/commands.go | 1140 --------------- rocketpool/api/pdao/commands.go | 1152 --------------- rocketpool/api/queue/commands.go | 149 -- rocketpool/api/security/commands.go | 419 ------ rocketpool/api/service/commands.go | 90 -- rocketpool/api/wait.go | 29 + rocketpool/api/wallet/commands.go | 353 ----- rocketpool/node/routes/routes.go | 2 + rocketpool/rocketpool.go | 18 +- shared/services/rocketpool/api.go | 3 +- shared/services/rocketpool/client.go | 10 +- shared/services/rocketpool/node.go | 2 - shared/services/rocketpool/odao.go | 85 -- shared/services/rocketpool/security.go | 141 -- shared/utils/api/http.go | 6 +- shared/utils/api/response.go | 65 +- shared/version.txt | 2 +- 24 files changed, 41 insertions(+), 7424 deletions(-) delete mode 100644 rocketpool/api/auction/commands.go delete mode 100644 rocketpool/api/debug/commands.go delete mode 100644 rocketpool/api/megapool/commands.go delete mode 100644 rocketpool/api/minipool/commands.go delete mode 100644 rocketpool/api/network/commands.go delete mode 100644 rocketpool/api/node/commands.go delete mode 100644 rocketpool/api/odao/commands.go delete mode 100644 rocketpool/api/pdao/commands.go delete mode 100644 rocketpool/api/queue/commands.go delete mode 100644 rocketpool/api/security/commands.go delete mode 100644 rocketpool/api/service/commands.go create mode 100644 rocketpool/api/wait.go delete mode 100644 rocketpool/api/wallet/commands.go diff --git a/rocketpool/api/api.go b/rocketpool/api/api.go index a8dc437cf..778f64ec1 100644 --- a/rocketpool/api/api.go +++ b/rocketpool/api/api.go @@ -1,116 +1 @@ package api - -import ( - "context" - "net/http" - - "github.com/ethereum/go-ethereum/common" - "github.com/rocket-pool/smartnode/rocketpool/api/debug" - "github.com/rocket-pool/smartnode/rocketpool/api/megapool" - "github.com/rocket-pool/smartnode/rocketpool/api/pdao" - "github.com/rocket-pool/smartnode/rocketpool/api/security" - "github.com/rocket-pool/smartnode/rocketpool/api/upgrade" - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/bindings/utils" - "github.com/rocket-pool/smartnode/rocketpool/api/auction" - "github.com/rocket-pool/smartnode/rocketpool/api/minipool" - "github.com/rocket-pool/smartnode/rocketpool/api/network" - "github.com/rocket-pool/smartnode/rocketpool/api/node" - "github.com/rocket-pool/smartnode/rocketpool/api/odao" - "github.com/rocket-pool/smartnode/rocketpool/api/queue" - apiservice "github.com/rocket-pool/smartnode/rocketpool/api/service" - "github.com/rocket-pool/smartnode/rocketpool/api/wallet" - "github.com/rocket-pool/smartnode/shared/services" - apitypes "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -const ( - MaxConcurrentEth1Requests = 200 -) - -// Waits for an auction transaction -func waitForTransaction(c *cli.Command, hash common.Hash) (*apitypes.APIResponse, error) { - - rp, err := services.GetRocketPool(c) - if err != nil { - return nil, err - } - - // Response - response := apitypes.APIResponse{} - _, err = utils.WaitForTransaction(rp.Client, hash) - if err != nil { - return nil, err - } - - // Return response - return &response, nil - -} - -// Register commands -func RegisterCommands(app *cli.Command, name string, aliases []string) { - - // CLI command - command := cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Run Rocket Pool API commands", - Commands: []*cli.Command{}, - } - - // Don't show help message for api errors because of JSON serialisation - command.OnUsageError = func(ctx context.Context, c *cli.Command, err error, isSubcommand bool) error { - return err - } - - // Register subcommands - auction.RegisterSubcommands(&command, "auction", []string{"a"}) - megapool.RegisterSubcommands(&command, "megapool", []string{"g"}) - minipool.RegisterSubcommands(&command, "minipool", []string{"m"}) - megapool.RegisterSubcommands(&command, "megapool", []string{"g"}) - network.RegisterSubcommands(&command, "network", []string{"e"}) - node.RegisterSubcommands(&command, "node", []string{"n"}) - odao.RegisterSubcommands(&command, "odao", []string{"o"}) - pdao.RegisterSubcommands(&command, "pdao", []string{"p"}) - queue.RegisterSubcommands(&command, "queue", []string{"q"}) - security.RegisterSubcommands(&command, "security", []string{"c"}) - apiservice.RegisterSubcommands(&command, "service", []string{"s"}) - wallet.RegisterSubcommands(&command, "wallet", []string{"w"}) - upgrade.RegisterSubcommands(&command, "upgrade", []string{"u"}) - debug.RegisterSubcommands(&command, "debug", []string{"d"}) - - // Append a general wait-for-transaction command to support async operations - command.Commands = append(command.Commands, &cli.Command{ - Name: "wait", - Aliases: []string{"t"}, - Usage: "Wait for a transaction to complete", - UsageText: "rocketpool api wait tx-hash", - Action: func(ctx context.Context, c *cli.Command) error { - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - hash, err := cliutils.ValidateTxHash("tx-hash", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(waitForTransaction(c, hash)) - return nil - }, - }) - - // Register CLI command - app.Commands = append(app.Commands, &command) - - // The daemon makes a large number of concurrent RPC requests to the Eth1 client - // The HTTP transport is set to cache connections for future re-use equal to the maximum expected number of concurrent requests - // This prevents issues related to memory consumption and address allowance from repeatedly opening and closing connections - http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = MaxConcurrentEth1Requests - -} diff --git a/rocketpool/api/auction/commands.go b/rocketpool/api/auction/commands.go deleted file mode 100644 index 5f6b72d7d..000000000 --- a/rocketpool/api/auction/commands.go +++ /dev/null @@ -1,235 +0,0 @@ -package auction - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage Rocket Pool RPL auctions", - Commands: []*cli.Command{ - - { - Name: "status", - Aliases: []string{"s"}, - Usage: "Get RPL auction status", - UsageText: "rocketpool api auction status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c)) - return nil - - }, - }, - - { - Name: "lots", - Aliases: []string{"l"}, - Usage: "Get RPL lots for auction", - UsageText: "rocketpool api auction lots", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getLots(c)) - return nil - - }, - }, - - { - Name: "can-create-lot", - Usage: "Check whether the node can create a new lot", - UsageText: "rocketpool api auction can-create-lot", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canCreateLot(c)) - return nil - - }, - }, - { - Name: "create-lot", - Aliases: []string{"t"}, - Usage: "Create a new lot", - UsageText: "rocketpool api auction create-lot", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(createLot(c)) - return nil - - }, - }, - - { - Name: "can-bid-lot", - Usage: "Check whether the node can bid on a lot", - UsageText: "rocketpool api auction can-bid-lot lot-id amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - lotIndex, err := cliutils.ValidateUint("lot ID", c.Args().Get(0)) - if err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("bid amount", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canBidOnLot(c, lotIndex, amountWei)) - return nil - - }, - }, - { - Name: "bid-lot", - Aliases: []string{"b"}, - Usage: "Bid on a lot", - UsageText: "rocketpool api auction bid-lot lot-id amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - lotIndex, err := cliutils.ValidateUint("lot ID", c.Args().Get(0)) - if err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("bid amount", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(bidOnLot(c, lotIndex, amountWei)) - return nil - - }, - }, - - { - Name: "can-claim-lot", - Usage: "Check whether the node can claim RPL from a lot", - UsageText: "rocketpool api auction can-claim-lot lot-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - lotIndex, err := cliutils.ValidateUint("lot ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canClaimFromLot(c, lotIndex)) - return nil - - }, - }, - { - Name: "claim-lot", - Aliases: []string{"c"}, - Usage: "Claim RPL from a lot", - UsageText: "rocketpool api auction claim-lot lot-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - lotIndex, err := cliutils.ValidateUint("lot ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(claimFromLot(c, lotIndex)) - return nil - - }, - }, - - { - Name: "can-recover-lot", - Usage: "Check whether the node can recover unclaimed RPL from a lot", - UsageText: "rocketpool api auction can-recover-lot lot-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - lotIndex, err := cliutils.ValidateUint("lot ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canRecoverRplFromLot(c, lotIndex)) - return nil - - }, - }, - { - Name: "recover-lot", - Aliases: []string{"r"}, - Usage: "Recover unclaimed RPL from a lot (returning it to the auction contract)", - UsageText: "rocketpool api auction recover-lot lot-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - lotIndex, err := cliutils.ValidateUint("lot ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(recoverRplFromLot(c, lotIndex)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/debug/commands.go b/rocketpool/api/debug/commands.go deleted file mode 100644 index c1dddf7ef..000000000 --- a/rocketpool/api/debug/commands.go +++ /dev/null @@ -1,100 +0,0 @@ -package debug - -import ( - "context" - "fmt" - - "github.com/urfave/cli/v3" - - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Debugging and troubleshooting commands", - Commands: []*cli.Command{ - - { - Name: "export-validators", - Aliases: []string{"x"}, - Usage: "Exports a TSV file of validators", - UsageText: "rocketpool api debug export-validators", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Export TSV of validators - if err := ExportValidators(c); err != nil { - fmt.Printf("An error occurred: %s\n", err) - } - return nil - - }, - }, - { - Name: "get-beacon-state", - Aliases: []string{"b"}, - Usage: "Returns the beacon state for a given slot number", - UsageText: "rocketpool api debug get-beacon-state slot-number validator-index", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - - slotNumber, err := cliutils.ValidatePositiveUint("slot number", c.Args().Get(0)) - if err != nil { - return err - } - - validatorIndex, err := cliutils.ValidatePositiveUint("validator index", c.Args().Get(1)) - if err != nil { - return err - } - - if err := getBeaconStateForSlot(c, slotNumber, validatorIndex); err != nil { - fmt.Printf("An error occurred: %s\n", err) - } - return nil - - }, - }, - { - Name: "get-withdrawal-proof", - Aliases: []string{"w"}, - Usage: "Returns a withdrawal proof for a given validator index and given slot, for the withdrawal most recent to that slot", - UsageText: "rocketpool api debug get-withdrawal-proof slot-number validator-index", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - - slotNumber, err := cliutils.ValidatePositiveUint("slot number", c.Args().Get(0)) - if err != nil { - return err - } - - validatorIndex, err := cliutils.ValidatePositiveUint("validator index", c.Args().Get(1)) - if err != nil { - return err - } - - if err := getWithdrawalProofForSlot(c, slotNumber, validatorIndex); err != nil { - fmt.Printf("An error occurred: %s\n", err) - } - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/megapool/commands.go b/rocketpool/api/megapool/commands.go deleted file mode 100644 index fc224f6ca..000000000 --- a/rocketpool/api/megapool/commands.go +++ /dev/null @@ -1,730 +0,0 @@ -package megapool - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the node's megapool", - Commands: []*cli.Command{ - { - Name: "can-distribute-megapool", - Usage: "Check if can distribute megapool rewards", - UsageText: "rocketpool api node can-distribute-megapool", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canDistributeMegapool(c)) - return nil - - }, - }, - - { - Name: "distribute-megapool", - Usage: "Distribute megapool rewards", - UsageText: "rocketpool api node distribute-megapool", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(distributeMegapool(c)) - return nil - - }, - }, - { - Name: "status", - Aliases: []string{"s"}, - Usage: "Get the node's megapool status", - UsageText: "rocketpool api megapool status finalized-state", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get finalized state - finalizedState, err := cliutils.ValidateBool("finalized-state", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c, finalizedState)) - return nil - - }, - }, - { - Name: "validator-map-and-balances", - Aliases: []string{"gvm"}, - Usage: "Get a map of the node's validators and beacon balances", - UsageText: "rocketpool api megapool validator-map-and-balances", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getValidatorMapAndBalances(c)) - return nil - - }, - }, - { - Name: "can-repay-debt", - Usage: "Check if we can repay the megapool debt", - UsageText: "rocketpool api megapool can-repay-debt amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get amount - amount, err := cliutils.ValidatePositiveWeiAmount("amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canRepayDebt(c, amount)) - return nil - - }, - }, - { - Name: "repay-debt", - Aliases: []string{"rd"}, - Usage: "Repay the megapool debt", - UsageText: "rocketpool api megapool repay-debt amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get amount - amount, err := cliutils.ValidatePositiveWeiAmount("amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(repayDebt(c, amount)) - return nil - - }, - }, - { - Name: "can-reduce-bond", - Usage: "Check if we can reduce the megapool bond", - UsageText: "rocketpool api megapool can-reduce-bond amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get amount - amount, err := cliutils.ValidatePositiveWeiAmount("amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canReduceBond(c, amount)) - return nil - - }, - }, - { - Name: "reduce-bond", - Aliases: []string{"rb"}, - Usage: "Reduce the megapool bond", - UsageText: "rocketpool api megapool reduce-bond amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get amount - amount, err := cliutils.ValidatePositiveWeiAmount("amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(reduceBond(c, amount)) - return nil - - }, - }, - { - Name: "can-claim-refund", - Usage: "Check if we can claim a megapool refund", - UsageText: "rocketpool api megapool can-claim-refund", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canClaimRefund(c)) - return nil - - }, - }, - { - Name: "claim-refund", - Aliases: []string{"cr"}, - Usage: "Claim a megapool refund", - UsageText: "rocketpool api megapool claim-refund", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(claimRefund(c)) - return nil - - }, - }, - { - Name: "can-stake", - Usage: "Check if we can stake a megapool validator", - UsageText: "rocketpool api megapool can-stake validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get the validatorId - validatorId, err := cliutils.ValidateUint("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canStake(c, validatorId)) - return nil - - }, - }, - { - Name: "stake", - Aliases: []string{"st"}, - Usage: "Stake a megapool validator", - UsageText: "rocketpool api megapool stake validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get validatorId - validatorId, err := cliutils.ValidateUint("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(stake(c, validatorId)) - return nil - - }, - }, - { - Name: "can-exit-queue", - Usage: "Check whether the node can exit the megapool queue", - UsageText: "rocketpool api megapool can-exit-queue validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Check the validator-id - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canExitQueue(c, validatorId)) - return nil - - }, - }, - { - Name: "exit-queue", - Usage: "Exit the megapool queue", - UsageText: "rocketpool api megapool exit-queue validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Check the validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(exitQueue(c, validatorId)) - return nil - - }, - }, - { - Name: "can-dissolve-validator", - Usage: "Check if we can dissolve a megapool validator", - UsageText: "rocketpool api megapool can-dissolve-validator validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get the validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canDissolveValidator(c, validatorId)) - return nil - - }, - }, - { - Name: "dissolve-validator", - Aliases: []string{"dv"}, - Usage: "Dissolve a megapool validator", - UsageText: "rocketpool api megapool dissolve-validator validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(dissolveValidator(c, validatorId)) - return nil - - }, - }, - { - Name: "can-exit-validator", - Usage: "Check if we can exit a megapool validator", - UsageText: "rocketpool api megapool can-exit-validator validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get the validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canExitValidator(c, validatorId)) - return nil - - }, - }, - { - Name: "exit-validator", - Aliases: []string{"ev"}, - Usage: "Exit a megapool validator", - UsageText: "rocketpool api megapool exit-validator validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(exitValidator(c, validatorId)) - return nil - - }, - }, - { - Name: "can-notify-validator-exit", - Usage: "Check if we can notify the exit of a megapool validator", - UsageText: "rocketpool api megapool can-notify-validator-exit validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get the validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNotifyValidatorExit(c, validatorId)) - return nil - - }, - }, - { - Name: "notify-validator-exit", - Aliases: []string{"ev"}, - Usage: "Notify a megapool validator exit", - UsageText: "rocketpool api megapool notify-validator-exit validator-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Get validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(notifyValidatorExit(c, validatorId)) - return nil - - }, - }, - { - Name: "can-notify-final-balance", - Usage: "Check if we can notify the final balance of a megapool validator", - UsageText: "rocketpool api megapool can-notify-final-balance validator-id slot", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - - // Get the validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Get slot - slot, err := cliutils.ValidateUint("slot", c.Args().Get(1)) - if err != nil { - return err - } - // Run - api.PrintResponse(canNotifyFinalBalance(c, validatorId, slot)) - return nil - - }, - }, - { - Name: "notify-final-balance", - Aliases: []string{"ev"}, - Usage: "Notify a megapool validator final balance", - UsageText: "rocketpool api megapool notify-final-balance validator-id slot", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - - // Get validatorId - validatorId, err := cliutils.ValidateUint32("validatorId", c.Args().Get(0)) - if err != nil { - return err - } - - // Get slot - slot, err := cliutils.ValidateUint("slot", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(notifyFinalBalance(c, validatorId, slot)) - return nil - - }, - }, - { - Name: "get-use-latest-delegate", - Usage: "Gets the current setting of the 'always use latest delegate' toggle", - UsageText: "rocketpool api megapool get-use-latest-delegate megapool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getUseLatestDelegate(c, megapoolAddress)) - return nil - - }, - }, - { - Name: "can-set-use-latest-delegate", - Usage: "Check whether the 'always use latest delegate' toggle can be set", - UsageText: "rocketpool api megapool can-set-use-latest-delegate megapool-address use-latest-delegate", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - useLatest, err := cliutils.ValidateBool("use-latest-delegate", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSetUseLatestDelegate(c, megapoolAddress, useLatest)) - return nil - - }, - }, - { - Name: "set-use-latest-delegate", - Usage: "Set to ignore the megapool's current delegate, and always use the latest delegate instead", - UsageText: "rocketpool api megapool set-use-latest-delegate use-latest-delegate", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - useLatest, err := cliutils.ValidateBool("use-latest-delegate", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(setUseLatestDelegate(c, megapoolAddress, useLatest)) - return nil - - }, - }, - { - Name: "get-delegate", - Usage: "Gets the address of the current delegate contract used by the megapool", - UsageText: "rocketpool api megapool get-delegate megapool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getDelegate(c, megapoolAddress)) - return nil - - }, - }, - { - Name: "get-effective-delegate", - Usage: "Gets the address of the effective delegate contract used by the megapool, which takes the UseLatestDelegate setting into account", - UsageText: "rocketpool api megapool get-effective-delegate megapool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getEffectiveDelegate(c, megapoolAddress)) - return nil - - }, - }, - { - Name: "can-delegate-upgrade", - Usage: "Check whether the megapool delegate can be upgraded", - UsageText: "rocketpool api megapool can-delegate-upgrade megapool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canDelegateUpgrade(c, megapoolAddress)) - return nil - - }, - }, - { - Name: "delegate-upgrade", - Usage: "Upgrade this megapool to the latest network delegate contract", - UsageText: "rocketpool api megapool delegate-upgrade megapool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(delegateUpgrade(c, megapoolAddress)) - return nil - - }, - }, - { - Name: "calculate-rewards", - Usage: "Calculate the rewards split given an eth amount", - UsageText: "rocketpool api megapool calculate-rewards amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - // Get amount - amount, err := cliutils.ValidatePositiveWeiAmount("amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(calculateRewards(c, amount)) - return nil - - }, - }, - { - Name: "pending-rewards", - Usage: "Calculate the pending rewards split", - UsageText: "rocketpool api megapool pending-rewards", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - // Run - api.PrintResponse(calculatePendingRewards(c)) - return nil - - }, - }, - { - Name: "get-new-validator-bond-requirement", - Usage: "Get the bond amount required for the megapool's next validator", - UsageText: "rocketpool api megapool get-new-validator-bond-requirement", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - // Run - api.PrintResponse(getNewValidatorBondRequirement(c)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/minipool/commands.go b/rocketpool/api/minipool/commands.go deleted file mode 100644 index e133bacc9..000000000 --- a/rocketpool/api/minipool/commands.go +++ /dev/null @@ -1,596 +0,0 @@ -package minipool - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the node's minipools", - Commands: []*cli.Command{ - - { - Name: "status", - Aliases: []string{"s"}, - Usage: "Get a list of the node's minipools", - UsageText: "rocketpool api minipool status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c)) - return nil - - }, - }, - - { - Name: "can-stake", - Usage: "Check whether the minipool is ready to be staked, moving from prelaunch to staking status", - UsageText: "rocketpool api minipool can-stake minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canStakeMinipool(c, minipoolAddress)) - return nil - - }, - }, - { - Name: "stake", - Aliases: []string{"t"}, - Usage: "Stake the minipool, moving it from prelaunch to staking status", - UsageText: "rocketpool api minipool stake minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(stakeMinipool(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "can-promote", - Usage: "Check whether a vacant minipool is ready to be promoted", - UsageText: "rocketpool api minipool can-promote minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canPromoteMinipool(c, minipoolAddress)) - return nil - - }, - }, - { - Name: "promote", - Usage: "Promote a vacant minipool", - UsageText: "rocketpool api minipool promote minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(promoteMinipool(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "can-refund", - Usage: "Check whether the node can refund ETH from the minipool", - UsageText: "rocketpool api minipool can-refund minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canRefundMinipool(c, minipoolAddress)) - return nil - - }, - }, - { - Name: "refund", - Aliases: []string{"r"}, - Usage: "Refund ETH belonging to the node from a minipool", - UsageText: "rocketpool api minipool refund minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(refundMinipool(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "can-dissolve", - Usage: "Check whether the minipool can be dissolved", - UsageText: "rocketpool api minipool can-dissolve minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canDissolveMinipool(c, minipoolAddress)) - return nil - - }, - }, - { - Name: "dissolve", - Aliases: []string{"d"}, - Usage: "Dissolve an initialized or prelaunch minipool", - UsageText: "rocketpool api minipool dissolve minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(dissolveMinipool(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "can-exit", - Usage: "Check whether the minipool can be exited from the beacon chain", - UsageText: "rocketpool api minipool can-exit minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canExitMinipool(c, minipoolAddress)) - return nil - - }, - }, - { - Name: "exit", - Aliases: []string{"e"}, - Usage: "Exit a staking minipool from the beacon chain", - UsageText: "rocketpool api minipool exit minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(exitMinipool(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "get-minipool-close-details-for-node", - Usage: "Check all of the node's minipools for closure eligibility, and return the details of the closeable ones", - UsageText: "rocketpool api minipool get-minipool-close-details-for-node", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getMinipoolCloseDetailsForNode(c)) - return nil - - }, - }, - { - Name: "close", - Aliases: []string{"c"}, - Usage: "Withdraw balance from a dissolved minipool and close it", - UsageText: "rocketpool api minipool close minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(closeMinipool(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "can-delegate-upgrade", - Usage: "Check whether the minipool delegate can be upgraded", - UsageText: "rocketpool api minipool can-delegate-upgrade minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canDelegateUpgrade(c, minipoolAddress)) - return nil - - }, - }, - { - Name: "delegate-upgrade", - Usage: "Upgrade this minipool to the latest network delegate contract", - UsageText: "rocketpool api minipool delegate-upgrade minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(delegateUpgrade(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "get-use-latest-delegate", - Usage: "Gets the current setting of the 'always use latest delegate' toggle", - UsageText: "rocketpool api minipool get-use-latest-delegate minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getUseLatestDelegate(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "get-delegate", - Usage: "Gets the address of the current delegate contract used by the minipool", - UsageText: "rocketpool api minipool get-delegate minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getDelegate(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "get-effective-delegate", - Usage: "Gets the address of the effective delegate contract used by the minipool, which takes the UseLatestDelegate setting into account", - UsageText: "rocketpool api minipool get-effective-delegate minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getEffectiveDelegate(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "get-vanity-artifacts", - Aliases: []string{"v"}, - Usage: "Gets the data necessary to search for vanity minipool addresses", - UsageText: "rocketpool api minipool get-vanity-artifacts deposit node-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - depositAmount, err := cliutils.ValidatePositiveWeiAmount("deposit amount", c.Args().Get(0)) - if err != nil { - return err - } - nodeAddressStr := c.Args().Get(1) - - // Run - api.PrintResponse(getVanityArtifacts(c, depositAmount, nodeAddressStr)) - return nil - - }, - }, - - { - Name: "get-distribute-balance-details", - Usage: "Get the balance distribution details for all of the node's minipools", - UsageText: "rocketpool api minipool get-distribute-balance-details", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getDistributeBalanceDetails(c)) - return nil - - }, - }, - { - Name: "distribute-balance", - Usage: "Distribute a minipool's ETH balance", - UsageText: "rocketpool api minipool distribute-balance minipool-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(distributeBalance(c, minipoolAddress)) - return nil - - }, - }, - - { - Name: "import-key", - Usage: "Import a validator private key for a vacant minipool", - UsageText: "rocketpool api minipool import-key minipool-address mnemonic", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - mnemonic, err := cliutils.ValidateWalletMnemonic("mnemonic", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(importKey(c, minipoolAddress, mnemonic)) - return nil - - }, - }, - - { - Name: "can-change-withdrawal-creds", - Usage: "Check whether a solo validator's withdrawal credentials can be changed to a minipool address", - UsageText: "rocketpool api minipool can-change-withdrawal-creds minipool-address mnemonic", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - mnemonic, err := cliutils.ValidateWalletMnemonic("mnemonic", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canChangeWithdrawalCreds(c, minipoolAddress, mnemonic)) - return nil - - }, - }, - { - Name: "change-withdrawal-creds", - Usage: "Change a solo validator's withdrawal credentials to a minipool address", - UsageText: "rocketpool api minipool change-withdrawal-creds minipool-address mnemonic", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - mnemonic, err := cliutils.ValidateWalletMnemonic("mnemonic", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(changeWithdrawalCreds(c, minipoolAddress, mnemonic)) - return nil - - }, - }, - - { - Name: "get-rescue-dissolved-details-for-node", - Usage: "Check all of the node's minipools for rescue eligibility, and return the details of the rescuable ones", - UsageText: "rocketpool api minipool get-rescue-dissolved-details-for-node", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getMinipoolRescueDissolvedDetailsForNode(c)) - return nil - - }, - }, - - { - Name: "rescue-dissolved", - Usage: "Rescue a dissolved minipool by depositing ETH for it to the Beacon deposit contract", - UsageText: "rocketpool api minipool rescue-dissolved minipool-address deposit-amount submit", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - minipoolAddress, err := cliutils.ValidateAddress("minipool address", c.Args().Get(0)) - if err != nil { - return err - } - depositAmount, err := cliutils.ValidateBigInt("deposit amount", c.Args().Get(1)) - if err != nil { - return err - } - submit, err := cliutils.ValidateBool("submit", c.Args().Get(2)) - if err != nil { - return err - } - - // Run - api.PrintResponse(rescueDissolvedMinipool(c, minipoolAddress, depositAmount, submit)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/network/commands.go b/rocketpool/api/network/commands.go deleted file mode 100644 index e0857bf68..000000000 --- a/rocketpool/api/network/commands.go +++ /dev/null @@ -1,203 +0,0 @@ -package network - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage Rocket Pool network parameters", - Commands: []*cli.Command{ - - { - Name: "node-fee", - Aliases: []string{"f"}, - Usage: "Get the current network node commission rate", - UsageText: "rocketpool api network node-fee", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getNodeFee(c)) - return nil - - }, - }, - - { - Name: "rpl-price", - Aliases: []string{"p"}, - Usage: "Get the current network RPL price in ETH", - UsageText: "rocketpool api network rpl-price", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getRplPrice(c)) - return nil - - }, - }, - - { - Name: "stats", - Aliases: []string{"s"}, - Usage: "Get stats about the Rocket Pool network and its tokens", - UsageText: "rocketpool api network stats", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStats(c)) - return nil - - }, - }, - - { - Name: "timezone-map", - Aliases: []string{"t"}, - Usage: "Get the table of node operators by timezone", - UsageText: "rocketpool api network stats", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getTimezones(c)) - return nil - - }, - }, - - { - Name: "can-generate-rewards-tree", - Usage: "Check if the rewards tree for the provided interval can be generated", - UsageText: "rocketpool api network can-generate-rewards-tree index", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - index, err := cliutils.ValidateUint("index", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canGenerateRewardsTree(c, index)) - return nil - - }, - }, - - { - Name: "generate-rewards-tree", - Usage: "Set a request marker for the watchtower to generate the rewards tree for the given interval", - UsageText: "rocketpool api network generate-rewards-tree index", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - index, err := cliutils.ValidateUint("index", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(generateRewardsTree(c, index)) - return nil - - }, - }, - - { - Name: "dao-proposals", - Aliases: []string{"d"}, - Usage: "Get the currently active DAO proposals", - UsageText: "rocketpool api network dao-proposals", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getActiveDAOProposals(c)) - return nil - - }, - }, - - { - Name: "download-rewards-file", - Aliases: []string{"drf"}, - Usage: "Download a rewards info file from IPFS for the given interval", - UsageText: "rocketpool api service download-rewards-file interval", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - interval, err := cliutils.ValidateUint("interval", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(downloadRewardsFile(c, interval)) - return nil - - }, - }, - { - Name: "latest-delegate", - Usage: "Get the address of the latest minipool delegate contract.", - UsageText: "rocketpool api network latest-delegate", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getLatestDelegate(c)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/node/commands.go b/rocketpool/api/node/commands.go deleted file mode 100644 index 32965eeae..000000000 --- a/rocketpool/api/node/commands.go +++ /dev/null @@ -1,1820 +0,0 @@ -package node - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the node", - Commands: []*cli.Command{ - - { - Name: "status", - Aliases: []string{"s"}, - Usage: "Get the node's status", - UsageText: "rocketpool api node status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c)) - return nil - - }, - }, - - { - Name: "alerts", - Aliases: []string{"al"}, - Usage: "Get active alerts from Alertmanager", - UsageText: "rocketpool api node alerts", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getAlerts(c)) - return nil - - }, - }, - - { - Name: "sync", - Aliases: []string{"y"}, - Usage: "Get the sync progress of the eth1 and eth2 clients", - UsageText: "rocketpool api node sync", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getSyncProgress(c)) - return nil - - }, - }, - - { - Name: "can-register", - Usage: "Check whether the node can be registered with Rocket Pool", - UsageText: "rocketpool api node can-register timezone-location", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - timezoneLocation, err := cliutils.ValidateTimezoneLocation("timezone location", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canRegisterNode(c, timezoneLocation)) - return nil - - }, - }, - { - Name: "register", - Aliases: []string{"r"}, - Usage: "Register the node with Rocket Pool", - UsageText: "rocketpool api node register timezone-location", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - timezoneLocation, err := cliutils.ValidateTimezoneLocation("timezone location", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(registerNode(c, timezoneLocation)) - return nil - - }, - }, - - { - Name: "can-set-primary-withdrawal-address", - Usage: "Checks if the node can set its primary withdrawal address", - UsageText: "rocketpool api node can-set-primary-withdrawal-address address confirm", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - withdrawalAddress, err := cliutils.ValidateAddress("withdrawal address", c.Args().Get(0)) - if err != nil { - return err - } - - confirm, err := cliutils.ValidateBool("confirm", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSetPrimaryWithdrawalAddress(c, withdrawalAddress, confirm)) - return nil - - }, - }, - { - Name: "set-primary-withdrawal-address", - Usage: "Set the node's primary withdrawal address", - UsageText: "rocketpool api node set-primary-withdrawal-address address confirm", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - withdrawalAddress, err := cliutils.ValidateAddress("withdrawal address", c.Args().Get(0)) - if err != nil { - return err - } - - confirm, err := cliutils.ValidateBool("confirm", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(setPrimaryWithdrawalAddress(c, withdrawalAddress, confirm)) - return nil - - }, - }, - - { - Name: "can-confirm-primary-withdrawal-address", - Usage: "Checks if the node can confirm its primary withdrawal address", - UsageText: "rocketpool api node can-confirm-primary-withdrawal-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canConfirmPrimaryWithdrawalAddress(c)) - return nil - - }, - }, - { - Name: "confirm-primary-withdrawal-address", - Usage: "Confirms the node's primary withdrawal address if it was set back to the node address", - UsageText: "rocketpool api node confirm-primary-withdrawal-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(confirmPrimaryWithdrawalAddress(c)) - return nil - - }, - }, - - { - Name: "can-set-rpl-withdrawal-address", - Usage: "Checks if the node can set its RPL withdrawal address", - UsageText: "rocketpool api node can-set-rpl-withdrawal-address address confirm", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - withdrawalAddress, err := cliutils.ValidateAddress("withdrawal address", c.Args().Get(0)) - if err != nil { - return err - } - - confirm, err := cliutils.ValidateBool("confirm", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSetRPLWithdrawalAddress(c, withdrawalAddress, confirm)) - return nil - - }, - }, - { - Name: "set-rpl-withdrawal-address", - Usage: "Set the node's RPL withdrawal address", - UsageText: "rocketpool api node set-rpl-withdrawal-address address confirm", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - withdrawalAddress, err := cliutils.ValidateAddress("withdrawal address", c.Args().Get(0)) - if err != nil { - return err - } - - confirm, err := cliutils.ValidateBool("confirm", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(setRPLWithdrawalAddress(c, withdrawalAddress, confirm)) - return nil - - }, - }, - - { - Name: "can-confirm-rpl-withdrawal-address", - Usage: "Checks if the node can confirm its RPL withdrawal address", - UsageText: "rocketpool api node can-confirm-rpl-withdrawal-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canConfirmRPLWithdrawalAddress(c)) - return nil - - }, - }, - { - Name: "confirm-rpl-withdrawal-address", - Usage: "Confirms the node's RPL withdrawal address if it was set back to the node address", - UsageText: "rocketpool api node confirm-rpl-withdrawal-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(confirmRPLWithdrawalAddress(c)) - return nil - - }, - }, - - { - Name: "can-set-timezone", - Usage: "Checks if the node can set its timezone location", - UsageText: "rocketpool api node can-set-timezone timezone-location", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - timezoneLocation, err := cliutils.ValidateTimezoneLocation("timezone location", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSetTimezoneLocation(c, timezoneLocation)) - return nil - - }, - }, - { - Name: "set-timezone", - Aliases: []string{"t"}, - Usage: "Set the node's timezone location", - UsageText: "rocketpool api node set-timezone timezone-location", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - timezoneLocation, err := cliutils.ValidateTimezoneLocation("timezone location", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(setTimezoneLocation(c, timezoneLocation)) - return nil - - }, - }, - - { - Name: "can-swap-rpl", - Usage: "Check whether the node can swap old RPL for new RPL", - UsageText: "rocketpool api node can-swap-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("swap amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeSwapRpl(c, amountWei)) - return nil - - }, - }, - { - Name: "swap-rpl-approve-rpl", - Aliases: []string{"p1"}, - Usage: "Approve fixed-supply RPL for swapping to new RPL", - UsageText: "rocketpool api node swap-rpl-approve-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("swap amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(approveFsRpl(c, amountWei)) - return nil - - }, - }, - { - Name: "wait-and-swap-rpl", - Aliases: []string{"p2"}, - Usage: "Swap old RPL for new RPL, waiting for the approval TX hash to be included in a block first", - UsageText: "rocketpool api node wait-and-swap-rpl amount tx-hash", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("swap amount", c.Args().Get(0)) - if err != nil { - return err - } - hash, err := cliutils.ValidateTxHash("swap amount", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(waitForApprovalAndSwapFsRpl(c, amountWei, hash)) - return nil - - }, - }, - { - Name: "get-swap-rpl-approval-gas", - Usage: "Estimate the gas cost of legacy RPL interaction approval", - UsageText: "rocketpool api node get-swap-rpl-approval-gas", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("approve amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getSwapApprovalGas(c, amountWei)) - return nil - - }, - }, - { - Name: "swap-rpl-allowance", - Usage: "Get the node's legacy RPL allowance for new RPL contract", - UsageText: "rocketpool api node swap-allowance-rpl", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(allowanceFsRpl(c)) - return nil - - }, - }, - { - Name: "swap-rpl", - Aliases: []string{"p3"}, - Usage: "Swap old RPL for new RPL", - UsageText: "rocketpool api node swap-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("swap amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(swapRpl(c, amountWei)) - return nil - - }, - }, - - { - Name: "can-stake-rpl", - Usage: "Check whether the node can stake RPL", - UsageText: "rocketpool api node can-stake-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("stake amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeStakeRpl(c, amountWei)) - return nil - - }, - }, - { - Name: "stake-rpl-approve-rpl", - Aliases: []string{"k1"}, - Usage: "Approve RPL for staking against the node", - UsageText: "rocketpool api node stake-rpl-approve-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("stake amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(approveRpl(c, amountWei)) - return nil - - }, - }, - { - Name: "wait-and-stake-rpl", - Aliases: []string{"k2"}, - Usage: "Stake RPL against the node, waiting for approval tx-hash to be included in a block first", - UsageText: "rocketpool api node wait-and-stake-rpl amount tx-hash", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("stake amount", c.Args().Get(0)) - if err != nil { - return err - } - hash, err := cliutils.ValidateTxHash("tx-hash", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(waitForApprovalAndStakeRpl(c, amountWei, hash)) - return nil - - }, - }, - { - Name: "get-stake-rpl-approval-gas", - Usage: "Estimate the gas cost of new RPL interaction approval", - UsageText: "rocketpool api node get-stake-rpl-approval-gas", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("approve amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getStakeApprovalGas(c, amountWei)) - return nil - - }, - }, - { - Name: "stake-rpl-allowance", - Usage: "Get the node's RPL allowance for the staking contract", - UsageText: "rocketpool api node stake-allowance-rpl", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(allowanceRpl(c)) - return nil - - }, - }, - { - Name: "stake-rpl", - Aliases: []string{"k3"}, - Usage: "Stake RPL against the node", - UsageText: "rocketpool api node stake-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("stake amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(stakeRpl(c, amountWei)) - return nil - - }, - }, - { - Name: "can-set-rpl-locking-allowed", - Usage: "Check whether the node can set the RPL lock allowed status", - UsageText: "rocketpool api node can-set-rpl-locking-allowed caller allowed", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - allowedString := c.Args().Get(0) - allowed, err := cliutils.ValidateBool("allowed", allowedString) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSetRplLockAllowed(c, allowed)) - return nil - - }, - }, - - { - Name: "set-rpl-locking-allowed", - Usage: "Sets the node RPL locking allowed status", - UsageText: "rocketpool api node set-rpl-locking-allowed caller allowed", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - allowedString := c.Args().Get(0) - allowed, err := cliutils.ValidateBool("allowed", allowedString) - if err != nil { - return err - } - - // Run - api.PrintResponse(setRplLockAllowed(c, allowed)) - return nil - - }, - }, - - { - Name: "can-set-stake-rpl-for-allowed", - Usage: "Check whether the node can set allowed status for an address to stake RPL on behalf of themself", - UsageText: "rocketpool api node can-set-stake-rpl-for-allowed caller allowed", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - - callerAddressString := c.Args().Get(0) - callerAddress, err := cliutils.ValidateAddress("caller", callerAddressString) - if err != nil { - return err - } - - allowedString := c.Args().Get(1) - allowed, err := cliutils.ValidateBool("allowed", allowedString) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSetStakeRplForAllowed(c, callerAddress, allowed)) - return nil - - }, - }, - { - Name: "set-stake-rpl-for-allowed", - Aliases: []string{"kf"}, - Usage: "Sets the allowed status for an address to stake RPL on behalf of your node", - UsageText: "rocketpool api node set-stake-rpl-for-allowed caller allowed", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - - callerAddressString := c.Args().Get(0) - callerAddress, err := cliutils.ValidateAddress("caller", callerAddressString) - if err != nil { - return err - } - - allowedString := c.Args().Get(1) - allowed, err := cliutils.ValidateBool("allowed", allowedString) - if err != nil { - return err - } - - // Run - api.PrintResponse(setStakeRplForAllowed(c, callerAddress, allowed)) - - return nil - }, - }, - { - Name: "can-withdraw-credit", - Usage: "Check whether the node can withdraw credit", - UsageText: "rocketpool api node can-withdraw-credit amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("withdrawal amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeWithdrawCredit(c, amountWei)) - return nil - - }, - }, - { - Name: "withdraw-credit", - Aliases: []string{"wc"}, - Usage: "Withdraw credit from the node", - UsageText: "rocketpool api node withdraw-credit amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("withdrawal amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(nodeWithdrawCredit(c, amountWei)) - return nil - - }, - }, - { - Name: "can-withdraw-eth", - Usage: "Check whether the node can withdraw ETH staked on its behalf", - UsageText: "rocketpool api node can-withdraw-eth amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("withdrawal amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeWithdrawEth(c, amountWei)) - return nil - - }, - }, - { - Name: "withdraw-eth", - Aliases: []string{"i"}, - Usage: "Withdraw ETH staked on behalf of the node", - UsageText: "rocketpool api node withdraw-eth amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("withdrawal amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(nodeWithdrawEth(c, amountWei)) - return nil - - }, - }, - { - Name: "can-unstake-legacy-rpl", - Usage: "Check whether the node can withdraw legacy staked RPL", - UsageText: "rocketpool api node can-withdraw-legacy-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("unstake amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeUnstakeLegacyRpl(c, amountWei)) - return nil - - }, - }, - { - Name: "unstake-legacy-rpl", - Aliases: []string{"l"}, - Usage: "Unstake legacy RPL staked against the node", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("unstake amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(nodeUnstakeLegacyRpl(c, amountWei)) - return nil - }, - }, - { - Name: "can-withdraw-rpl", - Usage: "Check whether the node can withdraw staked RPL", - UsageText: "rocketpool api node can-withdraw-rpl", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canNodeWithdrawRpl(c)) - return nil - - }, - }, - { - Name: "withdraw-rpl", - Aliases: []string{"w"}, - Usage: "Withdraw RPL staked against the node", - UsageText: "rocketpool api node withdraw-rpl", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(nodeWithdrawRpl(c)) - return nil - - }, - }, - { - Name: "can-withdraw-rpl-v131", - Usage: "Check whether the node can withdraw staked RPL", - UsageText: "rocketpool api node can-withdraw-rpl-v131 amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("withdrawal amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeWithdrawRplv1_3_1(c, amountWei)) - return nil - - }, - }, - { - Name: "withdraw-rpl-v131", - Aliases: []string{"w"}, - Usage: "Withdraw RPL staked against the node", - UsageText: "rocketpool api node withdraw-rpl-v131 amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("withdrawal amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(nodeWithdrawRplv1_3_1(c, amountWei)) - return nil - - }, - }, - { - Name: "can-unstake-rpl", - Usage: "Check whether the node can unstake RPL", - UsageText: "rocketpool api node can-unstake-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - amountWei, err := cliutils.ValidatePositiveWeiAmount("unstake amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeUnstakeRpl(c, amountWei)) - return nil - - }, - }, - { - Name: "unstake-rpl", - Aliases: []string{"u"}, - Usage: "Unstake RPL from the node", - UsageText: "rocketpool api node withdraw-rpl amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - amountWei, err := cliutils.ValidatePositiveWeiAmount("unstake amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(nodeUnstakeRpl(c, amountWei)) - return nil - - }, - }, - - { - Name: "can-deposit", - Usage: "Check whether the node can make a deposit. Optionally specify count to check multiple deposits.", - UsageText: "rocketpool api node can-deposit amount min-fee salt express-tickets count", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 5); err != nil { - return err - } - - amountWei, err := cliutils.ValidatePositiveWeiAmount("deposit amount", c.Args().Get(0)) - if err != nil { - return err - } - - minNodeFee, err := cliutils.ValidateFraction("minimum node fee", c.Args().Get(1)) - if err != nil { - return err - } - salt, err := cliutils.ValidateBigInt("salt", c.Args().Get(2)) - if err != nil { - return err - } - - expressTickets, err := cliutils.ValidateUint("express-tickets", c.Args().Get(3)) - if err != nil { - return err - } - - count, err := cliutils.ValidateUint("count", c.Args().Get(4)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeDeposits(c, count, amountWei, minNodeFee, salt, int64(expressTickets))) - return nil - - }, - }, - { - Name: "deposit", - Aliases: []string{"d"}, - Usage: "Make a deposit and create a minipool, or just make and sign the transaction (when submit = false). Optionally specify count to make multiple deposits.", - UsageText: "rocketpool api node deposit amount min-node-fee salt use-credit-balance express-tickets submit count", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 7); err != nil { - return err - } - - amountWei, err := cliutils.ValidatePositiveWeiAmount("deposit amount", c.Args().Get(0)) - if err != nil { - return err - } - - minNodeFee, err := cliutils.ValidateFraction("minimum node fee", c.Args().Get(1)) - if err != nil { - return err - } - - salt, err := cliutils.ValidateBigInt("salt", c.Args().Get(2)) - if err != nil { - return err - } - - useCreditBalanceString := c.Args().Get(3) - useCreditBalance, err := cliutils.ValidateBool("use-credit-balance", useCreditBalanceString) - if err != nil { - return err - } - - expressTickets, err := cliutils.ValidateUint("express-tickets", c.Args().Get(4)) - if err != nil { - return err - } - submit, err := cliutils.ValidateBool("submit", c.Args().Get(5)) - if err != nil { - return err - } - - // Check if count is provided - count, err := cliutils.ValidateUint("count", c.Args().Get(6)) - if err != nil { - return err - } - - // Run - response, err := nodeDeposits(c, count, amountWei, minNodeFee, salt, useCreditBalance, int64(expressTickets), submit) - - api.PrintResponse(response, err) - return nil - - }, - }, - - { - Name: "can-send", - Usage: "Check whether the node can send ETH or tokens to an address", - UsageText: "rocketpool api node can-send amount token to", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - amountRaw, err := cliutils.ValidateEthAmount("send amount", c.Args().Get(0)) - if err != nil { - return err - } - token, err := cliutils.ValidateTokenType("token type", c.Args().Get(1)) - if err != nil { - return err - } - toAddress, err := cliutils.ValidateAddress("to address", c.Args().Get(2)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeSend(c, amountRaw, token, toAddress)) - return nil - - }, - }, - { - Name: "send", - Aliases: []string{"n"}, - Usage: "Send ETH or tokens from the node account to an address", - UsageText: "rocketpool api node send amount token to", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - amountRaw, err := cliutils.ValidatePositiveEthAmount("send amount", c.Args().Get(0)) - if err != nil { - return err - } - token, err := cliutils.ValidateTokenType("token type", c.Args().Get(1)) - if err != nil { - return err - } - toAddress, err := cliutils.ValidateAddress("to address", c.Args().Get(2)) - if err != nil { - return err - } - - // Run - api.PrintResponse(nodeSend(c, amountRaw, token, toAddress)) - return nil - - }, - }, - { - Name: "send-all", - Usage: "Send the entire token balance from the node account to an address (avoids float64 rounding errors)", - UsageText: "rocketpool api node send-all token to", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - token, err := cliutils.ValidateTokenType("token type", c.Args().Get(0)) - if err != nil { - return err - } - toAddress, err := cliutils.ValidateAddress("to address", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(nodeSendAllTokens(c, token, toAddress)) - return nil - - }, - }, - - { - Name: "can-burn", - Usage: "Check whether the node can burn tokens for ETH", - UsageText: "rocketpool api node can-burn amount token", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("burn amount", c.Args().Get(0)) - if err != nil { - return err - } - token, err := cliutils.ValidateBurnableTokenType("token type", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canNodeBurn(c, amountWei, token)) - return nil - - }, - }, - { - Name: "burn", - Aliases: []string{"b"}, - Usage: "Burn tokens for ETH", - UsageText: "rocketpool api node burn amount token", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - amountWei, err := cliutils.ValidatePositiveWeiAmount("burn amount", c.Args().Get(0)) - if err != nil { - return err - } - token, err := cliutils.ValidateBurnableTokenType("token type", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(nodeBurn(c, amountWei, token)) - return nil - - }, - }, - - { - Name: "can-claim-rpl-rewards", - Usage: "Check whether the node has RPL rewards available to claim", - UsageText: "rocketpool api node can-claim-rpl-rewards", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canNodeClaimRpl(c)) - return nil - - }, - }, - { - Name: "claim-rpl-rewards", - Usage: "Claim available RPL rewards", - UsageText: "rocketpool api node claim-rpl-rewards", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(nodeClaimRpl(c)) - return nil - - }, - }, - - { - Name: "rewards", - Usage: "Get RPL rewards info", - UsageText: "rocketpool api node rewards", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getRewards(c)) - return nil - - }, - }, - - { - Name: "deposit-contract-info", - Usage: "Get information about the deposit contract specified by Rocket Pool and the Beacon Chain client", - UsageText: "rocketpool api node deposit-contract-info", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getDepositContractInfo(c)) - return nil - - }, - }, - - { - Name: "sign", - Usage: "Signs a transaction with the node's private key. The TX must be serialized as a hex string.", - UsageText: "rocketpool api node sign tx", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - data := c.Args().Get(0) - - // Run - api.PrintResponse(sign(c, data)) - return nil - - }, - }, - - { - Name: "sign-message", - Usage: "Signs an arbitrary message with the node's private key.", - UsageText: "rocketpool api node sign-message 'message'", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - message := c.Args().Get(0) - - // Run - api.PrintResponse(signMessage(c, message)) - return nil - - }, - }, - - { - Name: "is-fee-distributor-initialized", - Usage: "Check if the fee distributor contract for this node is initialized and deployed", - UsageText: "rocketpool api node is-fee-distributor-initialized", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(isFeeDistributorInitialized(c)) - return nil - - }, - }, - { - Name: "get-initialize-fee-distributor-gas", - Usage: "Estimate the cost of initializing the fee distributor", - UsageText: "rocketpool api node get-initialize-fee-distributor-gas", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getInitializeFeeDistributorGas(c)) - return nil - }, - }, - - { - Name: "initialize-fee-distributor", - Usage: "Initialize and deploy the fee distributor contract for this node", - UsageText: "rocketpool api node initialize-fee-distributor", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(initializeFeeDistributor(c)) - return nil - - }, - }, - - { - Name: "can-distribute", - Usage: "Check if distributing ETH from the node's fee distributor is possible", - UsageText: "rocketpool api node can-distribute", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canDistribute(c)) - return nil - - }, - }, - { - Name: "distribute", - Usage: "Distribute ETH from the node's fee distributor", - UsageText: "rocketpool api node distribute", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(distribute(c)) - return nil - - }, - }, - { - Name: "claim-rpl-rewards", - Usage: "Claim available RPL rewards", - UsageText: "rocketpool api node claim-rpl-rewards", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(nodeClaimRpl(c)) - return nil - - }, - }, - - { - Name: "get-rewards-info", - Usage: "Get info about your eligible rewards periods, including balances and Merkle proofs", - UsageText: "rocketpool api node get-rewards-info", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getRewardsInfo(c)) - return nil - - }, - }, - { - Name: "can-claim-rewards", - Usage: "Check if the rewards for the given intervals can be claimed", - UsageText: "rocketpool api node can-claim-rewards 0,1,2,5,6", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - indicesString := c.Args().Get(0) - - // Run - api.PrintResponse(canClaimRewards(c, indicesString)) - return nil - - }, - }, - { - Name: "claim-rewards", - Usage: "Claim rewards for the given reward intervals", - UsageText: "rocketpool api node claim-rewards 0,1,2,5,6", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - indicesString := c.Args().Get(0) - - // Run - api.PrintResponse(claimRewards(c, indicesString)) - return nil - - }, - }, - { - Name: "can-claim-and-stake-rewards", - Usage: "Check if the rewards for the given intervals can be claimed, and RPL restaked automatically", - UsageText: "rocketpool api node can-claim-and-stake-rewards 0,1,2,5,6 amount-to-restake", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - indicesString := c.Args().Get(0) - - stakeAmount, err := cliutils.ValidateBigInt("stakeAmount", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canClaimAndStakeRewards(c, indicesString, stakeAmount)) - return nil - - }, - }, - { - Name: "claim-and-stake-rewards", - Usage: "Claim rewards for the given reward intervals and restake RPL automatically", - UsageText: "rocketpool api node claim-and-stake-rewards 0,1,2,5,6 amount-to-restake", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - indicesString := c.Args().Get(0) - - stakeAmount, err := cliutils.ValidateBigInt("stakeAmount", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(claimAndStakeRewards(c, indicesString, stakeAmount)) - return nil - - }, - }, - - { - Name: "get-smoothing-pool-registration-status", - Usage: "Check whether or not the node is opted into the Smoothing Pool", - UsageText: "rocketpool api node get-smoothing-pool-registration-status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getSmoothingPoolRegistrationStatus(c)) - return nil - - }, - }, - { - Name: "can-set-smoothing-pool-status", - Usage: "Check if the node's Smoothing Pool status can be changed", - UsageText: "rocketpool api node can-set-smoothing-pool-status status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - status, err := cliutils.ValidateBool("status", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSetSmoothingPoolStatus(c, status)) - return nil - - }, - }, - { - Name: "set-smoothing-pool-status", - Usage: "Sets the node's Smoothing Pool opt-in status", - UsageText: "rocketpool api node set-smoothing-pool-status status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - status, err := cliutils.ValidateBool("status", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(setSmoothingPoolStatus(c, status)) - return nil - - }, - }, - { - Name: "resolve-ens-name", - Usage: "Resolve an ENS name", - UsageText: "rocketpool api node resolve-ens-name name", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Run - api.PrintResponse(resolveEnsName(c, c.Args().Get(0))) - return nil - - }, - }, - { - Name: "reverse-resolve-ens-name", - Usage: "Reverse resolve an address to an ENS name", - UsageText: "rocketpool api node reverse-resolve-ens-name address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - address, err := cliutils.ValidateAddress("address", c.Args().Get(0)) - if err != nil { - return err - } - // Run - api.PrintResponse(reverseResolveEnsName(c, address)) - return nil - - }, - }, - - { - Name: "check-collateral", - Usage: "Check if the node is above the minimum collateralization threshold, including pending bond reductions", - UsageText: "rocketpool api node check-collateral", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(checkCollateral(c)) - return nil - - }, - }, - - { - Name: "get-eth-balance", - Usage: "Get the ETH balance of the node address", - UsageText: "rocketpool api node get-eth-balance", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getNodeEthBalance(c)) - return nil - - }, - }, - - { - Name: "can-send-message", - Usage: "Estimates the gas for sending a zero-value message with a payload", - UsageText: "rocketpool api node can-send-message address message", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - address, err := cliutils.ValidateAddress("address", c.Args().Get(0)) - if err != nil { - return err - } - message, err := cliutils.ValidateByteArray("message", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSendMessage(c, address, message)) - return nil - - }, - }, - { - Name: "send-message", - Usage: "Sends a zero-value message with a payload", - UsageText: "rocketpool api node send-message address message", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - address, err := cliutils.ValidateAddress("address", c.Args().Get(0)) - if err != nil { - return err - } - message, err := cliutils.ValidateByteArray("message", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(sendMessage(c, address, message)) - return nil - - }, - }, - { - Name: "get-express-ticket-count", - Usage: "Get the number of express tickets available for the node", - UsageText: "rocketpool api node get-express-ticket-count", - Action: func(ctx context.Context, c *cli.Command) error { - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - api.PrintResponse(getExpressTicketCount(c)) - return nil - }, - }, - { - Name: "can-claim-unclaimed-rewards", - Usage: "Check if any unclaimed rewards can be sent to the node's withdrawal address", - UsageText: "rocketpool api node can-claim-unclaimed-rewards address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - // Get amount - nodeAddress, err := cliutils.ValidateAddress("address", c.Args().Get(0)) - if err != nil { - return err - } - // Run - api.PrintResponse(canClaimUnclaimedRewards(c, nodeAddress)) - return nil - - }, - }, - { - Name: "claim-unclaimed-rewards", - Usage: "Send unclaimed rewards to the node's withdrawal address", - UsageText: "rocketpool api node claim-unclaimed-rewards address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - // Get amount - nodeAddress, err := cliutils.ValidateAddress("address", c.Args().Get(0)) - if err != nil { - return err - } - // Run - api.PrintResponse(canClaimUnclaimedRewards(c, nodeAddress)) - return nil - - }, - }, - { - Name: "get-express-tickets-provisioned", - Usage: "Get the number of express tickets provisioned for the node", - UsageText: "rocketpool api node get-express-tickets-provisioned", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getExpressTicketsProvisioned(c)) - return nil - - }, - }, - { - Name: "can-provision-express-tickets", - Usage: "Check if the node's express tickets can be provisioned", - UsageText: "rocketpool api node can-provision-express-tickets", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canProvisionExpressTickets(c)) - return nil - - }, - }, - { - Name: "provision-express-tickets", - Usage: "Provision the node's express tickets", - UsageText: "rocketpool api node provision-express-tickets", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(provisionExpressTickets(c)) - return nil - - }, - }, - { - Name: "get-bond-requirement", - Usage: "Get the bond requirement for a validator", - UsageText: "rocketpool api node get-bond-requirement num-validators", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - numValidators, err := cliutils.ValidateUint("num-validators", c.Args().Get(0)) - if err != nil { - return err - } - // Run - api.PrintResponse(getBondRequirement(c, numValidators)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/odao/commands.go b/rocketpool/api/odao/commands.go deleted file mode 100644 index 92a35723f..000000000 --- a/rocketpool/api/odao/commands.go +++ /dev/null @@ -1,1140 +0,0 @@ -package odao - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the Rocket Pool oracle DAO", - Commands: []*cli.Command{ - - { - Name: "status", - Aliases: []string{"s"}, - Usage: "Get oracle DAO status", - UsageText: "rocketpool api odao status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c)) - return nil - - }, - }, - - { - Name: "members", - Aliases: []string{"m"}, - Usage: "Get the oracle DAO members", - UsageText: "rocketpool api odao members", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getMembers(c)) - return nil - - }, - }, - - { - Name: "proposals", - Aliases: []string{"p"}, - Usage: "Get the oracle DAO proposals", - UsageText: "rocketpool api odao proposals", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getProposals(c)) - return nil - - }, - }, - - { - Name: "can-penalise-megapool", - Aliases: []string{"cpm"}, - Usage: "Checks whether we can penalise a megapool", - UsageText: "rocketpool api odao can-penalise-megapool megapool-address block amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - var err error - if err = cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - block, err := cliutils.ValidateBigInt("block", c.Args().Get(1)) - if err != nil { - return err - } - - amount, err := cliutils.ValidateBigInt("amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canPenaliseMegapool(c, megapoolAddress, block, amount)) - return nil - - }, - }, - - { - Name: "penalise-megapool", - Aliases: []string{"pm"}, - Usage: "Penalise a megapool", - UsageText: "rocketpool api odao penalise-megapool megapool-address block amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - var err error - if err = cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - megapoolAddress, err := cliutils.ValidateAddress("megapool address", c.Args().Get(0)) - if err != nil { - return err - } - - block, err := cliutils.ValidateBigInt("block", c.Args().Get(1)) - if err != nil { - return err - } - - amount, err := cliutils.ValidateBigInt("amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(penaliseMegapool(c, megapoolAddress, block, amount)) - return nil - - }, - }, - - { - Name: "proposal-details", - Aliases: []string{"d"}, - Usage: "Get details of a proposal", - UsageText: "rocketpool api odao proposal-details proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - var err error - if err = cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - id, err := cliutils.ValidateUint("proposal-id", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getProposal(c, id)) - return nil - - }, - }, - - { - Name: "can-propose-invite", - Usage: "Check whether the node can propose inviting a new member", - UsageText: "rocketpool api odao can-propose-invite member-address member-id member-url", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - memberAddress, err := cliutils.ValidateAddress("member address", c.Args().Get(0)) - if err != nil { - return err - } - memberId, err := cliutils.ValidateDAOMemberID("member ID", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeInvite(c, memberAddress, memberId, c.Args().Get(2))) - return nil - - }, - }, - { - Name: "propose-invite", - Aliases: []string{"i"}, - Usage: "Propose inviting a new member", - UsageText: "rocketpool api odao propose-invite member-address member-id member-url", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - memberAddress, err := cliutils.ValidateAddress("member address", c.Args().Get(0)) - if err != nil { - return err - } - memberId, err := cliutils.ValidateDAOMemberID("member ID", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeInvite(c, memberAddress, memberId, c.Args().Get(2))) - return nil - - }, - }, - - { - Name: "can-propose-leave", - Usage: "Check whether the node can propose leaving the oracle DAO", - UsageText: "rocketpool api odao can-propose-leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canProposeLeave(c)) - return nil - - }, - }, - { - Name: "propose-leave", - Aliases: []string{"l"}, - Usage: "Propose leaving the oracle DAO", - UsageText: "rocketpool api odao propose-leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(proposeLeave(c)) - return nil - - }, - }, - - { - Name: "can-propose-kick", - Usage: "Check whether the node can propose kicking a member", - UsageText: "rocketpool api odao can-propose-kick member-address fine-amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - memberAddress, err := cliutils.ValidateAddress("member address", c.Args().Get(0)) - if err != nil { - return err - } - fineAmountWei, err := cliutils.ValidatePositiveOrZeroWeiAmount("fine amount", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeKick(c, memberAddress, fineAmountWei)) - return nil - - }, - }, - { - Name: "propose-kick", - Aliases: []string{"k"}, - Usage: "Propose kicking a member", - UsageText: "rocketpool api odao propose-kick member-address fine-amount", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - memberAddress, err := cliutils.ValidateAddress("member address", c.Args().Get(0)) - if err != nil { - return err - } - fineAmountWei, err := cliutils.ValidatePositiveOrZeroWeiAmount("fine amount", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeKick(c, memberAddress, fineAmountWei)) - return nil - - }, - }, - - { - Name: "can-cancel-proposal", - Usage: "Check whether the node can cancel a proposal", - UsageText: "rocketpool api odao can-cancel-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canCancelProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "cancel-proposal", - Aliases: []string{"c"}, - Usage: "Cancel a proposal made by the node", - UsageText: "rocketpool api odao cancel-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(cancelProposal(c, proposalId)) - return nil - - }, - }, - - { - Name: "can-vote-proposal", - Usage: "Check whether the node can vote on a proposal", - UsageText: "rocketpool api odao can-vote-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canVoteOnProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "vote-proposal", - Aliases: []string{"v"}, - Usage: "Vote on a proposal", - UsageText: "rocketpool api odao vote-proposal proposal-id support", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - support, err := cliutils.ValidateBool("support", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(voteOnProposal(c, proposalId, support)) - return nil - - }, - }, - - { - Name: "can-execute-proposal", - Usage: "Check whether the node can execute a proposal", - UsageText: "rocketpool api odao can-execute-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canExecuteProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "execute-proposal", - Aliases: []string{"x"}, - Usage: "Execute a proposal", - UsageText: "rocketpool api odao execute-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(executeProposal(c, proposalId)) - return nil - - }, - }, - - { - Name: "can-join", - Usage: "Check whether the node can join the oracle DAO", - UsageText: "rocketpool api odao can-join", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canJoin(c)) - return nil - - }, - }, - { - Name: "join-approve-rpl", - Aliases: []string{"j1"}, - Usage: "Approves the RPL bond transfer prior to join the oracle DAO", - UsageText: "rocketpool api odao join-approve-rpl", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(approveRpl(c)) - return nil - - }, - }, - { - Name: "join", - Aliases: []string{"j2"}, - Usage: "Join the oracle DAO (requires an executed invite proposal)", - UsageText: "rocketpool api odao join tx-hash", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - hash, err := cliutils.ValidateTxHash("tx-hash", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(waitForApprovalAndJoin(c, hash)) - return nil - - }, - }, - - { - Name: "can-leave", - Usage: "Check whether the node can leave the oracle DAO", - UsageText: "rocketpool api odao can-leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canLeave(c)) - return nil - - }, - }, - { - Name: "leave", - Aliases: []string{"e"}, - Usage: "Leave the oracle DAO (requires an executed leave proposal)", - UsageText: "rocketpool api odao leave bond-refund-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - bondRefundAddress, err := cliutils.ValidateAddress("bond refund address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(leave(c, bondRefundAddress)) - return nil - - }, - }, - - { - Name: "can-propose-members-quorum", - Usage: "Check whether the node can propose the members.quorum setting", - UsageText: "rocketpool api odao can-propose-members-quorum value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - quorum, err := cliutils.ValidateFraction("quorum", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingMembersQuorum(c, quorum)) - return nil - - }, - }, - { - Name: "propose-members-quorum", - Usage: "Propose updating the members.quorum setting", - UsageText: "rocketpool api odao propose-members-quorum value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - quorum, err := cliutils.ValidateFraction("quorum", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingMembersQuorum(c, quorum)) - return nil - - }, - }, - - { - Name: "can-propose-members-rplbond", - Usage: "Check whether the node can propose the members.rplbond setting", - UsageText: "rocketpool api odao can-propose-members-rplbond value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - bondAmountWei, err := cliutils.ValidateWeiAmount("RPL bond amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingMembersRplBond(c, bondAmountWei)) - return nil - - }, - }, - { - Name: "propose-members-rplbond", - Usage: "Propose updating the members.rplbond setting", - UsageText: "rocketpool api odao propose-members-rplbond value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - bondAmountWei, err := cliutils.ValidateWeiAmount("RPL bond amount", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingMembersRplBond(c, bondAmountWei)) - return nil - - }, - }, - - { - Name: "can-propose-members-minipool-unbonded-max", - Usage: "Check whether the node can propose the members.minipool.unbonded.max setting", - UsageText: "rocketpool api odao can-propose-members-minipool-unbonded-max value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - unbondedMinipoolMax, err := cliutils.ValidateUint("maximum unbonded minipool count", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingMinipoolUnbondedMax(c, unbondedMinipoolMax)) - return nil - - }, - }, - { - Name: "propose-members-minipool-unbonded-max", - Usage: "Propose updating the members.minipool.unbonded.max setting", - UsageText: "rocketpool api odao propose-members-minipool-unbonded-max value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - unbondedMinipoolMax, err := cliutils.ValidateUint("maximum unbonded minipool count", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingMinipoolUnbondedMax(c, unbondedMinipoolMax)) - return nil - - }, - }, - - { - Name: "can-propose-proposal-cooldown", - Usage: "Check whether the node can propose the proposal.cooldown setting", - UsageText: "rocketpool api odao can-propose-proposal-cooldown value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalCooldownBlocks, err := cliutils.ValidateUint("proposal cooldown period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingProposalCooldown(c, proposalCooldownBlocks)) - return nil - - }, - }, - { - Name: "propose-proposal-cooldown", - Usage: "Propose updating the proposal.cooldown setting", - UsageText: "rocketpool api odao propose-proposal-cooldown value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalCooldownBlocks, err := cliutils.ValidateUint("proposal cooldown period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingProposalCooldown(c, proposalCooldownBlocks)) - return nil - - }, - }, - - { - Name: "can-propose-proposal-vote-timespan", - Usage: "Check whether the node can propose the proposal.vote.time setting", - UsageText: "rocketpool api odao can-propose-proposal-vote-timespan value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalVoteTimespan, err := cliutils.ValidateUint("proposal voting period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingProposalVoteTimespan(c, proposalVoteTimespan)) - return nil - - }, - }, - { - Name: "propose-proposal-vote-timespan", - Usage: "Propose updating the proposal.vote.time setting", - UsageText: "rocketpool api odao propose-proposal-vote-timespan value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalVoteTimespan, err := cliutils.ValidateUint("proposal voting period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingProposalVoteTimespan(c, proposalVoteTimespan)) - return nil - - }, - }, - - { - Name: "can-propose-proposal-vote-delay-timespan", - Usage: "Check whether the node can propose the proposal.vote.delay.time setting", - UsageText: "rocketpool api odao can-propose-proposal-vote-delay-timespan value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalDelayTimespan, err := cliutils.ValidateUint("proposal delay period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingProposalVoteDelayTimespan(c, proposalDelayTimespan)) - return nil - - }, - }, - { - Name: "propose-proposal-vote-delay-timespan", - Usage: "Propose updating the proposal.vote.delay.time setting", - UsageText: "rocketpool api odao propose-proposal-vote-delay-timespan value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalDelayTimespan, err := cliutils.ValidateUint("proposal delay period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingProposalVoteDelayTimespan(c, proposalDelayTimespan)) - return nil - - }, - }, - - { - Name: "can-propose-proposal-execute-timespan", - Usage: "Check whether the node can propose the proposal.execute.time setting", - UsageText: "rocketpool api odao can-propose-proposal-execute-timespan value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalExecuteTimespan, err := cliutils.ValidateUint("proposal execution period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingProposalExecuteTimespan(c, proposalExecuteTimespan)) - return nil - - }, - }, - { - Name: "propose-proposal-execute-timespan", - Usage: "Propose updating the proposal.execute.time setting", - UsageText: "rocketpool api odao propose-proposal-execute-timespan value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalExecuteTimespan, err := cliutils.ValidateUint("proposal execution period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingProposalExecuteTimespan(c, proposalExecuteTimespan)) - return nil - - }, - }, - - { - Name: "can-propose-proposal-action-timespan", - Usage: "Check whether the node can propose the proposal.action.time setting", - UsageText: "rocketpool api odao can-propose-proposal-action-timespan value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalActionTimespan, err := cliutils.ValidateUint("proposal action period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingProposalActionTimespan(c, proposalActionTimespan)) - return nil - - }, - }, - { - Name: "propose-proposal-action-timespan", - Usage: "Propose updating the proposal.action.time setting", - UsageText: "rocketpool api odao propose-proposal-action-timespan value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalActionTimespan, err := cliutils.ValidateUint("proposal action period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingProposalActionTimespan(c, proposalActionTimespan)) - return nil - - }, - }, - - { - Name: "can-propose-scrub-period", - Usage: "Check whether the node can propose the minipool.scrub.period setting", - UsageText: "rocketpool api odao can-propose-scrub-period value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - scrubPeriod, err := cliutils.ValidateUint("scrub period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingScrubPeriod(c, scrubPeriod)) - return nil - - }, - }, - { - Name: "propose-scrub-period", - Usage: "Propose updating the minipool.scrub.period setting", - UsageText: "rocketpool api odao propose-scrub-period value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - scrubPeriod, err := cliutils.ValidateUint("scrub period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingScrubPeriod(c, scrubPeriod)) - return nil - - }, - }, - - { - Name: "can-propose-promotion-scrub-period", - Usage: "Check whether the node can propose the minipool.promotion.scrub.period setting", - UsageText: "rocketpool api odao can-propose-promotion-scrub-period value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - scrubPeriod, err := cliutils.ValidateUint("promotion scrub period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingPromotionScrubPeriod(c, scrubPeriod)) - return nil - - }, - }, - { - Name: "propose-promotion-scrub-period", - Usage: "Propose updating the minipool.promotion.scrub.period setting", - UsageText: "rocketpool api odao propose-promotion-scrub-period value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - scrubPeriod, err := cliutils.ValidateUint("promotion scrub period", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingPromotionScrubPeriod(c, scrubPeriod)) - return nil - - }, - }, - - { - Name: "can-propose-scrub-penalty-enabled", - Usage: "Check whether the node can propose the minipool.scrub.penalty.enabled setting", - UsageText: "rocketpool api odao can-propose-scrub-penalty-enabled value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - enabled, err := cliutils.ValidateBool("scrub penalty enabled", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingScrubPenaltyEnabled(c, enabled)) - return nil - - }, - }, - { - Name: "propose-scrub-penalty-enabled", - Usage: "Propose updating the minipool.scrub.penalty.enabled setting", - UsageText: "rocketpool api odao propose-scrub-penalty-enabled value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - enabled, err := cliutils.ValidateBool("scrub penalty enabled", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingScrubPenaltyEnabled(c, enabled)) - return nil - - }, - }, - - { - Name: "can-propose-bond-reduction-window-start", - Usage: "Check whether the node can propose the minipool.bond.reduction.window.start setting", - UsageText: "rocketpool api odao can-propose-bond-reduction-window-start value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - windowStart, err := cliutils.ValidateUint("window start", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingBondReductionWindowStart(c, windowStart)) - return nil - - }, - }, - { - Name: "propose-bond-reduction-window-start", - Usage: "Propose updating the minipool.bond.reduction.window.start setting", - UsageText: "rocketpool api odao propose-bond-reduction-window-start value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - windowStart, err := cliutils.ValidateUint("window start", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingBondReductionWindowStart(c, windowStart)) - return nil - - }, - }, - - { - Name: "can-propose-bond-reduction-window-length", - Usage: "Check whether the node can propose the minipool.bond.reduction.window.length setting", - UsageText: "rocketpool api odao can-propose-bond-reduction-window-length value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - windowLength, err := cliutils.ValidateUint("window length", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeSettingBondReductionWindowLength(c, windowLength)) - return nil - - }, - }, - { - Name: "propose-bond-reduction-window-length", - Usage: "Propose updating the minipool.bond.reduction.window.length setting", - UsageText: "rocketpool api odao propose-bond-reduction-window-length value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - windowLength, err := cliutils.ValidateUint("window length", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSettingBondReductionWindowLength(c, windowLength)) - return nil - - }, - }, - - { - Name: "get-member-settings", - Usage: "Get the ODAO settings related to ODAO members", - UsageText: "rocketpool api odao get-member-settings", - Action: func(ctx context.Context, c *cli.Command) error { - - // Run - api.PrintResponse(getMemberSettings(c)) - return nil - - }, - }, - { - Name: "get-proposal-settings", - Usage: "Get the ODAO settings related to ODAO proposals", - UsageText: "rocketpool api odao get-proposal-settings", - Action: func(ctx context.Context, c *cli.Command) error { - - // Run - api.PrintResponse(getProposalSettings(c)) - return nil - - }, - }, - { - Name: "get-minipool-settings", - Usage: "Get the ODAO settings related to minipools", - UsageText: "rocketpool api odao get-minipool-settings", - Action: func(ctx context.Context, c *cli.Command) error { - - // Run - api.PrintResponse(getMinipoolSettings(c)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/pdao/commands.go b/rocketpool/api/pdao/commands.go deleted file mode 100644 index ae5fc273d..000000000 --- a/rocketpool/api/pdao/commands.go +++ /dev/null @@ -1,1152 +0,0 @@ -package pdao - -import ( - "context" - "fmt" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the Rocket Pool protocol DAO", - Commands: []*cli.Command{ - - { - Name: "proposals", - Aliases: []string{"p"}, - Usage: "Get the protocol DAO proposals", - UsageText: "rocketpool api pdao proposals", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getProposals(c)) - return nil - - }, - }, - - { - Name: "proposal-details", - Aliases: []string{"d"}, - Usage: "Get details of a proposal", - UsageText: "rocketpool api pdao proposal-details proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - var err error - if err = cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - id, err := cliutils.ValidateUint("proposal-id", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getProposal(c, id)) - return nil - - }, - }, - - { - Name: "can-vote-proposal", - Usage: "Check whether the node can vote on a proposal", - UsageText: "rocketpool api pdao can-vote-proposal proposal-id vote-direction", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - voteDir, err := cliutils.ValidateVoteDirection("vote direction", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canVoteOnProposal(c, proposalId, voteDir)) - return nil - - }, - }, - { - Name: "vote-proposal", - Aliases: []string{"v"}, - Usage: "Vote on a proposal", - UsageText: "rocketpool api pdao vote-proposal proposal-id vote-direction", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - voteDir, err := cliutils.ValidateVoteDirection("vote direction", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(voteOnProposal(c, proposalId, voteDir)) - return nil - - }, - }, - - { - Name: "can-override-vote", - Usage: "Check whether the node can override their delegate's vote on a proposal", - UsageText: "rocketpool api pdao can-override-vote proposal-id vote-direction", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - voteDir, err := cliutils.ValidateVoteDirection("vote direction", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canOverrideVote(c, proposalId, voteDir)) - return nil - - }, - }, - { - Name: "override-vote", - Usage: "Override the vote of the node's delegate on a proposal", - UsageText: "rocketpool api pdao override-vote proposal-id vote-direction", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - voteDir, err := cliutils.ValidateVoteDirection("vote direction", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(overrideVote(c, proposalId, voteDir)) - return nil - - }, - }, - - { - Name: "can-execute-proposal", - Usage: "Check whether the node can execute a proposal", - UsageText: "rocketpool api pdao can-execute-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canExecuteProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "execute-proposal", - Aliases: []string{"x"}, - Usage: "Execute a proposal", - UsageText: "rocketpool api pdao execute-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(executeProposal(c, proposalId)) - return nil - - }, - }, - - { - Name: "get-settings", - Usage: "Get the Protocol DAO settings", - UsageText: "rocketpool api pdao get-member-settings", - Action: func(ctx context.Context, c *cli.Command) error { - - // Run - api.PrintResponse(getSettings(c)) - return nil - - }, - }, - - { - Name: "can-propose-setting", - Usage: "Check whether the node can propose a PDAO setting", - UsageText: "rocketpool api pdao can-propose-setting contract-name setting-name value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - contractName := c.Args().Get(0) - settingName := c.Args().Get(1) - value := c.Args().Get(2) - - // Run - api.PrintResponse(canProposeSetting(c, contractName, settingName, value)) - return nil - - }, - }, - { - Name: "propose-setting", - Usage: "Propose updating a PDAO setting (use can-propose-setting to get the pollard)", - UsageText: "rocketpool api pdao propose-setting contract-name setting-name value block-number", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 4); err != nil { - return err - } - contractName := c.Args().Get(0) - settingName := c.Args().Get(1) - value := c.Args().Get(2) - blockNumber, err := cliutils.ValidatePositiveUint32("block-number", c.Args().Get(3)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeSetting(c, contractName, settingName, value, blockNumber)) - return nil - - }, - }, - - { - Name: "get-rewards-percentages", - Usage: "Get the allocation percentages of RPL rewards for the Oracle DAO, the Protocol DAO, and the node operators", - UsageText: "rocketpool api pdao get-rewards-percentages", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getRewardsPercentages(c)) - return nil - - }, - }, - { - Name: "can-propose-rewards-percentages", - Usage: "Check whether the node can propose new RPL rewards allocation percentages for the Oracle DAO, the Protocol DAO, and the node operators", - UsageText: "rocketpool api pdao can-propose-rewards-percentages node odao pdao", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - node, err := cliutils.ValidateBigInt("node", c.Args().Get(0)) - if err != nil { - return err - } - odao, err := cliutils.ValidateBigInt("odao", c.Args().Get(1)) - if err != nil { - return err - } - pdao, err := cliutils.ValidateBigInt("pdao", c.Args().Get(2)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeRewardsPercentages(c, node, odao, pdao)) - return nil - - }, - }, - { - Name: "propose-rewards-percentages", - Usage: "Propose new RPL rewards allocation percentages for the Oracle DAO, the Protocol DAO, and the node operators", - UsageText: "rocketpool api pdao propose-rewards-percentages node odao pdao block-number", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 4); err != nil { - return err - } - node, err := cliutils.ValidateBigInt("node", c.Args().Get(0)) - if err != nil { - return err - } - odao, err := cliutils.ValidateBigInt("odao", c.Args().Get(1)) - if err != nil { - return err - } - pdao, err := cliutils.ValidateBigInt("pdao", c.Args().Get(2)) - if err != nil { - return err - } - blockNumber, err := cliutils.ValidateUint32("blockNumber", c.Args().Get(3)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeRewardsPercentages(c, node, odao, pdao, blockNumber)) - return nil - - }, - }, - - { - Name: "can-propose-one-time-spend", - Usage: "Check whether the node can propose a one-time spend of the Protocol DAO's treasury", - UsageText: "rocketpool api pdao can-propose-one-time-spend invoice-id recipient amount custom-message", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 4); err != nil { - return err - } - invoiceID := c.Args().Get(0) - recipient, err := cliutils.ValidateAddress("recipient", c.Args().Get(1)) - if err != nil { - return err - } - amount, err := cliutils.ValidateBigInt("amount", c.Args().Get(2)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeOneTimeSpend(c, invoiceID, recipient, amount, c.Args().Get(3))) - return nil - - }, - }, - { - Name: "propose-one-time-spend", - Usage: "Propose a one-time spend of the Protocol DAO's treasury", - UsageText: "rocketpool api pdao propose-one-time-spend invoice-id recipient amount block-number custom-message", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 5); err != nil { - return err - } - invoiceID := c.Args().Get(0) - recipient, err := cliutils.ValidateAddress("recipient", c.Args().Get(1)) - if err != nil { - return err - } - amount, err := cliutils.ValidateBigInt("amount", c.Args().Get(2)) - if err != nil { - return err - } - blockNumber, err := cliutils.ValidateUint32("blockNumber", c.Args().Get(3)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeOneTimeSpend(c, invoiceID, recipient, amount, blockNumber, c.Args().Get(4))) - return nil - - }, - }, - - { - Name: "can-propose-recurring-spend", - Usage: "Check whether the node can propose a recurring spend of the Protocol DAO's treasury", - UsageText: "rocketpool api pdao can-propose-recurring-spend contract-name recipient amount-per-period period-length start-time number-of-periods custom-message", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 7); err != nil { - return err - } - contractName := c.Args().Get(0) - recipient, err := cliutils.ValidateAddress("recipient", c.Args().Get(1)) - if err != nil { - return err - } - amountPerPeriod, err := cliutils.ValidateBigInt("amount-per-period", c.Args().Get(2)) - if err != nil { - return err - } - periodLength, err := cliutils.ValidateDuration("period-length", c.Args().Get(3)) - if err != nil { - return err - } - startTime, err := cliutils.ValidatePositiveUint("start-time", c.Args().Get(4)) - if err != nil { - return err - } - numberOfPeriods, err := cliutils.ValidatePositiveUint("number-of-periods", c.Args().Get(5)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeRecurringSpend(c, contractName, recipient, amountPerPeriod, periodLength, time.Unix(int64(startTime), 0), numberOfPeriods, c.Args().Get(6))) - return nil - - }, - }, - { - Name: "propose-recurring-spend", - Usage: "Propose a recurring spend of the Protocol DAO's treasury", - UsageText: "rocketpool api pdao propose-recurring-spend contract-name recipient amount-per-period period-length start-time number-of-periods block-number custom-message", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 8); err != nil { - return err - } - contractName := c.Args().Get(0) - recipient, err := cliutils.ValidateAddress("recipient", c.Args().Get(1)) - if err != nil { - return err - } - amountPerPeriod, err := cliutils.ValidateBigInt("amount-per-period", c.Args().Get(2)) - if err != nil { - return err - } - periodLength, err := cliutils.ValidateDuration("period-length", c.Args().Get(3)) - if err != nil { - return err - } - startTime, err := cliutils.ValidatePositiveUint("start-time", c.Args().Get(4)) - if err != nil { - return err - } - numberOfPeriods, err := cliutils.ValidatePositiveUint("number-of-periods", c.Args().Get(5)) - if err != nil { - return err - } - blockNumber, err := cliutils.ValidateUint32("blockNumber", c.Args().Get(6)) - if err != nil { - return err - } - // Run - api.PrintResponse(proposeRecurringSpend(c, contractName, recipient, amountPerPeriod, periodLength, time.Unix(int64(startTime), 0), numberOfPeriods, blockNumber, c.Args().Get(7))) - return nil - - }, - }, - - { - Name: "can-propose-recurring-spend-update", - Usage: "Check whether the node can propose an update to an existing recurring spend plan", - UsageText: "rocketpool api pdao can-propose-recurring-spend-update contract-name recipient amount-per-period period-length number-of-periods custom-message", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 6); err != nil { - return err - } - contractName := c.Args().Get(0) - recipient, err := cliutils.ValidateAddress("recipient", c.Args().Get(1)) - if err != nil { - return err - } - amountPerPeriod, err := cliutils.ValidateBigInt("amount-per-period", c.Args().Get(2)) - if err != nil { - return err - } - periodLength, err := cliutils.ValidateDuration("period-length", c.Args().Get(3)) - if err != nil { - return err - } - numberOfPeriods, err := cliutils.ValidatePositiveUint("number-of-periods", c.Args().Get(4)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeRecurringSpendUpdate(c, contractName, recipient, amountPerPeriod, periodLength, numberOfPeriods, c.Args().Get(5))) - return nil - - }, - }, - { - Name: "propose-recurring-spend-update", - Usage: "Propose an update to an existing recurring spend plan", - UsageText: "rocketpool api pdao propose-recurring-spend-update contract-name recipient amount-per-period period-length number-of-periods block-number custom-message", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 7); err != nil { - return err - } - contractName := c.Args().Get(0) - recipient, err := cliutils.ValidateAddress("recipient", c.Args().Get(1)) - if err != nil { - return err - } - amountPerPeriod, err := cliutils.ValidateBigInt("amount-per-period", c.Args().Get(2)) - if err != nil { - return err - } - periodLength, err := cliutils.ValidateDuration("period-length", c.Args().Get(3)) - if err != nil { - return err - } - numberOfPeriods, err := cliutils.ValidatePositiveUint("number-of-periods", c.Args().Get(4)) - if err != nil { - return err - } - blockNumber, err := cliutils.ValidateUint32("blockNumber", c.Args().Get(5)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeRecurringSpendUpdate(c, contractName, recipient, amountPerPeriod, periodLength, numberOfPeriods, blockNumber, c.Args().Get(6))) - return nil - - }, - }, - - { - Name: "can-propose-invite-to-security-council", - Usage: "Check whether the node can invite someone to the security council", - UsageText: "rocketpool api pdao can-propose-invite-to-security-council id address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - id := c.Args().Get(0) - address, err := cliutils.ValidateAddress("address", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeInviteToSecurityCouncil(c, id, address)) - return nil - - }, - }, - { - Name: "propose-invite-to-security-council", - Usage: "Propose inviting someone to the security council", - UsageText: "rocketpool api pdao propose-invite-to-security-council id address block-number", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - id := c.Args().Get(0) - address, err := cliutils.ValidateAddress("address", c.Args().Get(1)) - if err != nil { - return err - } - blockNumber, err := cliutils.ValidateUint32("blockNumber", c.Args().Get(2)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeInviteToSecurityCouncil(c, id, address, blockNumber)) - return nil - - }, - }, - - { - Name: "can-propose-kick-from-security-council", - Usage: "Check whether the node can kick someone from the security council", - UsageText: "rocketpool api pdao can-propose-kick-from-security-council address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - address, err := cliutils.ValidateAddress("address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeKickFromSecurityCouncil(c, address)) - return nil - - }, - }, - { - Name: "propose-kick-from-security-council", - Usage: "Propose kicking someone from the security council", - UsageText: "rocketpool api pdao propose-kick-from-security-council address block-number", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - address, err := cliutils.ValidateAddress("address", c.Args().Get(0)) - if err != nil { - return err - } - blockNumber, err := cliutils.ValidateUint32("blockNumber", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeKickFromSecurityCouncil(c, address, blockNumber)) - return nil - - }, - }, - - { - Name: "can-propose-kick-multi-from-security-council", - Usage: "Check whether the node can kick multiple members from the security council", - UsageText: "rocketpool api pdao can-propose-kick-multi-from-security-council addresses", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - addresses, err := cliutils.ValidateAddresses("address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeKickMultiFromSecurityCouncil(c, addresses)) - return nil - - }, - }, - { - Name: "propose-kick-multi-from-security-council", - Usage: "Propose kicking multiple members from the security council", - UsageText: "rocketpool api pdao propose-kick-multi-from-security-council addresses block-number", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - addresses, err := cliutils.ValidateAddresses("addresses", c.Args().Get(0)) - if err != nil { - return err - } - blockNumber, err := cliutils.ValidateUint32("blockNumber", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeKickMultiFromSecurityCouncil(c, addresses, blockNumber)) - return nil - - }, - }, - - { - Name: "can-propose-replace-member-of-security-council", - Usage: "Check whether the node can propose replacing someone on the security council with another member", - UsageText: "rocketpool api pdao can-propose-replace-member-of-security-council existing-address new-id new-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - existingAddress, err := cliutils.ValidateAddress("existingAddress", c.Args().Get(0)) - if err != nil { - return err - } - newID := c.Args().Get(1) - newAddress, err := cliutils.ValidateAddress("newAddress", c.Args().Get(2)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProposeReplaceMemberOfSecurityCouncil(c, existingAddress, newID, newAddress)) - return nil - - }, - }, - { - Name: "propose-replace-member-of-security-council", - Usage: "Propose replacing someone on the security council with another member", - UsageText: "rocketpool api pdao propose-replace-member-of-security-council existing-address new-id new-address block-number", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 4); err != nil { - return err - } - existingAddress, err := cliutils.ValidateAddress("existingAddress", c.Args().Get(0)) - if err != nil { - return err - } - newID := c.Args().Get(1) - newAddress, err := cliutils.ValidateAddress("newAddress", c.Args().Get(2)) - if err != nil { - return err - } - blockNumber, err := cliutils.ValidateUint32("blockNumber", c.Args().Get(3)) - if err != nil { - return err - } - - // Run - api.PrintResponse(proposeReplaceMemberOfSecurityCouncil(c, existingAddress, newID, newAddress, blockNumber)) - return nil - - }, - }, - - { - Name: "get-claimable-bonds", - Usage: "Get the list of proposals with claimable / rewardable bonds, and the relevant indices for each one", - UsageText: "rocketpool api pdao get-claimable-bonds", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getClaimableBonds(c)) - return nil - - }, - }, - - { - Name: "can-claim-bonds", - Usage: "Check whether the node can claim the bonds and/or rewards from a proposal", - UsageText: "rocketpool api pdao can-claim-bonds proposal-id tree-node-indices", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - indices, err := cliutils.ValidatePositiveUints("indices", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canClaimBonds(c, proposalId, indices)) - return nil - - }, - }, - { - Name: "claim-bonds", - Usage: "Claim the bonds and/or rewards from a proposal", - UsageText: "rocketpool api pdao claim-bonds is-proposer proposal-id tree-node-indice", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - isProposer, err := cliutils.ValidateBool("is-proposer", c.Args().Get(0)) - if err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal-id", c.Args().Get(1)) - if err != nil { - return err - } - indices, err := cliutils.ValidatePositiveUints("indices", c.Args().Get(2)) - if err != nil { - return err - } - - // Run - api.PrintResponse(claimBonds(c, isProposer, proposalId, indices)) - return nil - - }, - }, - - { - Name: "can-defeat-proposal", - Usage: "Check whether a proposal can be defeated with the provided tree index", - UsageText: "rocketpool api pdao can-defeat-proposal proposal-id challenged-index", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal-id", c.Args().Get(0)) - if err != nil { - return err - } - index, err := cliutils.ValidatePositiveUint("challenged-index", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canDefeatProposal(c, proposalId, index)) - return nil - - }, - }, - { - Name: "defeat-proposal", - Usage: "Defeat a proposal if it still has a challenge after voting has started", - UsageText: "rocketpool api pdao defeat-proposal proposal-id challenged-index", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal-id", c.Args().Get(0)) - if err != nil { - return err - } - index, err := cliutils.ValidatePositiveUint("challenged-index", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(defeatProposal(c, proposalId, index)) - return nil - - }, - }, - - { - Name: "can-finalize-proposal", - Usage: "Check whether a proposal can be finalized after being vetoed", - UsageText: "rocketpool api pdao can-finalize-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal-id", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canFinalizeProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "finalize-proposal", - Usage: "Finalize a proposal if it's been vetoed by burning the proposer's bond", - UsageText: "rocketpool api pdao finalize-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal-id", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(finalizeProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "estimate-set-voting-delegate-gas", - Usage: "Estimate the gas required to set an on-chain voting delegate", - UsageText: "rocketpool api pdao estimate-set-voting-delegate-gas address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - delegate, err := cliutils.ValidateAddress("delegate", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(estimateSetVotingDelegateGas(c, delegate)) - return nil - - }, - }, - { - Name: "set-voting-delegate", - Usage: "Set an on-chain voting delegate for the node", - UsageText: "rocketpool api pdao set-voting-delegate address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - delegate, err := cliutils.ValidateAddress("delegate", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(setVotingDelegate(c, delegate)) - return nil - - }, - }, - { - Name: "get-current-voting-delegate", - Usage: "Get the current on-chain voting delegate for the node", - UsageText: "rocketpool api pdao get-current-voting-delegate", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getCurrentVotingDelegate(c)) - return nil - - }, - }, - { - Name: "status", - Usage: "Get the pdao status", - UsageText: "rocketpool api pdao status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c)) - return nil - - }, - }, - { - Name: "can-set-signalling-address", - Usage: "Checks if signalling address can be set.", - UsageText: "rocketpool api pdao can-set-signalling-address signalling-address signature", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - signallingAddress, err := cliutils.ValidateAddress("signalling-address", c.Args().Get(0)) - if err != nil { - return err - } - signature, err := cliutils.ValidateSignature("signature", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canSetSignallingAddress(c, signallingAddress, signature)) - return nil - - }, - }, - { - Name: "set-signalling-address", - Usage: "Set the signalling address for the node", - UsageText: "rocketpool api pdao set-signalling-address signalling-address signature", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - signallingAddress, err := cliutils.ValidateAddress("signalling-address", c.Args().Get(0)) - if err != nil { - return err - } - signature, err := cliutils.ValidateSignature("signature", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(setSignallingAddress(c, signallingAddress, signature)) - return nil - - }, - }, - { - Name: "can-clear-signalling-address", - Usage: "Checks if the signalling address can be cleared.", - UsageText: "rocketpool api pdao can-clear-signalling-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - // Run - api.PrintResponse(canClearSignallingAddress(c)) - return nil - - }, - }, - { - Name: "clear-signalling-address", - Usage: "Clear the signalling delegate address for the node", - UsageText: "rocketpool api pdao clear-signalling-address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - // Run - api.PrintResponse(clearSignallingAddress(c)) - return nil - - }, - }, - { - Name: "can-propose-allow-listed-controllers", - Usage: "Check whether the node can propose a list of addresses that can update commission share parameters", - UsageText: "rocketpool api pdao can-propose-allow-listed-controllers addresses", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if c.NArg() > 2 { - return fmt.Errorf("Incorrect argument count;") - } - - var addressList []common.Address - var err error - if c.NArg() != 0 { - addressList, err = cliutils.ValidateAddresses("addressList", c.Args().Get(0)) - if err != nil { - return err - } - } - // Run - api.PrintResponse(canProposeAllowListedControllers(c, addressList)) - return nil - - }, - }, - { - Name: "propose-allow-listed-controllers", - Usage: "Propose a list of addresses that can update commission share parameters", - UsageText: "rocketpool api pdao propose-allow-listed-controllers addresses block-number", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if c.NArg() > 3 || c.NArg() < 1 { - return fmt.Errorf("Incorrect argument count;") - } - - var addressList []common.Address - var blockNumber uint32 - var err error - - // Handles a case where an empty addressList is passed, to propose an empty addressList - if c.NArg() == 1 { - blockNumber, err = cliutils.ValidateUint32("blockNumber", c.Args().Get(0)) - if err != nil { - return err - } - } else { - addressList, err = cliutils.ValidateAddresses("addressList", c.Args().Get(0)) - if err != nil { - return err - } - blockNumber, err = cliutils.ValidateUint32("blockNumber", c.Args().Get(1)) - if err != nil { - return err - } - } - - // Run - api.PrintResponse(proposeAllowListedControllers(c, addressList, blockNumber)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/queue/commands.go b/rocketpool/api/queue/commands.go deleted file mode 100644 index bc9862546..000000000 --- a/rocketpool/api/queue/commands.go +++ /dev/null @@ -1,149 +0,0 @@ -package queue - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the Rocket Pool deposit queue", - Commands: []*cli.Command{ - - { - Name: "status", - Aliases: []string{"s"}, - Usage: "Get the deposit pool and minipool queue status", - UsageText: "rocketpool api queue status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c)) - return nil - - }, - }, - - { - Name: "can-process", - Usage: "Check whether the deposit pool can be processed", - UsageText: "rocketpool api queue can-process max-validators", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - max, err := cliutils.ValidatePositiveUint32("max-validators", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canProcessQueue(c, int64(max))) - return nil - - }, - }, - { - Name: "process", - Aliases: []string{"p"}, - Usage: "Process the deposit pool", - UsageText: "rocketpool api queue process max-validators", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - max, err := cliutils.ValidatePositiveUint32("max-validators", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(processQueue(c, int64(max))) - return nil - - }, - }, - { - Name: "get-queue-details", - Usage: "Gets queue details.", - UsageText: "rocketpool api queue get-queue-details", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getQueueDetails(c)) - return nil - - }, - }, - - { - Name: "can-assign-deposits", - Usage: "Check whether deposits can be assigned", - UsageText: "rocketpool api queue can-assign-deposits max", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - max, err := cliutils.ValidatePositiveUint32("max", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canAssignDeposits(c, int64(max))) - return nil - - }, - }, - { - Name: "assign-deposits", - Aliases: []string{"ad"}, - Usage: "Assign deposits to queued validators", - UsageText: "rocketpool api queue assign-deposits max", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - max, err := cliutils.ValidatePositiveUint32("max", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(assignDeposits(c, int64(max))) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/security/commands.go b/rocketpool/api/security/commands.go deleted file mode 100644 index b6037f8a2..000000000 --- a/rocketpool/api/security/commands.go +++ /dev/null @@ -1,419 +0,0 @@ -package security - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the Rocket Pool security council", - Commands: []*cli.Command{ - - { - Name: "status", - Aliases: []string{"s"}, - Usage: "Get security council status", - UsageText: "rocketpool api security status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c)) - return nil - - }, - }, - { - Name: "members", - Aliases: []string{"m"}, - Usage: "Get the security council members", - UsageText: "rocketpool api security members", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getMembers(c)) - return nil - - }, - }, - - { - Name: "proposals", - Aliases: []string{"p"}, - Usage: "Get the security council proposals", - UsageText: "rocketpool api security proposals", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getProposals(c)) - return nil - - }, - }, - - { - Name: "proposal-details", - Aliases: []string{"d"}, - Usage: "Get details of a proposal", - UsageText: "rocketpool api security proposal-details proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - var err error - if err = cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - id, err := cliutils.ValidateUint("proposal-id", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(getProposal(c, id)) - return nil - - }, - }, - { - Name: "can-propose-leave", - Usage: "Check whether the node can propose leaving the security council", - UsageText: "rocketpool api security can-propose-leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canProposeLeave(c)) - return nil - - }, - }, - { - Name: "propose-leave", - Aliases: []string{"l"}, - Usage: "Propose leaving the security council", - UsageText: "rocketpool api security propose-leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(proposeLeave(c)) - return nil - - }, - }, - { - Name: "can-leave", - Usage: "Check whether the node can leave the security council", - UsageText: "rocketpool api security can-leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canLeave(c)) - return nil - - }, - }, - { - Name: "leave", - Aliases: []string{"l"}, - Usage: "Leave the security council", - UsageText: "rocketpool api security propose-leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(leave(c)) - return nil - - }, - }, - { - Name: "can-cancel-proposal", - Usage: "Check whether the node can cancel a proposal", - UsageText: "rocketpool api security can-cancel-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canCancelProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "cancel-proposal", - Aliases: []string{"c"}, - Usage: "Cancel a proposal made by the node", - UsageText: "rocketpool api security cancel-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(cancelProposal(c, proposalId)) - return nil - - }, - }, - - { - Name: "can-vote-proposal", - Usage: "Check whether the node can vote on a proposal", - UsageText: "rocketpool api security can-vote-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canVoteOnProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "vote-proposal", - Aliases: []string{"v"}, - Usage: "Vote on a proposal", - UsageText: "rocketpool api security vote-proposal proposal-id support", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - support, err := cliutils.ValidateBool("support", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(voteOnProposal(c, proposalId, support)) - return nil - - }, - }, - - { - Name: "can-execute-proposal", - Usage: "Check whether the node can execute a proposal", - UsageText: "rocketpool api security can-execute-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canExecuteProposal(c, proposalId)) - return nil - - }, - }, - { - Name: "execute-proposal", - Aliases: []string{"x"}, - Usage: "Execute a proposal", - UsageText: "rocketpool api security execute-proposal proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - proposalId, err := cliutils.ValidatePositiveUint("proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(executeProposal(c, proposalId)) - return nil - - }, - }, - - { - Name: "can-join", - Usage: "Check whether the node can join the security council", - UsageText: "rocketpool api security can-join", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canJoin(c)) - return nil - - }, - }, - { - Name: "join", - Aliases: []string{"j"}, - Usage: "Join the security council (requires an executed invite proposal)", - UsageText: "rocketpool api security join", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(join(c)) - return nil - - }, - }, - - { - Name: "can-leave", - Usage: "Check whether the node can leave the security council", - UsageText: "rocketpool api security can-leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(canLeave(c)) - return nil - - }, - }, - { - Name: "leave", - Aliases: []string{"e"}, - Usage: "Leave the security council (requires an executed leave proposal)", - UsageText: "rocketpool api security leave", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(leave(c)) - return nil - - }, - }, - - { - Name: "can-propose-setting", - Usage: "Check whether the node can propose a PDAO setting", - UsageText: "rocketpool api security can-propose-setting contract-name setting-name value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - contractName := c.Args().Get(0) - settingName := c.Args().Get(1) - value := c.Args().Get(2) - - // Run - api.PrintResponse(canProposeSetting(c, contractName, settingName, value)) - return nil - - }, - }, - { - Name: "propose-setting", - Usage: "Propose updating a PDAO setting", - UsageText: "rocketpool api security propose-setting contract-name setting-name value", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 3); err != nil { - return err - } - contractName := c.Args().Get(0) - settingName := c.Args().Get(1) - value := c.Args().Get(2) - - // Run - api.PrintResponse(proposeSetting(c, contractName, settingName, value)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/service/commands.go b/rocketpool/api/service/commands.go deleted file mode 100644 index fa2010e60..000000000 --- a/rocketpool/api/service/commands.go +++ /dev/null @@ -1,90 +0,0 @@ -package service - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the Rocket Pool deposit queue", - Commands: []*cli.Command{ - { - Name: "get-gas-price-from-latest-block", - Aliases: []string{"g"}, - Usage: "Get the gas price from the latest block", - UsageText: "rocketpool api gas get-gas-price-from-latest-block", - Action: func(ctx context.Context, c *cli.Command) error { - - // Run - api.PrintResponse(getGasPriceFromLatestBlock(c)) - return nil - - }, - }, - - { - Name: "terminate-data-folder", - Aliases: []string{"t"}, - Usage: "Deletes the data folder including the wallet file, password file, and all validator keys - don't use this unless you have a very good reason to do it (such as switching from a Testnet to Mainnet)", - UsageText: "rocketpool api service terminate-data-folder", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(terminateDataFolder(c)) - return nil - - }, - }, - - { - Name: "get-client-status", - Aliases: []string{"g"}, - Usage: "Gets the status of the configured Execution and Beacon clients", - UsageText: "rocketpool api service get-client-status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getClientStatus(c)) - return nil - - }, - }, - - { - Name: "restart-vc", - Usage: "Restarts the validator client", - UsageText: "rocketpool api service restart-vc", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(restartVc(c)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/wait.go b/rocketpool/api/wait.go new file mode 100644 index 000000000..5e5dd6207 --- /dev/null +++ b/rocketpool/api/wait.go @@ -0,0 +1,29 @@ +package api + +import ( + "net/http" + + "github.com/ethereum/go-ethereum/common" + "github.com/urfave/cli" + + "github.com/rocket-pool/smartnode/bindings/utils" + "github.com/rocket-pool/smartnode/shared/services" + apitypes "github.com/rocket-pool/smartnode/shared/types/api" + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +// RegisterWaitRoute registers the /api/wait endpoint on mux. +// It waits for a transaction hash to be mined. +func RegisterWaitRoute(mux *http.ServeMux, c *cli.Context) { + mux.HandleFunc("/api/wait", func(w http.ResponseWriter, r *http.Request) { + hash := common.HexToHash(r.URL.Query().Get("txHash")) + rp, err := services.GetRocketPool(c) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + response := apitypes.APIResponse{} + _, err = utils.WaitForTransaction(rp.Client, hash) + apiutils.WriteResponse(w, &response, err) + }) +} diff --git a/rocketpool/api/wallet/commands.go b/rocketpool/api/wallet/commands.go deleted file mode 100644 index c1d209863..000000000 --- a/rocketpool/api/wallet/commands.go +++ /dev/null @@ -1,353 +0,0 @@ -package wallet - -import ( - "context" - - "github.com/urfave/cli/v3" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the node wallet", - Commands: []*cli.Command{ - - { - Name: "status", - Aliases: []string{"s"}, - Usage: "Get the node wallet status", - UsageText: "rocketpool api wallet status", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(getStatus(c)) - return nil - - }, - }, - - { - Name: "set-password", - Aliases: []string{"p"}, - Usage: "Set the node wallet password", - UsageText: "rocketpool api wallet set-password password", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - password, err := cliutils.ValidateNodePassword("wallet password", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(setPassword(c, password)) - return nil - - }, - }, - - { - Name: "init", - Aliases: []string{"i"}, - Usage: "Initialize the node wallet", - UsageText: "rocketpool api wallet init", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "derivation-path", - Aliases: []string{"d"}, - Usage: "Specify the derivation path for the wallet.\nOmit this flag (or leave it blank) for the default of \"m/44'/60'/0'/0/%d\" (where %d is the index).\nSet this to \"ledgerLive\" to use Ledger Live's path of \"m/44'/60'/%d/0/0\".\nSet this to \"mew\" to use MyEtherWallet's path of \"m/44'/60'/0'/%d\".\nFor custom paths, simply enter them here.", - }, - }, - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(initWallet(c)) - return nil - - }, - }, - - { - Name: "recover", - Aliases: []string{"r"}, - Usage: "Recover a node wallet from a mnemonic phrase", - UsageText: "rocketpool api wallet recover mnemonic", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "skip-validator-key-recovery", - Aliases: []string{"k"}, - Usage: "Recover the node wallet, but do not regenerate its validator keys", - }, - &cli.StringFlag{ - Name: "derivation-path", - Aliases: []string{"d"}, - Usage: "Specify the derivation path for the wallet.\nOmit this flag (or leave it blank) for the default of \"m/44'/60'/0'/0/%d\" (where %d is the index).\nSet this to \"ledgerLive\" to use Ledger Live's path of \"m/44'/60'/%d/0/0\".\nSet this to \"mew\" to use MyEtherWallet's path of \"m/44'/60'/0'/%d\".\nFor custom paths, simply enter them here.", - }, - &cli.Uint64Flag{ - Name: "wallet-index", - Aliases: []string{"i"}, - Usage: "Specify the index to use with the derivation path when recovering your wallet", - Value: 0, - }, - }, - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - mnemonic, err := cliutils.ValidateWalletMnemonic("mnemonic", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(recoverWallet(c, mnemonic)) - return nil - - }, - }, - - { - Name: "search-and-recover", - Aliases: []string{"r"}, - Usage: "Search for and recover a node wallet's derivation key and index using a mnemonic phrase and a well-known address.", - UsageText: "rocketpool api wallet search-and-recover mnemonic address", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "skip-validator-key-recovery", - Aliases: []string{"k"}, - Usage: "Recover the node wallet, but do not regenerate its validator keys", - }, - }, - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - mnemonic, err := cliutils.ValidateWalletMnemonic("mnemonic", c.Args().Get(0)) - if err != nil { - return err - } - address, err := cliutils.ValidateAddress("address", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(searchAndRecoverWallet(c, mnemonic, address)) - return nil - - }, - }, - - { - Name: "rebuild", - Aliases: []string{"b"}, - Usage: "Rebuild validator keystores from derived keys", - UsageText: "rocketpool api wallet rebuild", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(rebuildWallet(c)) - return nil - - }, - }, - - { - Name: "test-recovery", - Aliases: []string{"r"}, - Usage: "Test recovery of a node wallet and its validator keys without actually saving the recovered files", - UsageText: "rocketpool api wallet test-recovery mnemonic", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "skip-validator-key-recovery", - Aliases: []string{"k"}, - Usage: "Recover the node wallet, but do not regenerate its validator keys", - }, - &cli.StringFlag{ - Name: "derivation-path", - Aliases: []string{"d"}, - Usage: "Specify the derivation path for the wallet.\nOmit this flag (or leave it blank) for the default of \"m/44'/60'/0'/0/%d\" (where %d is the index).\nSet this to \"ledgerLive\" to use Ledger Live's path of \"m/44'/60'/%d/0/0\".\nSet this to \"mew\" to use MyEtherWallet's path of \"m/44'/60'/0'/%d\".\nFor custom paths, simply enter them here.", - }, - &cli.Uint64Flag{ - Name: "wallet-index", - Aliases: []string{"i"}, - Usage: "Specify the index to use with the derivation path when recovering your wallet", - Value: 0, - }, - }, - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - mnemonic, err := cliutils.ValidateWalletMnemonic("mnemonic", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(testRecoverWallet(c, mnemonic)) - return nil - - }, - }, - - { - Name: "test-search-and-recover", - Aliases: []string{"r"}, - Usage: "Test searching for and recovery of a node wallet's derivation key, index, and validator keys using a mnemonic phrase and a well-known address.", - UsageText: "rocketpool api wallet test-search-and-recover mnemonic address", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "skip-validator-key-recovery", - Aliases: []string{"k"}, - Usage: "Recover the node wallet, but do not regenerate its validator keys", - }, - }, - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 2); err != nil { - return err - } - mnemonic, err := cliutils.ValidateWalletMnemonic("mnemonic", c.Args().Get(0)) - if err != nil { - return err - } - address, err := cliutils.ValidateAddress("address", c.Args().Get(1)) - if err != nil { - return err - } - - // Run - api.PrintResponse(testSearchAndRecoverWallet(c, mnemonic, address)) - return nil - - }, - }, - - { - Name: "export", - Aliases: []string{"e"}, - Usage: "Export the node wallet in JSON format", - UsageText: "rocketpool api wallet export", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(exportWallet(c)) - return nil - - }, - }, - - { - Name: "estimate-gas-set-ens-name", - Usage: "Estimate the gas required to set the name for the node wallet's ENS reverse record", - UsageText: "rocketpool api node estimate-gas-set-ens-name name", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Run - api.PrintResponse(setEnsName(c, c.Args().Get(0), true)) - return nil - - }, - }, - - { - Name: "set-ens-name", - Usage: "Set a name to the node wallet's ENS reverse record", - UsageText: "rocketpool api node set-ens-name name", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - - // Run - api.PrintResponse(setEnsName(c, c.Args().Get(0), false)) - return nil - - }, - }, - - { - Name: "masquerade", - Usage: "Change your node's effective address to a different one. Your node will not be able to submit transactions or sign messages since you don't have the corresponding wallet's private key.", - UsageText: "rocketpool api wallet masquerade address", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - address, err := cliutils.ValidateAddress("address", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(masquerade(c, address)) - return nil - - }, - }, - - { - Name: "end-masquerade", - Usage: "End a masquerade, restoring your node's effective address back to your wallet address if one is loaded.", - UsageText: "rocketpool api wallet end-masquerade", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 0); err != nil { - return err - } - - // Run - api.PrintResponse(endMasquerade(c)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index a1844deeb..ddaffc952 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -5,6 +5,7 @@ import ( "github.com/urfave/cli" + apiroutes "github.com/rocket-pool/smartnode/rocketpool/api" auctionroutes "github.com/rocket-pool/smartnode/rocketpool/api/auction" megapoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/megapool" minipoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/minipool" @@ -25,6 +26,7 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { w.WriteHeader(http.StatusOK) }) + apiroutes.RegisterWaitRoute(mux, c) auctionroutes.RegisterRoutes(mux, c) megapoolroutes.RegisterRoutes(mux, c) minipoolroutes.RegisterRoutes(mux, c) diff --git a/rocketpool/rocketpool.go b/rocketpool/rocketpool.go index 9cdadceb3..ed2c971fc 100644 --- a/rocketpool/rocketpool.go +++ b/rocketpool/rocketpool.go @@ -7,11 +7,9 @@ import ( cli "github.com/urfave/cli/v3" - "github.com/rocket-pool/smartnode/rocketpool/api" "github.com/rocket-pool/smartnode/rocketpool/node" "github.com/rocket-pool/smartnode/rocketpool/watchtower" "github.com/rocket-pool/smartnode/shared" - apiutils "github.com/rocket-pool/smartnode/shared/utils/api" blsversionpin "github.com/herumi/bls-eth-go-binary/bls" ) @@ -83,25 +81,13 @@ func main() { } // Register commands - api.RegisterCommands(app, "api", []string{"a"}) node.RegisterCommands(app, "node", []string{"n"}) watchtower.RegisterCommands(app, "watchtower", []string{"w"}) - // Get command being run - var commandName string - app.Before = func(ctx context.Context, c *cli.Command) (context.Context, error) { - commandName = c.Args().First() - return ctx, nil - } - // Run application if err := app.Run(context.Background(), os.Args); err != nil { - if commandName == "api" { - apiutils.PrintErrorResponse(err) - } else { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } + fmt.Fprintln(os.Stderr, err) + os.Exit(1) } } diff --git a/shared/services/rocketpool/api.go b/shared/services/rocketpool/api.go index 42ccddd01..d2a633272 100644 --- a/shared/services/rocketpool/api.go +++ b/shared/services/rocketpool/api.go @@ -2,6 +2,7 @@ package rocketpool import ( "fmt" + "net/url" "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" @@ -10,7 +11,7 @@ import ( // Wait for a transaction func (c *Client) WaitForTransaction(txHash common.Hash) (api.APIResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("wait %s", txHash.String())) + responseBytes, err := c.callHTTPAPI("GET", "/api/wait", url.Values{"txHash": {txHash.Hex()}}) if err != nil { return api.APIResponse{}, fmt.Errorf("Error waiting for tx: %w", err) } diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index 17ecb084c..386edaa1c 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -122,7 +122,6 @@ func checkClientStatus(rp *Client) (bool, error) { // Primary EC and CC are good if ecMgrStatus.PrimaryClientStatus.IsSynced && bcMgrStatus.PrimaryClientStatus.IsSynced { - rp.SetClientStatusFlags(true, false) return true, nil } @@ -1039,11 +1038,6 @@ func (c *Client) AssignGasSettings(maxFee float64, maxPrioFee float64, gasLimit } // Set the flags for ignoring EC and CC sync checks and forcing fallbacks to prevent unnecessary duplication of effort by the API during CLI commands -func (c *Client) SetClientStatusFlags(ignoreSyncCheck bool, forceFallbacks bool) { - c.ignoreSyncCheck = ignoreSyncCheck - c.forceFallbacks = forceFallbacks -} - func (c *Client) checkIfCommandExists(command string) (bool, error) { // Run `type` to check for existence cmd := fmt.Sprintf("type %s", command) @@ -1326,7 +1320,7 @@ func (c *Client) callHTTPAPI(method, path string, params url.Values) ([]byte, er return nil, fmt.Errorf("error building HTTP request for %s %s: %w", method, path, err) } - if c.debugPrint { + if c.globals.DebugPrint { fmt.Printf("HTTP API: %s %s\n", method, target) } @@ -1341,7 +1335,7 @@ func (c *Client) callHTTPAPI(method, path string, params url.Values) ([]byte, er return nil, fmt.Errorf("error reading HTTP API response for %s %s: %w", method, path, err) } - if c.debugPrint { + if c.globals.DebugPrint { fmt.Printf("HTTP API response (%d): %s\n", resp.StatusCode, string(responseBytes)) } diff --git a/shared/services/rocketpool/node.go b/shared/services/rocketpool/node.go index c27b903da..d8f0b519b 100644 --- a/shared/services/rocketpool/node.go +++ b/shared/services/rocketpool/node.go @@ -1223,8 +1223,6 @@ func (c *Client) ReverseResolveEnsName(name string) (api.ResolveEnsNameResponse, // Use the node private key to sign an arbitrary message func (c *Client) SignMessage(message string) (api.NodeSignResponse, error) { - // Ignore sync status so we can sign messages even without ready clients - c.ignoreSyncCheck = true responseBytes, err := c.callHTTPAPI("POST", "/api/node/sign-message", url.Values{"message": {message}}) if err != nil { return api.NodeSignResponse{}, fmt.Errorf("Could not sign message: %w", err) diff --git a/shared/services/rocketpool/odao.go b/shared/services/rocketpool/odao.go index 757296487..b600d02ec 100644 --- a/shared/services/rocketpool/odao.go +++ b/shared/services/rocketpool/odao.go @@ -154,40 +154,6 @@ func (c *Client) ProposeLeaveTNDAO() (api.ProposeTNDAOLeaveResponse, error) { return response, nil } -// Check whether the node can propose replacing its position with a new member -// No server-side handler exists for this command; kept on callAPI. -func (c *Client) CanProposeReplaceTNDAOMember(memberAddress common.Address, memberId, memberUrl string) (api.CanProposeTNDAOReplaceResponse, error) { - responseBytes, err := c.callAPI("odao can-propose-replace", memberAddress.Hex(), memberId, memberUrl) - if err != nil { - return api.CanProposeTNDAOReplaceResponse{}, fmt.Errorf("Could not get can propose replacing oracle DAO member status: %w", err) - } - var response api.CanProposeTNDAOReplaceResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.CanProposeTNDAOReplaceResponse{}, fmt.Errorf("Could not decode can propose replacing oracle DAO member response: %w", err) - } - if response.Error != "" { - return api.CanProposeTNDAOReplaceResponse{}, fmt.Errorf("Could not get can propose replacing oracle DAO member status: %s", response.Error) - } - return response, nil -} - -// Propose replacing the node's position with a new member -// No server-side handler exists for this command; kept on callAPI. -func (c *Client) ProposeReplaceTNDAOMember(memberAddress common.Address, memberId, memberUrl string) (api.ProposeTNDAOReplaceResponse, error) { - responseBytes, err := c.callAPI("odao propose-replace", memberAddress.Hex(), memberId, memberUrl) - if err != nil { - return api.ProposeTNDAOReplaceResponse{}, fmt.Errorf("Could not propose replacing oracle DAO member: %w", err) - } - var response api.ProposeTNDAOReplaceResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.ProposeTNDAOReplaceResponse{}, fmt.Errorf("Could not decode propose replacing oracle DAO member response: %w", err) - } - if response.Error != "" { - return api.ProposeTNDAOReplaceResponse{}, fmt.Errorf("Could not propose replacing oracle DAO member: %s", response.Error) - } - return response, nil -} - // Check whether the node can propose kicking a member func (c *Client) CanProposeKickFromTNDAO(memberAddress common.Address, fineAmountWei *big.Int) (api.CanProposeTNDAOKickResponse, error) { responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-kick", url.Values{ @@ -409,57 +375,6 @@ func (c *Client) LeaveTNDAO(bondRefundAddress common.Address) (api.LeaveTNDAORes return response, nil } -// Check whether the node can replace its position in the oracle DAO -// No server-side handler exists for this command; kept on callAPI. -func (c *Client) CanReplaceTNDAOMember() (api.CanReplaceTNDAOPositionResponse, error) { - responseBytes, err := c.callAPI("odao can-replace") - if err != nil { - return api.CanReplaceTNDAOPositionResponse{}, fmt.Errorf("Could not get can replace oracle DAO member status: %w", err) - } - var response api.CanReplaceTNDAOPositionResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.CanReplaceTNDAOPositionResponse{}, fmt.Errorf("Could not decode can replace oracle DAO member response: %w", err) - } - if response.Error != "" { - return api.CanReplaceTNDAOPositionResponse{}, fmt.Errorf("Could not get can replace oracle DAO member status: %s", response.Error) - } - return response, nil -} - -// Replace the node's position in the oracle DAO (requires an executed replace proposal) -// No server-side handler exists for this command; kept on callAPI. -func (c *Client) ReplaceTNDAOMember() (api.ReplaceTNDAOPositionResponse, error) { - responseBytes, err := c.callAPI("odao replace") - if err != nil { - return api.ReplaceTNDAOPositionResponse{}, fmt.Errorf("Could not replace oracle DAO member: %w", err) - } - var response api.ReplaceTNDAOPositionResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.ReplaceTNDAOPositionResponse{}, fmt.Errorf("Could not decode replace oracle DAO member response: %w", err) - } - if response.Error != "" { - return api.ReplaceTNDAOPositionResponse{}, fmt.Errorf("Could not replace oracle DAO member: %s", response.Error) - } - return response, nil -} - -// Check whether the node can propose a setting update (generic) -// No server-side handler for the no-argument "can-propose-setting" command; kept on callAPI. -func (c *Client) CanProposeTNDAOSetting() (api.CanProposeTNDAOSettingResponse, error) { - responseBytes, err := c.callAPI("odao can-propose-setting") - if err != nil { - return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting status: %w", err) - } - var response api.CanProposeTNDAOSettingResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not decode can propose setting response: %w", err) - } - if response.Error != "" { - return api.CanProposeTNDAOSettingResponse{}, fmt.Errorf("Could not get can propose setting status: %s", response.Error) - } - return response, nil -} - func (c *Client) CanProposeTNDAOSettingMembersQuorum(quorum float64) (api.CanProposeTNDAOSettingResponse, error) { responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-members-quorum", url.Values{"quorum": {strconv.FormatFloat(quorum, 'f', -1, 64)}}) if err != nil { diff --git a/shared/services/rocketpool/security.go b/shared/services/rocketpool/security.go index b7d721dc0..47bfa84e7 100644 --- a/shared/services/rocketpool/security.go +++ b/shared/services/rocketpool/security.go @@ -3,9 +3,7 @@ package rocketpool import ( "fmt" "net/url" - "strings" - "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" "github.com/rocket-pool/smartnode/shared/types/api" ) @@ -74,41 +72,6 @@ func (c *Client) SecurityProposal(id uint64) (api.SecurityProposalResponse, erro return response, nil } -// NOTE: ProposeInvite/ProposeKick/ProposeKickMulti/ProposeReplace do not have -// server-side handlers in the security API package; they remain on callAPI. - -// Check whether the node can propose inviting a new member -func (c *Client) SecurityCanProposeInvite(memberId string, memberAddress common.Address) (api.SecurityCanProposeInviteResponse, error) { - responseBytes, err := c.callAPI("security can-propose-invite", memberId, memberAddress.Hex()) - if err != nil { - return api.SecurityCanProposeInviteResponse{}, fmt.Errorf("Could not get security-can-propose-invite status: %w", err) - } - var response api.SecurityCanProposeInviteResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityCanProposeInviteResponse{}, fmt.Errorf("Could not decode security-can-propose-invite response: %w", err) - } - if response.Error != "" { - return api.SecurityCanProposeInviteResponse{}, fmt.Errorf("Could not get security-can-propose-invite status: %s", response.Error) - } - return response, nil -} - -// Propose inviting a new member -func (c *Client) SecurityProposeInvite(memberId string, memberAddress common.Address) (api.SecurityProposeInviteResponse, error) { - responseBytes, err := c.callAPI("security propose-invite", memberId, memberAddress.Hex()) - if err != nil { - return api.SecurityProposeInviteResponse{}, fmt.Errorf("Could not propose security council invite: %w", err) - } - var response api.SecurityProposeInviteResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityProposeInviteResponse{}, fmt.Errorf("Could not decode propose security council invite response: %w", err) - } - if response.Error != "" { - return api.SecurityProposeInviteResponse{}, fmt.Errorf("Could not propose security council invite: %s", response.Error) - } - return response, nil -} - // Check whether the node can propose to leave the security council func (c *Client) SecurityProposeLeave() (api.SecurityProposeLeaveResponse, error) { responseBytes, err := c.callHTTPAPI("POST", "/api/security/propose-leave", nil) @@ -141,110 +104,6 @@ func (c *Client) SecurityCanProposeLeave() (api.SecurityCanProposeLeaveResponse, return response, nil } -// Check whether the node can propose kicking a member -func (c *Client) SecurityCanProposeKick(memberAddress common.Address) (api.SecurityCanProposeKickResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security can-propose-kick %s", memberAddress.Hex())) - if err != nil { - return api.SecurityCanProposeKickResponse{}, fmt.Errorf("Could not get security-can-propose-kick status: %w", err) - } - var response api.SecurityCanProposeKickResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityCanProposeKickResponse{}, fmt.Errorf("Could not decode security-can-propose-kick response: %w", err) - } - if response.Error != "" { - return api.SecurityCanProposeKickResponse{}, fmt.Errorf("Could not get security-can-propose-kick status: %s", response.Error) - } - return response, nil -} - -// Propose kicking a member -func (c *Client) SecurityProposeKick(memberAddress common.Address) (api.SecurityProposeKickResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security propose-kick %s", memberAddress.Hex())) - if err != nil { - return api.SecurityProposeKickResponse{}, fmt.Errorf("Could not propose kicking security council member: %w", err) - } - var response api.SecurityProposeKickResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityProposeKickResponse{}, fmt.Errorf("Could not decode propose kicking security council member response: %w", err) - } - if response.Error != "" { - return api.SecurityProposeKickResponse{}, fmt.Errorf("Could not propose kicking security council member: %s", response.Error) - } - return response, nil -} - -// Check whether the node can propose kicking multiple members -func (c *Client) SecurityCanProposeKickMulti(addresses []common.Address) (api.SecurityCanProposeKickMultiResponse, error) { - addressStrings := make([]string, len(addresses)) - for i, address := range addresses { - addressStrings[i] = address.Hex() - } - responseBytes, err := c.callAPI(fmt.Sprintf("security can-propose-kick-multi %s", strings.Join(addressStrings, ","))) - if err != nil { - return api.SecurityCanProposeKickMultiResponse{}, fmt.Errorf("Could not get security-can-propose-kick-multi status: %w", err) - } - var response api.SecurityCanProposeKickMultiResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityCanProposeKickMultiResponse{}, fmt.Errorf("Could not decode security-can-propose-kick-multi response: %w", err) - } - if response.Error != "" { - return api.SecurityCanProposeKickMultiResponse{}, fmt.Errorf("Could not get security-can-propose-kick-multi status: %s", response.Error) - } - return response, nil -} - -// Propose kicking multiple members -func (c *Client) SecurityProposeKickMulti(addresses []common.Address) (api.SecurityProposeKickMultiResponse, error) { - addressStrings := make([]string, len(addresses)) - for i, address := range addresses { - addressStrings[i] = address.Hex() - } - responseBytes, err := c.callAPI(fmt.Sprintf("security propose-kick-multi %s", strings.Join(addressStrings, ","))) - if err != nil { - return api.SecurityProposeKickMultiResponse{}, fmt.Errorf("Could not propose kicking multiple security council members: %w", err) - } - var response api.SecurityProposeKickMultiResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityProposeKickMultiResponse{}, fmt.Errorf("Could not decode propose kicking multiple security council members response: %w", err) - } - if response.Error != "" { - return api.SecurityProposeKickMultiResponse{}, fmt.Errorf("Could not propose kicking multiple security council members: %s", response.Error) - } - return response, nil -} - -// Check whether the node can propose replacing someone on the security council -func (c *Client) SecurityCanProposeReplace(existingAddress common.Address, newID string, newAddress common.Address) (api.SecurityCanProposeReplaceResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security can-propose-replace-member %s", existingAddress.Hex()), newID, newAddress.Hex()) - if err != nil { - return api.SecurityCanProposeReplaceResponse{}, fmt.Errorf("Could not get security-can-propose-replace status: %w", err) - } - var response api.SecurityCanProposeReplaceResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityCanProposeReplaceResponse{}, fmt.Errorf("Could not decode security-can-propose-replace response: %w", err) - } - if response.Error != "" { - return api.SecurityCanProposeReplaceResponse{}, fmt.Errorf("Could not get security-can-propose-replace status: %s", response.Error) - } - return response, nil -} - -// Propose replacing someone on the security council -func (c *Client) SecurityProposeReplace(existingAddress common.Address, newID string, newAddress common.Address) (api.SecurityProposeReplaceResponse, error) { - responseBytes, err := c.callAPI(fmt.Sprintf("security propose-replace-member %s", existingAddress.Hex()), newID, newAddress.Hex()) - if err != nil { - return api.SecurityProposeReplaceResponse{}, fmt.Errorf("Could not propose replacement of security council member: %w", err) - } - var response api.SecurityProposeReplaceResponse - if err := json.Unmarshal(responseBytes, &response); err != nil { - return api.SecurityProposeReplaceResponse{}, fmt.Errorf("Could not decode propose replacement of security council member response: %w", err) - } - if response.Error != "" { - return api.SecurityProposeReplaceResponse{}, fmt.Errorf("Could not propose replacement of security council member: %s", response.Error) - } - return response, nil -} - // Check whether the node can cancel a proposal func (c *Client) SecurityCanCancelProposal(proposalId uint64) (api.SecurityCanCancelProposalResponse, error) { responseBytes, err := c.callHTTPAPI("GET", "/api/security/can-cancel-proposal", url.Values{"id": {fmt.Sprintf("%d", proposalId)}}) diff --git a/shared/utils/api/http.go b/shared/utils/api/http.go index 3d5e4afbe..8fa1a8e9b 100644 --- a/shared/utils/api/http.go +++ b/shared/utils/api/http.go @@ -11,10 +11,8 @@ import ( "github.com/rocket-pool/smartnode/shared/types/api" ) -// WriteResponse serialises response as JSON and writes it to w, applying the -// same Status/Error population logic as PrintResponse. -// response must be a pointer to a struct with string fields named Status and -// Error (same contract as PrintResponse). +// WriteResponse serialises response as JSON and writes it to w. +// response must be a pointer to a struct with string fields named Status and Error. func WriteResponse(w http.ResponseWriter, response interface{}, responseError error) { r := reflect.ValueOf(response) if !(r.Kind() == reflect.Ptr && r.Type().Elem().Kind() == reflect.Struct) { diff --git a/shared/utils/api/response.go b/shared/utils/api/response.go index 022b3e0bf..b7b6fd512 100644 --- a/shared/utils/api/response.go +++ b/shared/utils/api/response.go @@ -1,72 +1,9 @@ package api -import ( - "errors" - "fmt" - "math/big" - "reflect" - - "github.com/goccy/go-json" - - "github.com/rocket-pool/smartnode/shared/types/api" -) +import "math/big" func ZeroIfNil(in **big.Int) { if *in == nil { *in = big.NewInt(0) } } - -// Print an API response -// response must be a pointer to a struct type with Error and Status string fields -func PrintResponse(response interface{}, responseError error) { - - // Check response type - r := reflect.ValueOf(response) - if !(r.Kind() == reflect.Ptr && r.Type().Elem().Kind() == reflect.Struct) { - PrintErrorResponse(errors.New("Invalid API response")) - return - } - - // Create zero response value if nil - if r.IsNil() { - response = reflect.New(r.Type().Elem()).Interface() - r = reflect.ValueOf(response) - } - - // Get and check response fields - sf := r.Elem().FieldByName("Status") - ef := r.Elem().FieldByName("Error") - if !(sf.IsValid() && sf.CanSet() && sf.Kind() == reflect.String && ef.IsValid() && ef.CanSet() && ef.Kind() == reflect.String) { - PrintErrorResponse(errors.New("Invalid API response")) - return - } - - // Populate error - if responseError != nil { - ef.SetString(responseError.Error()) - } - - // Set status - if ef.String() == "" { - sf.SetString("success") - } else { - sf.SetString("error") - } - - // Encode - responseBytes, err := json.Marshal(response) - if err != nil { - PrintErrorResponse(fmt.Errorf("Could not encode API response: %w", err)) - return - } - - // Print - fmt.Println(string(responseBytes)) - -} - -// Print an API error response -func PrintErrorResponse(err error) { - PrintResponse(&api.APIResponse{}, err) -} diff --git a/shared/version.txt b/shared/version.txt index bb13bef55..734375f89 100644 --- a/shared/version.txt +++ b/shared/version.txt @@ -1 +1 @@ -1.19.5-dev \ No newline at end of file +1.20.0-dev From 7145eaa1333d89656c636626e9c966ce100dfe44 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:27:38 -0300 Subject: [PATCH 09/24] wip --- rocketpool/api/version.go | 22 +++++++ rocketpool/node/routes/routes.go | 1 + shared/services/ec-manager.go | 16 ++++- shared/services/requirements.go | 12 +++- .../assets/install/templates/api.tmpl | 30 --------- shared/services/rocketpool/client.go | 62 +++++++++---------- shared/services/rocketpool/node.go | 10 ++- 7 files changed, 81 insertions(+), 72 deletions(-) create mode 100644 rocketpool/api/version.go delete mode 100644 shared/services/rocketpool/assets/install/templates/api.tmpl diff --git a/rocketpool/api/version.go b/rocketpool/api/version.go new file mode 100644 index 000000000..832e68741 --- /dev/null +++ b/rocketpool/api/version.go @@ -0,0 +1,22 @@ +package api + +import ( + "net/http" + + "github.com/rocket-pool/smartnode/shared" + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +type VersionResponse struct { + Status string `json:"status"` + Error string `json:"error"` + Version string `json:"version"` +} + +// RegisterVersionRoute registers the /api/version endpoint on mux. +func RegisterVersionRoute(mux *http.ServeMux) { + mux.HandleFunc("/api/version", func(w http.ResponseWriter, r *http.Request) { + response := VersionResponse{Version: shared.RocketPoolVersion()} + apiutils.WriteResponse(w, &response, nil) + }) +} diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index ddaffc952..af15954c4 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -26,6 +26,7 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { w.WriteHeader(http.StatusOK) }) + apiroutes.RegisterVersionRoute(mux) apiroutes.RegisterWaitRoute(mux, c) auctionroutes.RegisterRoutes(mux, c) megapoolroutes.RegisterRoutes(mux, c) diff --git a/shared/services/ec-manager.go b/shared/services/ec-manager.go index a6fc89def..931ca7576 100644 --- a/shared/services/ec-manager.go +++ b/shared/services/ec-manager.go @@ -409,13 +409,21 @@ func getNetworkNameFromId(networkId uint) string { } +// ecStatusTimeout is the per-call deadline used when probing an EC for its +// network ID, sync progress, or latest block. 10 seconds is long enough to +// tolerate transient load on a healthy client while still returning quickly +// when the client is unresponsive. +const ecStatusTimeout = 10 * time.Second + // Check the client status func checkEcStatus(client *ethClient) api.ClientStatus { status := api.ClientStatus{} // Get the NetworkId - networkId, err := client.NetworkID(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), ecStatusTimeout) + networkId, err := client.NetworkID(ctx) + cancel() if err != nil { status.Error = fmt.Sprintf("Sync progress check failed with [%s]", err.Error()) status.IsSynced = false @@ -427,8 +435,10 @@ func checkEcStatus(client *ethClient) api.ClientStatus { status.NetworkId = uint(networkId.Uint64()) } - // Get the fallback's sync progress - progress, err := client.SyncProgress(context.Background()) + // Get the sync progress + ctx, cancel = context.WithTimeout(context.Background(), ecStatusTimeout) + progress, err := client.SyncProgress(ctx) + cancel() if err != nil { status.Error = fmt.Sprintf("Sync progress check failed with [%s]", err.Error()) status.IsSynced = false diff --git a/shared/services/requirements.go b/shared/services/requirements.go index cad320a2a..8a9646131 100644 --- a/shared/services/requirements.go +++ b/shared/services/requirements.go @@ -264,7 +264,9 @@ func getRocketStorageLoaded(c *cli.Command) (bool, error) { if err != nil { return false, err } - code, err := ec.CodeAt(context.Background(), common.HexToAddress(cfg.Smartnode.GetStorageAddress()), nil) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + code, err := ec.CodeAt(ctx, common.HexToAddress(cfg.Smartnode.GetStorageAddress()), nil) if err != nil { return false, err } @@ -477,7 +479,9 @@ func waitEthClientSynced(c *cli.Command, verbose bool, timeout int64) (bool, err } // Get sync progress - progress, err := clientToCheck.SyncProgress(context.Background()) + pollCtx, pollCancel := context.WithTimeout(context.Background(), 10*time.Second) + progress, err := clientToCheck.SyncProgress(pollCtx) + pollCancel() if err != nil { return false, err } @@ -595,7 +599,9 @@ func waitBeaconClientSynced(c *cli.Command, verbose bool, timeout int64) (bool, // Confirm the EC's latest block is within the threshold of the current system clock func IsSyncWithinThreshold(ec rocketpool.ExecutionClient) (bool, time.Time, error) { - t, err := ec.LatestBlockTime(context.Background()) + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + t, err := ec.LatestBlockTime(ctx) if err != nil { return false, time.Time{}, err } diff --git a/shared/services/rocketpool/assets/install/templates/api.tmpl b/shared/services/rocketpool/assets/install/templates/api.tmpl deleted file mode 100644 index 648d17d9d..000000000 --- a/shared/services/rocketpool/assets/install/templates/api.tmpl +++ /dev/null @@ -1,30 +0,0 @@ -# Autogenerated - DO NOT MODIFY THIS FILE DIRECTLY -# If you want to overwrite some of these values with your own customizations, -# please add them to `override/api.yml`. -# -# See https://docs.docker.com/compose/extends/#adding-and-overriding-configuration -# for more information on overriding specific parameters of docker-compose files. - -services: - api: - image: {{.Smartnode.GetSmartnodeContainerTag}} - container_name: {{.Smartnode.ProjectName}}_api - restart: unless-stopped - stop_signal: SIGKILL - stop_grace_period: 1s - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - {{.RocketPoolDirectory}}:/.rocketpool - - {{.Smartnode.DataPath}}:/.rocketpool/data - networks: - - net - entrypoint: /bin/sleep - command: "infinity" - cap_drop: - - all - cap_add: - - dac_override - security_opt: - - no-new-privileges -networks: - net: diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index 386edaa1c..706dff56d 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -3,6 +3,7 @@ package rocketpool import ( "bufio" "bytes" + "context" "errors" "fmt" "io" @@ -43,9 +44,6 @@ const ( PrometheusConfigTemplate string = "prometheus.tmpl" PrometheusFile string = "prometheus.yml" - APIContainerSuffix string = "_api" - APIBinPath string = "/go/bin/rocketpool" - templatesDir string = "templates" overrideDir string = "override" runtimeDir string = "runtime" @@ -546,40 +544,29 @@ func (c *Client) PrintServiceCompose(composeFiles []string) error { // Get the Rocket Pool service version func (c *Client) GetServiceVersion() (string, error) { - - // Get service container version output - var cmd string - if c.globals.DaemonPath == "" { - containerName, err := c.getAPIContainerName() - if err != nil { - return "", err - } - cmd = fmt.Sprintf("docker exec %s %s --version", shellescape.Quote(containerName), shellescape.Quote(APIBinPath)) - } else { - cmd = fmt.Sprintf("%s --version", shellescape.Quote(c.globals.DaemonPath)) + type versionResponse struct { + Status string `json:"status"` + Error string `json:"error"` + Version string `json:"version"` } - versionBytes, err := c.readOutput(cmd) + + responseBytes, err := c.callHTTPAPI("GET", "/api/version", nil) if err != nil { return "", fmt.Errorf("Could not get Rocket Pool service version: %w", err) } - - // Get the version string - outputString := string(versionBytes) - elements := strings.Fields(outputString) // Split on whitespace - if len(elements) < 1 { - return "", fmt.Errorf("Could not parse Rocket Pool service version number from output '%s'", outputString) + var response versionResponse + if err := json.Unmarshal(responseBytes, &response); err != nil { + return "", fmt.Errorf("Could not decode Rocket Pool service version response: %w", err) + } + if response.Error != "" { + return "", fmt.Errorf("Could not get Rocket Pool service version: %s", response.Error) } - versionString := elements[len(elements)-1] - // Make sure it's a semantic version - version, err := semver.Make(versionString) + version, err := semver.Make(response.Version) if err != nil { - return "", fmt.Errorf("Could not parse Rocket Pool service version number from output '%s': %w", outputString, err) + return "", fmt.Errorf("Could not parse Rocket Pool service version number '%s': %w", response.Version, err) } - - // Return the parsed semantic version (extra safety) return version.String(), nil - } // Increments the custom nonce parameter. @@ -1153,7 +1140,6 @@ func (c *Client) deployTemplates(cfg *config.RocketPoolConfig, rocketpoolDir str // These containers always run toDeploy := []string{ - config.ApiContainerName, config.NodeContainerName, config.WatchtowerContainerName, config.ValidatorContainerName, @@ -1284,14 +1270,22 @@ func (c *Client) getAPIURL() string { return c.apiURL } -// callHTTPAPI calls the node's HTTP API server. +// callHTTPAPI calls the node's HTTP API server with a 5-minute safety timeout. // method is "GET" or "POST". // path is the URL path, e.g. "/api/node/status". -// params are appended as query string parameters for GET or as a JSON body -// for POST. +// params are appended as query string parameters for GET or as a form body for POST. // The response body is returned as-is; callers unmarshal it the same way // they currently unmarshal the output of callAPI. func (c *Client) callHTTPAPI(method, path string, params url.Values) ([]byte, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + return c.callHTTPAPICtx(ctx, method, path, params) +} + +// callHTTPAPICtx is the context-aware core of callHTTPAPI. Use it directly +// when a tighter deadline is required (e.g. optional/informational requests +// that must not block the user). +func (c *Client) callHTTPAPICtx(ctx context.Context, method, path string, params url.Values) ([]byte, error) { base := c.getAPIURL() if base == "" { return nil, fmt.Errorf("node HTTP API URL is not configured (APIPort may be 0)") @@ -1306,10 +1300,10 @@ func (c *Client) callHTTPAPI(method, path string, params url.Values) ([]byte, er if len(params) > 0 { target += "?" + params.Encode() } - req, err = http.NewRequest(http.MethodGet, target, nil) + req, err = http.NewRequestWithContext(ctx, http.MethodGet, target, nil) case http.MethodPost: body := []byte(params.Encode()) - req, err = http.NewRequest(http.MethodPost, target, bytes.NewReader(body)) + req, err = http.NewRequestWithContext(ctx, http.MethodPost, target, bytes.NewReader(body)) if err == nil { req.Header.Set("Content-Type", "application/x-www-form-urlencoded") } diff --git a/shared/services/rocketpool/node.go b/shared/services/rocketpool/node.go index d8f0b519b..f54aab1e2 100644 --- a/shared/services/rocketpool/node.go +++ b/shared/services/rocketpool/node.go @@ -1,12 +1,14 @@ package rocketpool import ( + "context" "encoding/hex" "fmt" "math/big" "net/url" "strconv" "strings" + "time" "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" @@ -55,9 +57,13 @@ func (c *Client) NodeStatus() (api.NodeStatusResponse, error) { return response, nil } -// Get active alerts from Alertmanager +// Get active alerts from Alertmanager. +// Uses a short 2-second timeout: alerts are informational and displayed after +// every command, so they must never block the user if the daemon is not yet up. func (c *Client) NodeAlerts() (api.NodeAlertsResponse, error) { - responseBytes, err := c.callHTTPAPI("GET", "/api/node/alerts", nil) + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + responseBytes, err := c.callHTTPAPICtx(ctx, "GET", "/api/node/alerts", nil) if err != nil { return api.NodeAlertsResponse{}, fmt.Errorf("could not get node alerts: %w", err) } From d5b09a12fd34f86146c09185b176951556dfd8a7 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:09:59 -0300 Subject: [PATCH 10/24] fix lint --- shared/services/config/smartnode-config.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shared/services/config/smartnode-config.go b/shared/services/config/smartnode-config.go index bda308ece..5d8c17cc3 100644 --- a/shared/services/config/smartnode-config.go +++ b/shared/services/config/smartnode-config.go @@ -431,12 +431,12 @@ func NewSmartnodeConfig(cfg *RocketPoolConfig) *SmartnodeConfig { }, OpenAPIPort: config.Parameter{ - ID: "openAPIPort", - Name: "Expose API Port", - Description: "Expose the API port to other processes on your machine. For security reasons, this port can only be exposed to localhost. It is recommended to keep this setting on Closed unless you have a specific reason to expose it.", - Type: config.ParameterType_Choice, - Default: map[config.Network]interface{}{config.Network_All: config.RPC_Closed}, - AffectsContainers: []config.ContainerID{config.ContainerID_Node}, + ID: "openAPIPort", + Name: "Expose API Port", + Description: "Expose the API port to other processes on your machine. For security reasons, this port can only be exposed to localhost. It is recommended to keep this setting on Closed unless you have a specific reason to expose it.", + Type: config.ParameterType_Choice, + Default: map[config.Network]interface{}{config.Network_All: config.RPC_Closed}, + AffectsContainers: []config.ContainerID{config.ContainerID_Node}, CanBeBlank: false, OverwriteOnUpgrade: false, Options: config.RestrictedPortModes(), From b222eadbc2a24f852c1d8d9cc16eab46fd7f1b24 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Thu, 19 Mar 2026 18:16:02 -0300 Subject: [PATCH 11/24] Adjust upgrade to use the web api --- rocketpool/api/auction/routes.go | 4 +- rocketpool/api/megapool/routes.go | 10 +- rocketpool/api/minipool/routes.go | 60 +------- rocketpool/api/network/routes.go | 4 +- rocketpool/api/node/routes.go | 4 +- rocketpool/api/odao/routes.go | 4 +- rocketpool/api/pdao/routes.go | 4 +- rocketpool/api/queue/routes.go | 4 +- rocketpool/api/security/routes.go | 4 +- rocketpool/api/service/routes.go | 9 +- rocketpool/api/upgrade/commands.go | 74 ---------- rocketpool/api/upgrade/routes.go | 39 ++++++ rocketpool/api/wait.go | 4 +- rocketpool/api/wallet/routes.go | 4 +- rocketpool/node/http.go | 4 +- rocketpool/node/node.go | 43 +++--- rocketpool/node/routes/routes.go | 6 +- shared/services/rocketpool/client.go | 184 +------------------------ shared/services/rocketpool/command.go | 108 ++------------- shared/services/rocketpool/gas.go | 2 +- shared/services/rocketpool/upgrades.go | 7 +- 21 files changed, 124 insertions(+), 458 deletions(-) delete mode 100644 rocketpool/api/upgrade/commands.go create mode 100644 rocketpool/api/upgrade/routes.go diff --git a/rocketpool/api/auction/routes.go b/rocketpool/api/auction/routes.go index 4e4139b15..89c4b80c0 100644 --- a/rocketpool/api/auction/routes.go +++ b/rocketpool/api/auction/routes.go @@ -6,13 +6,13 @@ import ( "net/http" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the auction module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/auction/status", func(w http.ResponseWriter, r *http.Request) { resp, err := getStatus(c) apiutils.WriteResponse(w, resp, err) diff --git a/rocketpool/api/megapool/routes.go b/rocketpool/api/megapool/routes.go index 457a5c4fe..55eb8834c 100644 --- a/rocketpool/api/megapool/routes.go +++ b/rocketpool/api/megapool/routes.go @@ -7,13 +7,13 @@ import ( "strconv" "github.com/ethereum/go-ethereum/common" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the megapool module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/megapool/status", func(w http.ResponseWriter, r *http.Request) { finalizedState := r.URL.Query().Get("finalizedState") == "true" resp, err := getStatus(c, finalizedState) @@ -275,13 +275,15 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { mux.HandleFunc("/api/megapool/can-set-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { address := common.HexToAddress(r.URL.Query().Get("address")) - resp, err := canSetUseLatestDelegate(c, address) + setting := r.URL.Query().Get("setting") == "true" + resp, err := canSetUseLatestDelegate(c, address, setting) apiutils.WriteResponse(w, resp, err) }) mux.HandleFunc("/api/megapool/set-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { address := common.HexToAddress(r.FormValue("address")) - resp, err := setUseLatestDelegate(c, address) + setting := r.FormValue("setting") == "true" + resp, err := setUseLatestDelegate(c, address, setting) apiutils.WriteResponse(w, resp, err) }) diff --git a/rocketpool/api/minipool/routes.go b/rocketpool/api/minipool/routes.go index 8edd3217a..ceaf9d409 100644 --- a/rocketpool/api/minipool/routes.go +++ b/rocketpool/api/minipool/routes.go @@ -6,13 +6,13 @@ import ( "net/http" "github.com/ethereum/go-ethereum/common" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the minipool module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/minipool/status", func(w http.ResponseWriter, r *http.Request) { resp, err := getStatus(c) apiutils.WriteResponse(w, resp, err) @@ -225,58 +225,6 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { apiutils.WriteResponse(w, resp, err) }) - mux.HandleFunc("/api/minipool/can-begin-reduce-bond-amount", func(w http.ResponseWriter, r *http.Request) { - addr, err := parseAddress(r, "address") - if err != nil { - apiutils.WriteErrorResponse(w, err) - return - } - amountStr := r.URL.Query().Get("newBondAmountWei") - amount, ok := new(big.Int).SetString(amountStr, 10) - if !ok { - apiutils.WriteErrorResponse(w, fmt.Errorf("invalid newBondAmountWei: %s", amountStr)) - return - } - resp, err := canBeginReduceBondAmount(c, addr, amount) - apiutils.WriteResponse(w, resp, err) - }) - - mux.HandleFunc("/api/minipool/begin-reduce-bond-amount", func(w http.ResponseWriter, r *http.Request) { - addr, err := parseAddress(r, "address") - if err != nil { - apiutils.WriteErrorResponse(w, err) - return - } - amountStr := r.FormValue("newBondAmountWei") - amount, ok := new(big.Int).SetString(amountStr, 10) - if !ok { - apiutils.WriteErrorResponse(w, fmt.Errorf("invalid newBondAmountWei: %s", amountStr)) - return - } - resp, err := beginReduceBondAmount(c, addr, amount) - apiutils.WriteResponse(w, resp, err) - }) - - mux.HandleFunc("/api/minipool/can-reduce-bond-amount", func(w http.ResponseWriter, r *http.Request) { - addr, err := parseAddress(r, "address") - if err != nil { - apiutils.WriteErrorResponse(w, err) - return - } - resp, err := canReduceBondAmount(c, addr) - apiutils.WriteResponse(w, resp, err) - }) - - mux.HandleFunc("/api/minipool/reduce-bond-amount", func(w http.ResponseWriter, r *http.Request) { - addr, err := parseAddress(r, "address") - if err != nil { - apiutils.WriteErrorResponse(w, err) - return - } - resp, err := reduceBondAmount(c, addr) - apiutils.WriteResponse(w, resp, err) - }) - mux.HandleFunc("/api/minipool/get-distribute-balance-details", func(w http.ResponseWriter, r *http.Request) { resp, err := getDistributeBalanceDetails(c) apiutils.WriteResponse(w, resp, err) @@ -347,10 +295,6 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { apiutils.WriteResponse(w, resp, err) }) - mux.HandleFunc("/api/minipool/get-bond-reduction-enabled", func(w http.ResponseWriter, r *http.Request) { - resp, err := getBondReductionEnabled(c) - apiutils.WriteResponse(w, resp, err) - }) } func parseAddress(r *http.Request, name string) (common.Address, error) { diff --git a/rocketpool/api/network/routes.go b/rocketpool/api/network/routes.go index 8ec082ab3..bc07a5b61 100644 --- a/rocketpool/api/network/routes.go +++ b/rocketpool/api/network/routes.go @@ -4,13 +4,13 @@ import ( "net/http" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the network module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/network/node-fee", func(w http.ResponseWriter, r *http.Request) { resp, err := getNodeFee(c) apiutils.WriteResponse(w, resp, err) diff --git a/rocketpool/api/node/routes.go b/rocketpool/api/node/routes.go index ea0edfc1d..51c9425b6 100644 --- a/rocketpool/api/node/routes.go +++ b/rocketpool/api/node/routes.go @@ -9,13 +9,13 @@ import ( "github.com/ethereum/go-ethereum/common" rptypes "github.com/rocket-pool/smartnode/bindings/types" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the node module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/status", func(w http.ResponseWriter, r *http.Request) { resp, err := getStatus(c) apiutils.WriteResponse(w, resp, err) diff --git a/rocketpool/api/odao/routes.go b/rocketpool/api/odao/routes.go index 52bc38f24..b2978c72c 100644 --- a/rocketpool/api/odao/routes.go +++ b/rocketpool/api/odao/routes.go @@ -7,13 +7,13 @@ import ( "strconv" "github.com/ethereum/go-ethereum/common" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the odao module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/odao/status", func(w http.ResponseWriter, r *http.Request) { resp, err := getStatus(c) apiutils.WriteResponse(w, resp, err) diff --git a/rocketpool/api/pdao/routes.go b/rocketpool/api/pdao/routes.go index 6825c5d10..893a6a0b3 100644 --- a/rocketpool/api/pdao/routes.go +++ b/rocketpool/api/pdao/routes.go @@ -9,7 +9,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" bindtypes "github.com/rocket-pool/smartnode/bindings/types" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" @@ -17,7 +17,7 @@ import ( ) // RegisterRoutes registers the pdao module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/pdao/status", func(w http.ResponseWriter, r *http.Request) { resp, err := getStatus(c) apiutils.WriteResponse(w, resp, err) diff --git a/rocketpool/api/queue/routes.go b/rocketpool/api/queue/routes.go index bb15ddcce..40e2c7a5c 100644 --- a/rocketpool/api/queue/routes.go +++ b/rocketpool/api/queue/routes.go @@ -4,13 +4,13 @@ import ( "net/http" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the queue module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/queue/status", func(w http.ResponseWriter, r *http.Request) { resp, err := getStatus(c) apiutils.WriteResponse(w, resp, err) diff --git a/rocketpool/api/security/routes.go b/rocketpool/api/security/routes.go index b82e3d787..c217c18e7 100644 --- a/rocketpool/api/security/routes.go +++ b/rocketpool/api/security/routes.go @@ -4,13 +4,13 @@ import ( "net/http" "strconv" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the security module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/security/status", func(w http.ResponseWriter, r *http.Request) { resp, err := getStatus(c) apiutils.WriteResponse(w, resp, err) diff --git a/rocketpool/api/service/routes.go b/rocketpool/api/service/routes.go index 7c49913bf..ca9c2bbb7 100644 --- a/rocketpool/api/service/routes.go +++ b/rocketpool/api/service/routes.go @@ -3,13 +3,13 @@ package service import ( "net/http" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the service module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/service/get-client-status", func(w http.ResponseWriter, r *http.Request) { resp, err := getClientStatus(c) apiutils.WriteResponse(w, resp, err) @@ -24,4 +24,9 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { resp, err := terminateDataFolder(c) apiutils.WriteResponse(w, resp, err) }) + + mux.HandleFunc("/api/service/get-gas-price-from-latest-block", func(w http.ResponseWriter, r *http.Request) { + resp, err := getGasPriceFromLatestBlock(c) + apiutils.WriteResponse(w, resp, err) + }) } diff --git a/rocketpool/api/upgrade/commands.go b/rocketpool/api/upgrade/commands.go deleted file mode 100644 index 5e8868018..000000000 --- a/rocketpool/api/upgrade/commands.go +++ /dev/null @@ -1,74 +0,0 @@ -package upgrade - -import ( - "context" - - "github.com/rocket-pool/smartnode/shared/utils/api" - cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" - "github.com/urfave/cli/v3" -) - -// Register subcommands -func RegisterSubcommands(command *cli.Command, name string, aliases []string) { - command.Commands = append(command.Commands, &cli.Command{ - Name: name, - Aliases: aliases, - Usage: "Manage the Rocket Pool trusted node DAO upgrades", - Commands: []*cli.Command{ - { - Name: "get-upgrade-proposals", - Usage: "List the available upgrades", - UsageText: "rocketpool api upgrades get-upgrade-proposals", - Action: func(ctx context.Context, c *cli.Command) error { - // Run - api.PrintResponse(getUpgradeProposals(c)) - return nil - }, - }, - { - - Name: "can-execute-upgrade", - Usage: "Check whether the node can execute a proposal", - UsageText: "rocketpool api upgrades can-execute-upgrade upgrade-proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - upgradeProposalId, err := cliutils.ValidatePositiveUint("upgrade proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(canExecuteUpgrade(c, upgradeProposalId)) - return nil - - }, - }, - { - Name: "execute-upgrade", - Aliases: []string{"x"}, - Usage: "Execute an upgrade", - UsageText: "rocketpool api upgrades execute-upgrade upgrade-proposal-id", - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } - upgradeProposalId, err := cliutils.ValidatePositiveUint("upgrade proposal ID", c.Args().Get(0)) - if err != nil { - return err - } - - // Run - api.PrintResponse(executeUpgrade(c, upgradeProposalId)) - return nil - - }, - }, - }, - }) -} diff --git a/rocketpool/api/upgrade/routes.go b/rocketpool/api/upgrade/routes.go new file mode 100644 index 000000000..9c19a2626 --- /dev/null +++ b/rocketpool/api/upgrade/routes.go @@ -0,0 +1,39 @@ +package upgrade + +import ( + "net/http" + "strconv" + + "github.com/urfave/cli/v3" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" + cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" +) + +// RegisterRoutes registers the upgrade module's HTTP routes onto mux. +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { + mux.HandleFunc("/api/upgrade/get-upgrade-proposals", func(w http.ResponseWriter, r *http.Request) { + resp, err := getUpgradeProposals(c) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/upgrade/can-execute-upgrade", func(w http.ResponseWriter, r *http.Request) { + id, err := cliutils.ValidatePositiveUint("upgrade proposal ID", r.URL.Query().Get("id")) + if err != nil { + apiutils.WriteResponse(w, nil, err) + return + } + resp, err := canExecuteUpgrade(c, id) + apiutils.WriteResponse(w, resp, err) + }) + + mux.HandleFunc("/api/upgrade/execute-upgrade", func(w http.ResponseWriter, r *http.Request) { + id, err := strconv.ParseUint(r.URL.Query().Get("id"), 10, 64) + if err != nil { + apiutils.WriteResponse(w, nil, err) + return + } + resp, err := executeUpgrade(c, id) + apiutils.WriteResponse(w, resp, err) + }) +} diff --git a/rocketpool/api/wait.go b/rocketpool/api/wait.go index 5e5dd6207..dc30b51b2 100644 --- a/rocketpool/api/wait.go +++ b/rocketpool/api/wait.go @@ -4,7 +4,7 @@ import ( "net/http" "github.com/ethereum/go-ethereum/common" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" "github.com/rocket-pool/smartnode/bindings/utils" "github.com/rocket-pool/smartnode/shared/services" @@ -14,7 +14,7 @@ import ( // RegisterWaitRoute registers the /api/wait endpoint on mux. // It waits for a transaction hash to be mined. -func RegisterWaitRoute(mux *http.ServeMux, c *cli.Context) { +func RegisterWaitRoute(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/wait", func(w http.ResponseWriter, r *http.Request) { hash := common.HexToHash(r.URL.Query().Get("txHash")) rp, err := services.GetRocketPool(c) diff --git a/rocketpool/api/wallet/routes.go b/rocketpool/api/wallet/routes.go index 63c86645e..d99ab0650 100644 --- a/rocketpool/api/wallet/routes.go +++ b/rocketpool/api/wallet/routes.go @@ -5,13 +5,13 @@ import ( "strconv" "github.com/ethereum/go-ethereum/common" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers the wallet module's HTTP routes onto mux. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/wallet/status", func(w http.ResponseWriter, r *http.Request) { resp, err := getStatus(c) apiutils.WriteResponse(w, resp, err) diff --git a/rocketpool/node/http.go b/rocketpool/node/http.go index ca4a09e07..c3dbd1558 100644 --- a/rocketpool/node/http.go +++ b/rocketpool/node/http.go @@ -6,7 +6,7 @@ import ( "log" "net/http" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" "github.com/rocket-pool/smartnode/rocketpool/node/routes" "github.com/rocket-pool/smartnode/shared/services/config" @@ -20,7 +20,7 @@ type httpServer struct { // startHTTP starts the node's HTTP API server and returns immediately. // The server runs in the background for the lifetime of the process. -func startHTTP(ctx context.Context, c *cli.Context, cfg *config.RocketPoolConfig) { +func startHTTP(ctx context.Context, c *cli.Command, cfg *config.RocketPoolConfig) { port, ok := cfg.Smartnode.APIPort.Value.(uint16) if !ok || port == 0 { log.Println("Warning: APIPort not configured, HTTP API server will not start.") diff --git a/rocketpool/node/node.go b/rocketpool/node/node.go index c0929cb23..7e758704b 100644 --- a/rocketpool/node/node.go +++ b/rocketpool/node/node.go @@ -87,16 +87,35 @@ func run(c *cli.Command) error { // Configure configureHTTP() + // Load config early so we can start the HTTP API server before blocking + // on wallet/service readiness. + cfg, err := services.GetConfig(c) + if err != nil { + return err + } + + // Print the current mode + if cfg.IsNativeMode { + fmt.Println("Starting node daemon in Native Mode.") + } else { + fmt.Println("Starting node daemon in Docker Mode.") + } + + // Create a context that is cancelled on SIGINT/SIGTERM so the HTTP server + // and other background goroutines can shut down gracefully. + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer cancel() + + // Start the HTTP API server immediately so the CLI can reach it while + // the daemon waits for the wallet and services to become ready. + startHTTP(ctx, c, cfg) + // Wait until the node wallet stored on disk is registered if err := services.WaitNodeRegistered(c, true); err != nil { return err } // Get services - cfg, err := services.GetConfig(c) - if err != nil { - return err - } rp, err := services.GetRocketPool(c) if err != nil { return err @@ -117,13 +136,6 @@ func run(c *cli.Command) error { fmt.Printf("Protocol version: %s\n", protocolVersion) - // Print the current mode - if cfg.IsNativeMode { - fmt.Println("Starting node daemon in Native Mode.") - } else { - fmt.Println("Starting node daemon in Docker Mode.") - } - nodeAccount, err := w.GetNodeAccount() if err != nil { return fmt.Errorf("error getting node account: %w", err) @@ -133,15 +145,6 @@ func run(c *cli.Command) error { errorLog := log.NewColorLogger(ErrorColor) updateLog := log.NewColorLogger(UpdateColor) - // Create a context that is cancelled on SIGINT/SIGTERM so the HTTP server - // and other background goroutines can shut down gracefully. - ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) - defer cancel() - - // Start the HTTP API server. It runs in the background for the lifetime - // of the daemon and serves all migrated API endpoints. - startHTTP(ctx, c, cfg) - // Create the state manager m := state.NewNetworkStateManager(rp, cfg.Smartnode.GetStateManagerContracts(), bc, &updateLog) stateLocker := collectors.NewStateLocker() diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index af15954c4..22f08281f 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -3,7 +3,7 @@ package routes import ( "net/http" - "github.com/urfave/cli" + "github.com/urfave/cli/v3" apiroutes "github.com/rocket-pool/smartnode/rocketpool/api" auctionroutes "github.com/rocket-pool/smartnode/rocketpool/api/auction" @@ -16,12 +16,13 @@ import ( queueroutes "github.com/rocket-pool/smartnode/rocketpool/api/queue" securityroutes "github.com/rocket-pool/smartnode/rocketpool/api/security" serviceroutes "github.com/rocket-pool/smartnode/rocketpool/api/service" + upgraderoutes "github.com/rocket-pool/smartnode/rocketpool/api/upgrade" walletroutes "github.com/rocket-pool/smartnode/rocketpool/api/wallet" ) // RegisterRoutes registers all HTTP API routes onto mux. // Each migration branch adds additional module registrations here. -func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) }) @@ -38,5 +39,6 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Context) { queueroutes.RegisterRoutes(mux, c) securityroutes.RegisterRoutes(mux, c) serviceroutes.RegisterRoutes(mux, c) + upgraderoutes.RegisterRoutes(mux, c) walletroutes.RegisterRoutes(mux, c) } diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index 706dff56d..dd30731ae 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -22,7 +22,7 @@ import ( "github.com/fatih/color" "github.com/goccy/go-json" - "golang.org/x/crypto/ssh" + "github.com/alessio/shellescape" "github.com/blang/semver/v4" @@ -80,13 +80,7 @@ type Globals struct { // Rocket Pool client type Client struct { - globals Globals - client *ssh.Client - originalMaxFee float64 - originalMaxPrioFee float64 - originalGasLimit uint64 - ignoreSyncCheck bool - forceFallbacks bool + globals Globals // apiURL is the base URL for the node's HTTP API server. // It is derived lazily from config on first use. @@ -138,7 +132,6 @@ func checkClientStatus(rp *Client) (bool, error) { clicolor.YellowPrintf("\tPrimary EC status: %s\n", primaryEcStatus) clicolor.YellowPrintf("\tPrimary CC status: %s\n", primaryBcStatus) fmt.Println() - rp.SetClientStatusFlags(true, true) return true, nil } @@ -163,12 +156,7 @@ func NewClient() *Client { // Return client client := &Client{ - globals: Defaults, - originalMaxFee: Defaults.MaxFee, - originalMaxPrioFee: Defaults.MaxPrioFee, - originalGasLimit: Defaults.GasLimit, - forceFallbacks: false, - ignoreSyncCheck: false, + globals: Defaults, } return client @@ -202,18 +190,8 @@ func (c *Client) WithReady() (*Client, error) { return c, nil } -// Close client remote connection -func (c *Client) Close() { - if c == nil { - return - } - - if c.client == nil { - return - } - - _ = c.client.Close() -} +// Close is a no-op retained for interface compatibility. +func (c *Client) Close() {} func (c *Client) ConfigPath() string { return c.globals.ConfigPath @@ -1275,7 +1253,7 @@ func (c *Client) getAPIURL() string { // path is the URL path, e.g. "/api/node/status". // params are appended as query string parameters for GET or as a form body for POST. // The response body is returned as-is; callers unmarshal it the same way -// they currently unmarshal the output of callAPI. +// The response body is returned as-is; callers unmarshal it. func (c *Client) callHTTPAPI(method, path string, params url.Values) ([]byte, error) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() @@ -1340,156 +1318,6 @@ func (c *Client) callHTTPAPICtx(ctx context.Context, method, path string, params return responseBytes, nil } -// Call the Rocket Pool API -func (c *Client) callAPI(args string, otherArgs ...string) ([]byte, error) { - // Sanitize and parse the args - ignoreSyncCheckFlag, forceFallbackECFlag, args := c.getApiCallArgs(args, otherArgs...) - - // Create the command to run - var cmd string - if c.globals.DaemonPath == "" { - containerName, err := c.getAPIContainerName() - if err != nil { - return []byte{}, err - } - cmd = fmt.Sprintf("docker exec %s %s %s %s %s %s api %s", shellescape.Quote(containerName), shellescape.Quote(APIBinPath), ignoreSyncCheckFlag, forceFallbackECFlag, c.getGasOpts(), c.getCustomNonce(), args) - } else { - cmd = fmt.Sprintf("%s --settings %s %s %s %s %s api %s", - c.globals.DaemonPath, - shellescape.Quote(fmt.Sprintf("%s/%s", c.ConfigPath(), SettingsFile)), - ignoreSyncCheckFlag, - forceFallbackECFlag, - c.getGasOpts(), - c.getCustomNonce(), - args) - } - - // Run the command - return c.runApiCall(cmd) -} - -// Call the Rocket Pool API with some custom environment variables -func (c *Client) callAPIWithEnvVars(envVars map[string]string, args string, otherArgs ...string) ([]byte, error) { - // Sanitize and parse the args - ignoreSyncCheckFlag, forceFallbackECFlag, args := c.getApiCallArgs(args, otherArgs...) - - // Create the command to run - var cmd string - if c.globals.DaemonPath == "" { - envArgs := "" - for key, value := range envVars { - os.Setenv(key, shellescape.Quote(value)) - envArgs += fmt.Sprintf("-e %s ", key) - } - containerName, err := c.getAPIContainerName() - if err != nil { - return []byte{}, err - } - cmd = fmt.Sprintf("docker exec %s %s %s %s %s %s %s api %s", envArgs, shellescape.Quote(containerName), shellescape.Quote(APIBinPath), ignoreSyncCheckFlag, forceFallbackECFlag, c.getGasOpts(), c.getCustomNonce(), args) - } else { - envArgs := "" - for key, value := range envVars { - envArgs += fmt.Sprintf("%s=%s ", key, shellescape.Quote(value)) - } - cmd = fmt.Sprintf("%s %s --settings %s %s %s %s %s api %s", - envArgs, - c.globals.DaemonPath, - shellescape.Quote(fmt.Sprintf("%s/%s", c.ConfigPath(), SettingsFile)), - ignoreSyncCheckFlag, - forceFallbackECFlag, - c.getGasOpts(), - c.getCustomNonce(), - args) - } - - // Run the command - return c.runApiCall(cmd) -} - -func (c *Client) getApiCallArgs(args string, otherArgs ...string) (string, string, string) { - // Sanitize arguments - var sanitizedArgs []string - for arg := range strings.FieldsSeq(args) { - sanitizedArg := shellescape.Quote(arg) - sanitizedArgs = append(sanitizedArgs, sanitizedArg) - } - args = strings.Join(sanitizedArgs, " ") - if len(otherArgs) > 0 { - for _, arg := range otherArgs { - sanitizedArg := shellescape.Quote(arg) - args += fmt.Sprintf(" %s", sanitizedArg) - } - } - - ignoreSyncCheckFlag := "" - if c.ignoreSyncCheck { - ignoreSyncCheckFlag = "--ignore-sync-check" - } - forceFallbacksFlag := "" - if c.forceFallbacks { - forceFallbacksFlag = "--force-fallbacks" - } - - return ignoreSyncCheckFlag, forceFallbacksFlag, args -} - -func (c *Client) runApiCall(cmd string) ([]byte, error) { - if c.globals.DebugPrint { - fmt.Println("To API:") - fmt.Println(cmd) - } - - output, err := c.readOutput(cmd) - - if c.globals.DebugPrint { - if output != nil { - fmt.Println("API Out:") - fmt.Println(string(output)) - } - if err != nil { - fmt.Println("API Err:") - fmt.Println(err.Error()) - } - } - - // Reset the gas settings after the call - c.globals.MaxFee = c.originalMaxFee - c.globals.MaxPrioFee = c.originalMaxPrioFee - c.globals.GasLimit = c.originalGasLimit - - return output, err -} - -// Get the API container name -func (c *Client) getAPIContainerName() (string, error) { - cfg, _, err := c.LoadConfig() - if err != nil { - return "", err - } - if cfg.Smartnode.ProjectName.Value == "" { - return "", errors.New("Rocket Pool docker project name not set") - } - return cfg.Smartnode.ProjectName.Value.(string) + APIContainerSuffix, nil -} - -// Get gas price & limit flags -func (c *Client) getGasOpts() string { - var opts string - opts += fmt.Sprintf("--maxFee %f ", c.globals.MaxFee) - opts += fmt.Sprintf("--maxPrioFee %f ", c.globals.MaxPrioFee) - opts += fmt.Sprintf("--gasLimit %d ", c.globals.GasLimit) - return opts -} - -func (c *Client) getCustomNonce() string { - // Set the custom nonce - nonce := "" - if c.globals.CustomNonce != nil { - nonce = fmt.Sprintf("--nonce %s", c.globals.CustomNonce.String()) - } - return nonce -} - // Run a command and print its output func (c *Client) printOutput(cmdText string) error { diff --git a/shared/services/rocketpool/command.go b/shared/services/rocketpool/command.go index 508d23e4a..1a9a56577 100644 --- a/shared/services/rocketpool/command.go +++ b/shared/services/rocketpool/command.go @@ -3,128 +3,44 @@ package rocketpool import ( "io" "os/exec" - - "golang.org/x/crypto/ssh" ) -// A command to be executed either locally or remotely +// A command to be executed locally type command struct { cmd *exec.Cmd - session *ssh.Session cmdText string } -// Create a command to be run by the Rocket Pool client func (c *Client) newCommand(cmdText string) (*command, error) { - if c.client == nil { - return &command{ - cmd: exec.Command("sh", "-c", cmdText), - cmdText: cmdText, - }, nil - } - - session, err := c.client.NewSession() - if err != nil { - return nil, err - } return &command{ - session: session, + cmd: exec.Command("sh", "-c", cmdText), cmdText: cmdText, }, nil } -// Close the command session -func (c *command) Close() error { - if c.session != nil { - return c.session.Close() - } - return nil -} +func (c *command) Close() error { return nil } -// Run the command -func (c *command) Run() error { - if c.cmd != nil { - return c.cmd.Run() - } +func (c *command) Run() error { return c.cmd.Run() } - return c.session.Run(c.cmdText) -} +func (c *command) Start() error { return c.cmd.Start() } -// Start executes the command. Don't forget to call Wait -func (c *command) Start() error { - if c.cmd != nil { - return c.cmd.Start() - } +func (c *command) Wait() error { return c.cmd.Wait() } - return c.session.Start(c.cmdText) -} +func (c *command) SetStdin(r io.Reader) { c.cmd.Stdin = r } +func (c *command) SetStdout(w io.Writer) { c.cmd.Stdout = w } +func (c *command) SetStderr(w io.Writer) { c.cmd.Stderr = w } -// Wait for the command to exit -func (c *command) Wait() error { - if c.cmd != nil { - return c.cmd.Wait() - } +func (c *command) Output() ([]byte, error) { return c.cmd.Output() } - return c.session.Wait() -} +func (c *command) StdoutPipe() (io.Reader, error) { return c.cmd.StdoutPipe() } -func (c *command) SetStdin(r io.Reader) { - if c.cmd != nil { - c.cmd.Stdin = r - } else { - c.session.Stdin = r - } -} +func (c *command) StderrPipe() (io.Reader, error) { return c.cmd.StderrPipe() } -func (c *command) SetStdout(w io.Writer) { - if c.cmd != nil { - c.cmd.Stdout = w - } else { - c.session.Stdout = w - } -} - -func (c *command) SetStderr(w io.Writer) { - if c.cmd != nil { - c.cmd.Stderr = w - } else { - c.session.Stderr = w - } -} - -// Run the command and return its output -func (c *command) Output() ([]byte, error) { - if c.cmd != nil { - return c.cmd.Output() - } - - return c.session.Output(c.cmdText) -} - -// Get a pipe to the command's stdout -func (c *command) StdoutPipe() (io.Reader, error) { - if c.cmd != nil { - return c.cmd.StdoutPipe() - } - return c.session.StdoutPipe() -} - -// Get a pipe to the command's stderr -func (c *command) StderrPipe() (io.Reader, error) { - if c.cmd != nil { - return c.cmd.StderrPipe() - } - - return c.session.StderrPipe() -} - -// OutputPipes pipes for stdout and stderr func (c *command) OutputPipes() (io.Reader, io.Reader, error) { cmdOut, err := c.StdoutPipe() if err != nil { return nil, nil, err } cmdErr, err := c.StderrPipe() - return cmdOut, cmdErr, err } diff --git a/shared/services/rocketpool/gas.go b/shared/services/rocketpool/gas.go index 789c03c33..96dad910e 100644 --- a/shared/services/rocketpool/gas.go +++ b/shared/services/rocketpool/gas.go @@ -17,7 +17,7 @@ func (rp *Client) PrintMultiTxWarning() { // Get the gas price from the latest block func (c *Client) GetGasPriceFromLatestBlock() (api.GasPriceFromLatestBlockResponse, error) { - responseBytes, err := c.callAPI("service get-gas-price-from-latest-block") + responseBytes, err := c.callHTTPAPI("GET", "/api/service/get-gas-price-from-latest-block", nil) if err != nil { return api.GasPriceFromLatestBlockResponse{}, fmt.Errorf("Could not get gas price from latest block: %w", err) } diff --git a/shared/services/rocketpool/upgrades.go b/shared/services/rocketpool/upgrades.go index c2bdfe3b4..3c8491f34 100644 --- a/shared/services/rocketpool/upgrades.go +++ b/shared/services/rocketpool/upgrades.go @@ -2,6 +2,7 @@ package rocketpool import ( "fmt" + "net/url" "strconv" "github.com/goccy/go-json" @@ -10,7 +11,7 @@ import ( // Get upgrade proposals func (c *Client) TNDAOUpgradeProposals() (api.TNDAOGetUpgradeProposalsResponse, error) { - responseBytes, err := c.callAPI("upgrade get-upgrade-proposals") + responseBytes, err := c.callHTTPAPI("GET", "/api/upgrade/get-upgrade-proposals", nil) if err != nil { return api.TNDAOGetUpgradeProposalsResponse{}, fmt.Errorf("Could not get upgrade proposals: %w", err) } @@ -26,7 +27,7 @@ func (c *Client) TNDAOUpgradeProposals() (api.TNDAOGetUpgradeProposalsResponse, // Check whether the node can execute a proposal func (c *Client) CanExecuteUpgradeProposal(proposalId uint64) (api.CanExecuteUpgradeProposalResponse, error) { - responseBytes, err := c.callAPI("upgrade can-execute-upgrade", strconv.FormatUint(proposalId, 10)) + responseBytes, err := c.callHTTPAPI("GET", "/api/upgrade/can-execute-upgrade", url.Values{"id": {strconv.FormatUint(proposalId, 10)}}) if err != nil { return api.CanExecuteUpgradeProposalResponse{}, fmt.Errorf("Could not check whether the node can execute upgrade proposal: %w", err) } @@ -42,7 +43,7 @@ func (c *Client) CanExecuteUpgradeProposal(proposalId uint64) (api.CanExecuteUpg // Execute a proposal func (c *Client) ExecuteUpgradeProposal(proposalId uint64) (api.ExecuteUpgradeProposalResponse, error) { - responseBytes, err := c.callAPI("upgrade execute-upgrade", strconv.FormatUint(proposalId, 10)) + responseBytes, err := c.callHTTPAPI("POST", "/api/upgrade/execute-upgrade", url.Values{"id": {strconv.FormatUint(proposalId, 10)}}) if err != nil { return api.ExecuteUpgradeProposalResponse{}, fmt.Errorf("Could not execute upgrade proposal: %w", err) } From fe0d0e50f34010762b236f096808c6db8097f45f Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Wed, 25 Mar 2026 20:42:29 -0300 Subject: [PATCH 12/24] Fix lint --- shared/services/rocketpool/client.go | 1 - shared/services/rocketpool/odao.go | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index dd30731ae..85999cd23 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -23,7 +23,6 @@ import ( "github.com/fatih/color" "github.com/goccy/go-json" - "github.com/alessio/shellescape" "github.com/blang/semver/v4" "github.com/mitchellh/go-homedir" diff --git a/shared/services/rocketpool/odao.go b/shared/services/rocketpool/odao.go index b600d02ec..725a9690c 100644 --- a/shared/services/rocketpool/odao.go +++ b/shared/services/rocketpool/odao.go @@ -157,7 +157,7 @@ func (c *Client) ProposeLeaveTNDAO() (api.ProposeTNDAOLeaveResponse, error) { // Check whether the node can propose kicking a member func (c *Client) CanProposeKickFromTNDAO(memberAddress common.Address, fineAmountWei *big.Int) (api.CanProposeTNDAOKickResponse, error) { responseBytes, err := c.callHTTPAPI("GET", "/api/odao/can-propose-kick", url.Values{ - "address": {memberAddress.Hex()}, + "address": {memberAddress.Hex()}, "fineAmountWei": {fineAmountWei.String()}, }) if err != nil { @@ -176,7 +176,7 @@ func (c *Client) CanProposeKickFromTNDAO(memberAddress common.Address, fineAmoun // Propose kicking a member func (c *Client) ProposeKickFromTNDAO(memberAddress common.Address, fineAmountWei *big.Int) (api.ProposeTNDAOKickResponse, error) { responseBytes, err := c.callHTTPAPI("POST", "/api/odao/propose-kick", url.Values{ - "address": {memberAddress.Hex()}, + "address": {memberAddress.Hex()}, "fineAmountWei": {fineAmountWei.String()}, }) if err != nil { From 7063afd53fac3b4234ad6cb5a6d9e4683e8d74e8 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Thu, 26 Mar 2026 20:08:54 -0300 Subject: [PATCH 13/24] Add blank line at the end of responses --- rocketpool/node/http.go | 8 +++----- shared/utils/api/http.go | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/rocketpool/node/http.go b/rocketpool/node/http.go index c3dbd1558..7924aee38 100644 --- a/rocketpool/node/http.go +++ b/rocketpool/node/http.go @@ -27,18 +27,16 @@ func startHTTP(ctx context.Context, c *cli.Command, cfg *config.RocketPoolConfig return } - // In Docker mode the server must bind to 0.0.0.0 so the port mapping in - // node.tmpl makes it accessible from the host. In native mode we respect - // the OpenAPIPort setting: Closed → 127.0.0.1, OpenLocalhost → 0.0.0.0. var host string if !cfg.IsNativeMode { + // In Docker mode the server must bind to 0.0.0.0, so other containers can reach it. host = "0.0.0.0" } else { portMode, _ := cfg.Smartnode.OpenAPIPort.Value.(cfgtypes.RPCMode) if portMode == cfgtypes.RPC_OpenLocalhost { - host = "0.0.0.0" - } else { host = "127.0.0.1" + } else { + host = "0.0.0.0" } } diff --git a/shared/utils/api/http.go b/shared/utils/api/http.go index 8fa1a8e9b..bd17926c9 100644 --- a/shared/utils/api/http.go +++ b/shared/utils/api/http.go @@ -50,7 +50,7 @@ func WriteResponse(w http.ResponseWriter, response interface{}, responseError er w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - _, _ = w.Write(responseBytes) + _, _ = w.Write(append(responseBytes, '\n')) } // WriteErrorResponse writes a generic error response to w. From 3663d135d965d8e3948960836a684d6094c42da2 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Thu, 26 Mar 2026 21:19:30 -0300 Subject: [PATCH 14/24] Remove OpenAPIPort options. will always be opened just to localhost --- rocketpool/node/http.go | 8 +- rocketpool/node/metrics-exporter.go | 21 +++-- rocketpool/node/node.go | 92 +++++++++++++++----- shared/services/config/rocket-pool-config.go | 8 -- shared/services/config/smartnode-config.go | 16 ---- 5 files changed, 88 insertions(+), 57 deletions(-) diff --git a/rocketpool/node/http.go b/rocketpool/node/http.go index 7924aee38..2ae0d3df8 100644 --- a/rocketpool/node/http.go +++ b/rocketpool/node/http.go @@ -10,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/rocketpool/node/routes" "github.com/rocket-pool/smartnode/shared/services/config" - cfgtypes "github.com/rocket-pool/smartnode/shared/types/config" ) type httpServer struct { @@ -32,12 +31,7 @@ func startHTTP(ctx context.Context, c *cli.Command, cfg *config.RocketPoolConfig // In Docker mode the server must bind to 0.0.0.0, so other containers can reach it. host = "0.0.0.0" } else { - portMode, _ := cfg.Smartnode.OpenAPIPort.Value.(cfgtypes.RPCMode) - if portMode == cfgtypes.RPC_OpenLocalhost { - host = "127.0.0.1" - } else { - host = "0.0.0.0" - } + host = "127.0.0.1" } mux := http.NewServeMux() diff --git a/rocketpool/node/metrics-exporter.go b/rocketpool/node/metrics-exporter.go index ae53576a1..f9fb13f30 100644 --- a/rocketpool/node/metrics-exporter.go +++ b/rocketpool/node/metrics-exporter.go @@ -1,6 +1,7 @@ package node import ( + "context" "fmt" "net/http" "os" @@ -16,7 +17,7 @@ import ( "github.com/urfave/cli/v3" ) -func runMetricsServer(c *cli.Command, logger log.ColorLogger, stateLocker *collectors.StateLocker) error { +func runMetricsServer(ctx context.Context, c *cli.Command, logger log.ColorLogger, stateLocker *collectors.StateLocker) error { // Get services cfg, err := services.GetConfig(c) @@ -105,8 +106,9 @@ func runMetricsServer(c *cli.Command, logger log.ColorLogger, stateLocker *colle } logger.Printlnf("Starting metrics exporter on %s:%d.", metricsAddress, metricsPort) metricsPath := "/metrics" - http.Handle(metricsPath, handler) - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + mux := http.NewServeMux() + mux.Handle(metricsPath, handler) + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(` Rocket Pool Metrics Exporter @@ -116,8 +118,17 @@ func runMetricsServer(c *cli.Command, logger log.ColorLogger, stateLocker *colle `, )) }) - err = http.ListenAndServe(fmt.Sprintf("%s:%d", metricsAddress, metricsPort), nil) - if err != nil { + srv := &http.Server{ + Addr: fmt.Sprintf("%s:%d", metricsAddress, metricsPort), + Handler: mux, + } + + go func() { + <-ctx.Done() + _ = srv.Shutdown(context.Background()) + }() + + if err = srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { return fmt.Errorf("Error running HTTP server: %w", err) } diff --git a/rocketpool/node/node.go b/rocketpool/node/node.go index 7e758704b..3670d6163 100644 --- a/rocketpool/node/node.go +++ b/rocketpool/node/node.go @@ -217,16 +217,26 @@ func run(c *cli.Command) error { // Run task loop go func() { + defer wg.Done() // we assume clients are synced on startup so that we don't send unnecessary alerts wasExecutionClientSynced := true wasBeaconClientSynced := true for { + // Exit if the process received SIGINT/SIGTERM + select { + case <-ctx.Done(): + return + default: + } + // Check the EC status err := services.WaitEthClientSynced(c, false) // Force refresh the primary / fallback EC status if err != nil { wasExecutionClientSynced = false errorLog.Printlnf("Execution client not synced: %s. Waiting for sync...", err.Error()) - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } continue } @@ -242,7 +252,9 @@ func run(c *cli.Command) error { // NOTE: if not synced, it returns an error - so there isn't necessarily an underlying issue wasBeaconClientSynced = false errorLog.Printlnf("Beacon client not synced: %s. Waiting for sync...", err.Error()) - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } continue } @@ -256,7 +268,9 @@ func run(c *cli.Command) error { newProtocolVersion, err := utils.GetCurrentVersion(rp, nil) if err != nil { errorLog.Println(err) - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } continue } if newProtocolVersion.Compare(protocolVersion) != 0 { @@ -269,7 +283,9 @@ func run(c *cli.Command) error { state, err := updateNetworkState(m, &updateLog, nodeAccount.Address) if err != nil { errorLog.Println(err) - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } continue } stateLocker.UpdateState(state) @@ -278,7 +294,9 @@ func run(c *cli.Command) error { if err := manageFeeRecipient.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the defend challenge exit task if err := defendChallengeExit.run(state); err != nil { @@ -289,20 +307,26 @@ func run(c *cli.Command) error { if err := downloadRewardsTrees.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the pDAO proposal defender if err := defendPdaoProps.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the pDAO proposal verifier if verifyPdaoProps != nil { if err := verifyPdaoProps.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } } // Run the megapool prestake check @@ -310,63 +334,79 @@ func run(c *cli.Command) error { if err := prestakeMegapoolValidator.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } } // Run the megapool stake check if err := stakeMegapoolValidators.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the megapool notify validator exit check if err := notifyValidatorExit.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the megapool notify final balance check if err := notifyFinalBalance.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the megapool provision express ticket check if err := provisionExpressTickets.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the balance distribution check if err := distributeMinipools.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the set use latest delegate check if err := setUseLatestDelegate.run(state); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } // Run the port connectivity check if err := checkPorts.Run(); err != nil { errorLog.Println(err) } - time.Sleep(taskCooldown) + if !sleepWithContext(ctx, taskCooldown) { + return + } - time.Sleep(tasksInterval) + if !sleepWithContext(ctx, tasksInterval) { + return + } } - wg.Done() }() // Run metrics loop go func() { - err := runMetricsServer(c, log.NewColorLogger(MetricsColor), stateLocker) - if err != nil { + defer wg.Done() + if err := runMetricsServer(ctx, c, log.NewColorLogger(MetricsColor), stateLocker); err != nil { errorLog.Println(err) } - wg.Done() }() // Wait for both threads to stop @@ -374,6 +414,16 @@ func run(c *cli.Command) error { return nil } +// sleepWithContext sleeps for d or until ctx is cancelled, returning false if cancelled. +func sleepWithContext(ctx context.Context, d time.Duration) bool { + select { + case <-ctx.Done(): + return false + case <-time.After(d): + return true + } +} + // Configure HTTP transport settings func configureHTTP() { // The daemon makes a large number of concurrent RPC requests to the Eth1 client diff --git a/shared/services/config/rocket-pool-config.go b/shared/services/config/rocket-pool-config.go index cd6ef5a28..fa098cb39 100644 --- a/shared/services/config/rocket-pool-config.go +++ b/shared/services/config/rocket-pool-config.go @@ -1254,15 +1254,7 @@ func (cfg *RocketPoolConfig) GetECStopSignal() (string, error) { return "", fmt.Errorf("Unknown Execution Client %s", string(cfg.ExecutionClient.Value.(config.ExecutionClient))) } -// Gets the port mapping string for the node API webserver. -// In Docker mode this always returns "127.0.0.1:PORT:PORT/tcp" so the CLI on -// the host can reach the server. In native mode Docker is not involved so an -// empty string is returned. -// Used by text/template to format node.tmpl. func (cfg *RocketPoolConfig) GetNodeOpenPorts() string { - if cfg.IsNativeMode { - return "" - } port := cfg.Smartnode.APIPort.Value.(uint16) return fmt.Sprintf("\"127.0.0.1:%d:%d/tcp\"", port, port) } diff --git a/shared/services/config/smartnode-config.go b/shared/services/config/smartnode-config.go index 5d8c17cc3..f4d92a2d5 100644 --- a/shared/services/config/smartnode-config.go +++ b/shared/services/config/smartnode-config.go @@ -117,9 +117,6 @@ type SmartnodeConfig struct { // Port for the node's HTTP API webserver APIPort config.Parameter `yaml:"apiPort,omitempty"` - // Whether to expose the node's API port to the local network - OpenAPIPort config.Parameter `yaml:"openAPIPort,omitempty"` - /////////////////////////// // Non-editable settings // /////////////////////////// @@ -430,18 +427,6 @@ func NewSmartnodeConfig(cfg *RocketPoolConfig) *SmartnodeConfig { OverwriteOnUpgrade: false, }, - OpenAPIPort: config.Parameter{ - ID: "openAPIPort", - Name: "Expose API Port", - Description: "Expose the API port to other processes on your machine. For security reasons, this port can only be exposed to localhost. It is recommended to keep this setting on Closed unless you have a specific reason to expose it.", - Type: config.ParameterType_Choice, - Default: map[config.Network]interface{}{config.Network_All: config.RPC_Closed}, - AffectsContainers: []config.ContainerID{config.ContainerID_Node}, - CanBeBlank: false, - OverwriteOnUpgrade: false, - Options: config.RestrictedPortModes(), - }, - txWatchUrl: map[config.Network]string{ config.Network_Mainnet: "https://etherscan.io/tx", config.Network_Devnet: "https://hoodi.etherscan.io/tx", @@ -672,7 +657,6 @@ func (cfg *SmartnodeConfig) GetParameters() []*config.Parameter { &cfg.WatchtowerMaxFeeOverride, &cfg.WatchtowerPrioFeeOverride, &cfg.APIPort, - &cfg.OpenAPIPort, } } From f3bb482fab8c43fc9cac6f4e7a35c9eb2d420adc Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Sun, 29 Mar 2026 12:27:15 -0300 Subject: [PATCH 15/24] Fix flag types --- rocketpool-cli/megapool/commands.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rocketpool-cli/megapool/commands.go b/rocketpool-cli/megapool/commands.go index 4ec3fcac1..9e3a1bbbd 100644 --- a/rocketpool-cli/megapool/commands.go +++ b/rocketpool-cli/megapool/commands.go @@ -236,7 +236,7 @@ func RegisterCommands(app *cli.Command, name string, aliases []string) { Name: "yes", Usage: "Automatically confirm the action", }, - &cli.StringFlag{ + &cli.Uint64Flag{ Name: "validator-id", Usage: "The validator id to exit", }, @@ -277,7 +277,7 @@ func RegisterCommands(app *cli.Command, name string, aliases []string) { Name: "yes", Usage: "Automatically confirm the action", }, - &cli.StringFlag{ + &cli.Uint64Flag{ Name: "validator-id", Usage: "The validator id to exit", }, @@ -318,7 +318,7 @@ func RegisterCommands(app *cli.Command, name string, aliases []string) { Name: "yes", Usage: "Automatically confirm the action", }, - &cli.StringFlag{ + &cli.Uint64Flag{ Name: "validator-id", Usage: "The validator id for which the exit is being notified", }, @@ -359,7 +359,7 @@ func RegisterCommands(app *cli.Command, name string, aliases []string) { Name: "yes", Usage: "Automatically confirm the action", }, - &cli.StringFlag{ + &cli.Uint64Flag{ Name: "validator-id", Usage: "The validator id for which the final balance is being notified", }, From 8c9b771ab6b8b420edfbc83985ab73adc0619f88 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Sun, 29 Mar 2026 14:00:54 -0300 Subject: [PATCH 16/24] Fix set-use-latest --- rocketpool-cli/megapool/commands.go | 50 +++++++++++++------------- rocketpool-cli/megapool/delegate.go | 2 +- rocketpool/api/megapool/delegate.go | 10 +++--- rocketpool/api/megapool/routes.go | 4 +-- shared/services/rocketpool/megapool.go | 5 +-- shared/services/rocketpool/minipool.go | 6 ++-- 6 files changed, 41 insertions(+), 36 deletions(-) diff --git a/rocketpool-cli/megapool/commands.go b/rocketpool-cli/megapool/commands.go index 9e3a1bbbd..f458762c1 100644 --- a/rocketpool-cli/megapool/commands.go +++ b/rocketpool-cli/megapool/commands.go @@ -409,34 +409,36 @@ func RegisterCommands(app *cli.Command, name string, aliases []string) { return distribute(c.Bool("yes")) }, }, - // Add set-use-latest-delegate command - { - Name: "set-use-latest-delegate", - Aliases: []string{"l"}, - Usage: "Set the megapool to always use the latest delegate", - UsageText: "rocketpool megapool set-use-latest-delegate use-latest-delegate", - - Action: func(ctx context.Context, c *cli.Command) error { - - // Validate args - if err := cliutils.ValidateArgCount(c, 1); err != nil { - return err - } + // Add set-use-latest-delegate command + { + Name: "set-use-latest-delegate", + Aliases: []string{"l"}, + Usage: "Set the megapool to always use the latest delegate", + UsageText: "rocketpool megapool set-use-latest-delegate [true|false]", + Arguments: []cli.Argument{ + &cli.StringArgs{ + Name: "use-latest-delegate", + Min: 1, + Max: 1, + }, + }, + Action: func(ctx context.Context, c *cli.Command) error { - useLatest, err := cliutils.ValidateBool("use-latest-delegate", c.Args().Get(0)) - if err != nil { - return err - } + vals := c.StringArgs("use-latest-delegate") + useLatest, err := cliutils.ValidateBool("use-latest-delegate", vals[0]) + if err != nil { + return err + } - return setUseLatestDelegateMegapool(useLatest, c.Bool("yes")) - }, - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "yes", - Usage: "Automatically confirm the action", - }, + return setUseLatestDelegateMegapool(useLatest, c.Bool("yes")) + }, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "yes", + Usage: "Automatically confirm the action", }, }, }, + }, }) } diff --git a/rocketpool-cli/megapool/delegate.go b/rocketpool-cli/megapool/delegate.go index ae86a7ee4..78dc9d873 100644 --- a/rocketpool-cli/megapool/delegate.go +++ b/rocketpool-cli/megapool/delegate.go @@ -43,7 +43,7 @@ func setUseLatestDelegateMegapool(setting bool, yes bool) error { if err != nil { return fmt.Errorf("error checking if megapool %s could have its use-latest-delegate flag changed: %w", megapoolAddress.Hex(), err) } - if canResponse.MatchesCurrentSetting == true { + if canResponse.MatchesCurrentSetting { if setting == true { fmt.Printf("Could not enable use-latest-delegate on the node's megapool, the setting is already enabled.") } else { diff --git a/rocketpool/api/megapool/delegate.go b/rocketpool/api/megapool/delegate.go index 756dd3e54..dfc8f4030 100644 --- a/rocketpool/api/megapool/delegate.go +++ b/rocketpool/api/megapool/delegate.go @@ -128,7 +128,7 @@ func getUseLatestDelegate(c *cli.Command, megapoolAddress common.Address) (*api. } -func canSetUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, setting bool) (*api.MegapoolCanSetUseLatestDelegateResponse, error) { +func canSetUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, useLatest bool) (*api.MegapoolCanSetUseLatestDelegateResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err @@ -156,7 +156,7 @@ func canSetUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, set if err != nil { return nil, err } - if currentSetting == setting { + if currentSetting == useLatest { response.MatchesCurrentSetting = true return &response, nil } @@ -168,7 +168,7 @@ func canSetUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, set return nil, err } - gasInfo, err := mega.EstimateSetUseLatestDelegateGas(setting, opts) + gasInfo, err := mega.EstimateSetUseLatestDelegateGas(useLatest, opts) if err == nil { response.GasInfo = gasInfo } @@ -178,7 +178,7 @@ func canSetUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, set } -func setUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, setting bool) (*api.MegapoolSetUseLatestDelegateResponse, error) { +func setUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, useLatest bool) (*api.MegapoolSetUseLatestDelegateResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err @@ -214,7 +214,7 @@ func setUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, settin } // Set the new setting - hash, err := mega.SetUseLatestDelegate(setting, opts) + hash, err := mega.SetUseLatestDelegate(useLatest, opts) if err != nil { return nil, err } diff --git a/rocketpool/api/megapool/routes.go b/rocketpool/api/megapool/routes.go index 55eb8834c..e687eed75 100644 --- a/rocketpool/api/megapool/routes.go +++ b/rocketpool/api/megapool/routes.go @@ -275,8 +275,8 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/megapool/can-set-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { address := common.HexToAddress(r.URL.Query().Get("address")) - setting := r.URL.Query().Get("setting") == "true" - resp, err := canSetUseLatestDelegate(c, address, setting) + setLatest := r.URL.Query().Get("setLatest") == "true" + resp, err := canSetUseLatestDelegate(c, address, setLatest) apiutils.WriteResponse(w, resp, err) }) diff --git a/shared/services/rocketpool/megapool.go b/shared/services/rocketpool/megapool.go index 7c6228103..1fafe52cd 100644 --- a/shared/services/rocketpool/megapool.go +++ b/shared/services/rocketpool/megapool.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" "net/url" + "strconv" "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" @@ -421,8 +422,8 @@ func (c *Client) GetUseLatestDelegate(address common.Address) (api.MegapoolGetUs } // Check whether a megapool can have its use-latest-delegate setting changed -func (c *Client) CanSetUseLatestDelegateMegapool(address common.Address, setting bool) (api.MegapoolCanSetUseLatestDelegateResponse, error) { - responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-set-use-latest-delegate", url.Values{"address": {address.Hex()}}) +func (c *Client) CanSetUseLatestDelegateMegapool(address common.Address, useLatest bool) (api.MegapoolCanSetUseLatestDelegateResponse, error) { + responseBytes, err := c.callHTTPAPI("GET", "/api/megapool/can-set-use-latest-delegate", url.Values{"address": {address.Hex()}, "setLatest": {strconv.FormatBool(useLatest)}}) if err != nil { return api.MegapoolCanSetUseLatestDelegateResponse{}, fmt.Errorf("Could not get can set use latest delegate for megapool status: %w", err) } diff --git a/shared/services/rocketpool/minipool.go b/shared/services/rocketpool/minipool.go index 300e39355..ac4329fd2 100644 --- a/shared/services/rocketpool/minipool.go +++ b/shared/services/rocketpool/minipool.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" "net/url" + "strconv" "github.com/ethereum/go-ethereum/common" "github.com/goccy/go-json" @@ -250,8 +251,9 @@ func (c *Client) DelegateUpgradeMinipool(address common.Address) (api.DelegateUp } // Check whether a minipool can have its auto-upgrade setting changed -func (c *Client) CanSetUseLatestDelegateMinipool(address common.Address) (api.CanSetUseLatestDelegateResponse, error) { - responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-set-use-latest-delegate", url.Values{"address": {address.Hex()}}) +func (c *Client) CanSetUseLatestDelegateMinipool(address common.Address, setLatest bool) (api.CanSetUseLatestDelegateResponse, error) { + // pass setLatest as well + responseBytes, err := c.callHTTPAPI("GET", "/api/minipool/can-set-use-latest-delegate", url.Values{"address": {address.Hex()}, "setLatest": {strconv.FormatBool(setLatest)}}) if err != nil { return api.CanSetUseLatestDelegateResponse{}, fmt.Errorf("Could not get can set use latest delegate for minipool status: %w", err) } From d8ddebd7e63cf730af89af5da1511a2938b1814d Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Mon, 30 Mar 2026 00:09:46 -0300 Subject: [PATCH 17/24] Pass gas settings to the api --- bindings/utils/eth/units.go | 3 + rocketpool-cli/megapool/commands.go | 50 ++-- rocketpool/api/auction/bid-lot.go | 12 +- rocketpool/api/auction/claim-lot.go | 13 +- rocketpool/api/auction/create-lot.go | 13 +- rocketpool/api/auction/recover-lot.go | 13 +- rocketpool/api/auction/routes.go | 29 ++- rocketpool/api/megapool/claim-refunds.go | 9 +- rocketpool/api/megapool/delegate.go | 25 +- rocketpool/api/megapool/dissolve-validator.go | 9 +- .../api/megapool/dissolve-with-proof.go | 9 +- rocketpool/api/megapool/distribute.go | 9 +- rocketpool/api/megapool/exit-queue.go | 9 +- .../api/megapool/notify-final-balance.go | 9 +- .../api/megapool/notify-validator-exit.go | 9 +- rocketpool/api/megapool/reduce-bond.go | 9 +- rocketpool/api/megapool/repay-debt.go | 9 +- rocketpool/api/megapool/routes.go | 85 ++++++- rocketpool/api/megapool/stake.go | 9 +- rocketpool/api/minipool/close.go | 12 +- rocketpool/api/minipool/delegate.go | 25 +- rocketpool/api/minipool/dissolve.go | 13 +- rocketpool/api/minipool/distribute.go | 13 +- rocketpool/api/minipool/promote.go | 13 +- rocketpool/api/minipool/refund.go | 13 +- rocketpool/api/minipool/rescue-dissolved.go | 7 +- rocketpool/api/minipool/routes.go | 64 ++++- rocketpool/api/minipool/stake.go | 9 +- rocketpool/api/node/burn.go | 14 +- rocketpool/api/node/claim-rewards.go | 17 +- rocketpool/api/node/claim-rpl.go | 14 +- .../api/node/claim-unclaimed-rewards.go | 13 +- rocketpool/api/node/create-vacant-minipool.go | 10 +- rocketpool/api/node/deposit.go | 9 +- rocketpool/api/node/distributor.go | 21 +- rocketpool/api/node/express-ticket.go | 10 +- .../api/node/primary-withdrawal-address.go | 17 +- rocketpool/api/node/register.go | 14 +- rocketpool/api/node/routes.go | 239 +++++++++++++++--- rocketpool/api/node/rpl-withdrawal-address.go | 17 +- rocketpool/api/node/send-message.go | 9 +- rocketpool/api/node/send.go | 17 +- rocketpool/api/node/set-rpl-lock-allowed.go | 8 +- .../api/node/set-stake-rpl-for-allowed.go | 11 +- rocketpool/api/node/set-timezone.go | 14 +- rocketpool/api/node/smoothing-pool.go | 10 +- rocketpool/api/node/stake-rpl.go | 25 +- rocketpool/api/node/swap-rpl.go | 25 +- rocketpool/api/node/unstake-rpl.go | 13 +- rocketpool/api/node/withdraw-credit.go | 14 +- rocketpool/api/node/withdraw-eth.go | 10 +- rocketpool/api/node/withdraw-legacy-rpl.go | 13 +- rocketpool/api/node/withdraw-rpl.go | 21 +- rocketpool/api/odao/cancel-proposal.go | 14 +- rocketpool/api/odao/execute-proposal.go | 20 +- rocketpool/api/odao/join.go | 21 +- rocketpool/api/odao/leave.go | 13 +- rocketpool/api/odao/penalise-megapool.go | 14 +- rocketpool/api/odao/propose-invite.go | 13 +- rocketpool/api/odao/propose-kick.go | 13 +- rocketpool/api/odao/propose-leave.go | 10 +- rocketpool/api/odao/propose-settings.go | 171 ++----------- rocketpool/api/odao/routes.go | 162 ++++++++++-- rocketpool/api/odao/vote-proposal.go | 14 +- rocketpool/api/pdao/claim-bonds.go | 14 +- rocketpool/api/pdao/defeat-proposal.go | 14 +- rocketpool/api/pdao/execute-proposal.go | 14 +- rocketpool/api/pdao/finalize-proposal.go | 14 +- rocketpool/api/pdao/invite-security.go | 12 +- rocketpool/api/pdao/kick-multi-security.go | 12 +- rocketpool/api/pdao/kick-security.go | 12 +- rocketpool/api/pdao/one-time-spend.go | 12 +- rocketpool/api/pdao/override-vote.go | 13 +- rocketpool/api/pdao/percentages.go | 13 +- rocketpool/api/pdao/propose-settings.go | 13 +- rocketpool/api/pdao/recurring-spend.go | 12 +- rocketpool/api/pdao/replace-security.go | 12 +- rocketpool/api/pdao/routes.go | 134 ++++++++-- rocketpool/api/pdao/set-allow-list.go | 12 +- rocketpool/api/pdao/set-snapshot-address.go | 24 +- rocketpool/api/pdao/update-recurring-spend.go | 12 +- rocketpool/api/pdao/vote-proposal.go | 9 +- rocketpool/api/pdao/voting.go | 14 +- rocketpool/api/queue/assign-deposits.go | 13 +- rocketpool/api/queue/process.go | 13 +- rocketpool/api/queue/routes.go | 15 +- rocketpool/api/security/cancel-proposal.go | 14 +- rocketpool/api/security/execute-proposal.go | 14 +- rocketpool/api/security/join.go | 12 +- rocketpool/api/security/leave.go | 14 +- rocketpool/api/security/propose-leave.go | 14 +- rocketpool/api/security/propose-settings.go | 13 +- rocketpool/api/security/routes.go | 50 +++- rocketpool/api/security/vote-proposal.go | 14 +- rocketpool/api/upgrade/execute-upgrade.go | 14 +- rocketpool/api/upgrade/routes.go | 8 +- rocketpool/api/wallet/ens-name.go | 9 +- rocketpool/api/wallet/routes.go | 15 +- shared/services/gas/gas.go | 8 +- shared/services/rocketpool/client.go | 14 + shared/services/services.go | 36 +++ 101 files changed, 1012 insertions(+), 1202 deletions(-) diff --git a/bindings/utils/eth/units.go b/bindings/utils/eth/units.go index 9d5407eb7..4b5ec450f 100644 --- a/bindings/utils/eth/units.go +++ b/bindings/utils/eth/units.go @@ -39,6 +39,9 @@ func EthToWei(eth float64) *big.Int { // Convert wei to gigawei func WeiToGwei(wei *big.Int) float64 { + if wei == nil { + return 0 + } var weiFloat big.Float var gwei big.Float weiFloat.SetInt(wei) diff --git a/rocketpool-cli/megapool/commands.go b/rocketpool-cli/megapool/commands.go index f458762c1..a0230890f 100644 --- a/rocketpool-cli/megapool/commands.go +++ b/rocketpool-cli/megapool/commands.go @@ -409,36 +409,36 @@ func RegisterCommands(app *cli.Command, name string, aliases []string) { return distribute(c.Bool("yes")) }, }, - // Add set-use-latest-delegate command - { - Name: "set-use-latest-delegate", - Aliases: []string{"l"}, - Usage: "Set the megapool to always use the latest delegate", - UsageText: "rocketpool megapool set-use-latest-delegate [true|false]", - Arguments: []cli.Argument{ - &cli.StringArgs{ - Name: "use-latest-delegate", - Min: 1, - Max: 1, + // Add set-use-latest-delegate command + { + Name: "set-use-latest-delegate", + Aliases: []string{"l"}, + Usage: "Set the megapool to always use the latest delegate", + UsageText: "rocketpool megapool set-use-latest-delegate [true|false]", + Arguments: []cli.Argument{ + &cli.StringArgs{ + Name: "use-latest-delegate", + Min: 1, + Max: 1, + }, }, - }, - Action: func(ctx context.Context, c *cli.Command) error { + Action: func(ctx context.Context, c *cli.Command) error { - vals := c.StringArgs("use-latest-delegate") - useLatest, err := cliutils.ValidateBool("use-latest-delegate", vals[0]) - if err != nil { - return err - } + vals := c.StringArgs("use-latest-delegate") + useLatest, err := cliutils.ValidateBool("use-latest-delegate", vals[0]) + if err != nil { + return err + } - return setUseLatestDelegateMegapool(useLatest, c.Bool("yes")) - }, - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "yes", - Usage: "Automatically confirm the action", + return setUseLatestDelegateMegapool(useLatest, c.Bool("yes")) + }, + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "yes", + Usage: "Automatically confirm the action", + }, }, }, }, - }, }) } diff --git a/rocketpool/api/auction/bid-lot.go b/rocketpool/api/auction/bid-lot.go index 3aa9485d6..59906fd49 100644 --- a/rocketpool/api/auction/bid-lot.go +++ b/rocketpool/api/auction/bid-lot.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/auction" "github.com/rocket-pool/smartnode/bindings/settings/protocol" "github.com/urfave/cli/v3" @@ -99,7 +100,7 @@ func canBidOnLot(c *cli.Command, lotIndex uint64, amountWei *big.Int) (*api.CanB } -func bidOnLot(c *cli.Command, lotIndex uint64, amountWei *big.Int) (*api.BidOnLotResponse, error) { +func bidOnLot(c *cli.Command, lotIndex uint64, amountWei *big.Int, opts *bind.TransactOpts) (*api.BidOnLotResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -108,10 +109,6 @@ func bidOnLot(c *cli.Command, lotIndex uint64, amountWei *big.Int) (*api.BidOnLo if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -120,11 +117,6 @@ func bidOnLot(c *cli.Command, lotIndex uint64, amountWei *big.Int) (*api.BidOnLo // Response response := api.BidOnLotResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } opts.Value = amountWei // Override the provided pending TX if requested diff --git a/rocketpool/api/auction/claim-lot.go b/rocketpool/api/auction/claim-lot.go index fa17fbe20..4c8c44372 100644 --- a/rocketpool/api/auction/claim-lot.go +++ b/rocketpool/api/auction/claim-lot.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/auction" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -92,7 +93,7 @@ func canClaimFromLot(c *cli.Command, lotIndex uint64) (*api.CanClaimFromLotRespo } -func claimFromLot(c *cli.Command, lotIndex uint64) (*api.ClaimFromLotResponse, error) { +func claimFromLot(c *cli.Command, lotIndex uint64, opts *bind.TransactOpts) (*api.ClaimFromLotResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -101,10 +102,6 @@ func claimFromLot(c *cli.Command, lotIndex uint64) (*api.ClaimFromLotResponse, e if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -113,12 +110,6 @@ func claimFromLot(c *cli.Command, lotIndex uint64) (*api.ClaimFromLotResponse, e // Response response := api.ClaimFromLotResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/auction/create-lot.go b/rocketpool/api/auction/create-lot.go index 9752f1d9a..f1a8eaea2 100644 --- a/rocketpool/api/auction/create-lot.go +++ b/rocketpool/api/auction/create-lot.go @@ -3,6 +3,7 @@ package auction import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/auction" "github.com/rocket-pool/smartnode/bindings/settings/protocol" "github.com/urfave/cli/v3" @@ -79,7 +80,7 @@ func canCreateLot(c *cli.Command) (*api.CanCreateLotResponse, error) { } -func createLot(c *cli.Command) (*api.CreateLotResponse, error) { +func createLot(c *cli.Command, opts *bind.TransactOpts) (*api.CreateLotResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -88,10 +89,6 @@ func createLot(c *cli.Command) (*api.CreateLotResponse, error) { if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -100,12 +97,6 @@ func createLot(c *cli.Command) (*api.CreateLotResponse, error) { // Response response := api.CreateLotResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/auction/recover-lot.go b/rocketpool/api/auction/recover-lot.go index 6fe548ac4..0299de07c 100644 --- a/rocketpool/api/auction/recover-lot.go +++ b/rocketpool/api/auction/recover-lot.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/auction" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -97,7 +98,7 @@ func canRecoverRplFromLot(c *cli.Command, lotIndex uint64) (*api.CanRecoverRPLFr } -func recoverRplFromLot(c *cli.Command, lotIndex uint64) (*api.RecoverRPLFromLotResponse, error) { +func recoverRplFromLot(c *cli.Command, lotIndex uint64, opts *bind.TransactOpts) (*api.RecoverRPLFromLotResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -106,10 +107,6 @@ func recoverRplFromLot(c *cli.Command, lotIndex uint64) (*api.RecoverRPLFromLotR if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -118,12 +115,6 @@ func recoverRplFromLot(c *cli.Command, lotIndex uint64) (*api.RecoverRPLFromLotR // Response response := api.RecoverRPLFromLotResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/auction/routes.go b/rocketpool/api/auction/routes.go index 89c4b80c0..b5e0ab268 100644 --- a/rocketpool/api/auction/routes.go +++ b/rocketpool/api/auction/routes.go @@ -8,6 +8,7 @@ import ( "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) @@ -29,7 +30,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/auction/create-lot", func(w http.ResponseWriter, r *http.Request) { - resp, err := createLot(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := createLot(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -49,7 +55,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := bidOnLot(c, lotIndex, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := bidOnLot(c, lotIndex, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -69,7 +80,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := claimFromLot(c, lotIndex) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := claimFromLot(c, lotIndex, opts) apiutils.WriteResponse(w, resp, err) }) @@ -89,7 +105,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := recoverRplFromLot(c, lotIndex) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := recoverRplFromLot(c, lotIndex, opts) apiutils.WriteResponse(w, resp, err) }) } diff --git a/rocketpool/api/megapool/claim-refunds.go b/rocketpool/api/megapool/claim-refunds.go index 08c5d2c73..8e72c9fca 100644 --- a/rocketpool/api/megapool/claim-refunds.go +++ b/rocketpool/api/megapool/claim-refunds.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/urfave/cli/v3" @@ -83,7 +84,7 @@ func canClaimRefund(c *cli.Command) (*api.CanClaimRefundResponse, error) { } -func claimRefund(c *cli.Command) (*api.ClaimRefundResponse, error) { +func claimRefund(c *cli.Command, opts *bind.TransactOpts) (*api.ClaimRefundResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -119,12 +120,6 @@ func claimRefund(c *cli.Command) (*api.ClaimRefundResponse, error) { return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/megapool/delegate.go b/rocketpool/api/megapool/delegate.go index dfc8f4030..630e39aef 100644 --- a/rocketpool/api/megapool/delegate.go +++ b/rocketpool/api/megapool/delegate.go @@ -3,6 +3,7 @@ package megapool import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/shared/services" @@ -49,16 +50,12 @@ func canDelegateUpgrade(c *cli.Command, megapoolAddress common.Address) (*api.Me return &response, nil } -func delegateUpgrade(c *cli.Command, megapoolAddress common.Address) (*api.MegapoolDelegateUpgradeResponse, error) { +func delegateUpgrade(c *cli.Command, megapoolAddress common.Address, opts *bind.TransactOpts) (*api.MegapoolDelegateUpgradeResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -73,12 +70,6 @@ func delegateUpgrade(c *cli.Command, megapoolAddress common.Address) (*api.Megap return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -178,15 +169,11 @@ func canSetUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, use } -func setUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, useLatest bool) (*api.MegapoolSetUseLatestDelegateResponse, error) { +func setUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, useLatest bool, opts *bind.TransactOpts) (*api.MegapoolSetUseLatestDelegateResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -201,12 +188,6 @@ func setUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, useLat return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/megapool/dissolve-validator.go b/rocketpool/api/megapool/dissolve-validator.go index 1384c45aa..03a4e82a1 100644 --- a/rocketpool/api/megapool/dissolve-validator.go +++ b/rocketpool/api/megapool/dissolve-validator.go @@ -3,6 +3,7 @@ package megapool import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" @@ -83,7 +84,7 @@ func canDissolveValidator(c *cli.Command, validatorId uint32) (*api.CanDissolveV } -func dissolveValidator(c *cli.Command, validatorId uint32) (*api.DissolveValidatorResponse, error) { +func dissolveValidator(c *cli.Command, validatorId uint32, opts *bind.TransactOpts) (*api.DissolveValidatorResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -119,12 +120,6 @@ func dissolveValidator(c *cli.Command, validatorId uint32) (*api.DissolveValidat return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/megapool/dissolve-with-proof.go b/rocketpool/api/megapool/dissolve-with-proof.go index 4e820a472..c864eedde 100644 --- a/rocketpool/api/megapool/dissolve-with-proof.go +++ b/rocketpool/api/megapool/dissolve-with-proof.go @@ -3,6 +3,7 @@ package megapool import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/bindings/types" @@ -110,7 +111,7 @@ func canDissolveWithProof(c *cli.Command, validatorId uint32) (*api.CanDissolveW } -func dissolveWithProof(c *cli.Command, validatorId uint32) (*api.DissolveWithProofResponse, error) { +func dissolveWithProof(c *cli.Command, validatorId uint32, opts *bind.TransactOpts) (*api.DissolveWithProofResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -165,12 +166,6 @@ func dissolveWithProof(c *cli.Command, validatorId uint32) (*api.DissolveWithPro return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/megapool/distribute.go b/rocketpool/api/megapool/distribute.go index dee731e54..09cae91e7 100644 --- a/rocketpool/api/megapool/distribute.go +++ b/rocketpool/api/megapool/distribute.go @@ -3,6 +3,7 @@ package megapool import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" @@ -93,7 +94,7 @@ func canDistributeMegapool(c *cli.Command) (*api.CanDistributeMegapoolResponse, return &response, nil } -func distributeMegapool(c *cli.Command) (*api.DistributeMegapoolResponse, error) { +func distributeMegapool(c *cli.Command, opts *bind.TransactOpts) (*api.DistributeMegapoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err @@ -115,12 +116,6 @@ func distributeMegapool(c *cli.Command) (*api.DistributeMegapoolResponse, error) return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/megapool/exit-queue.go b/rocketpool/api/megapool/exit-queue.go index 5b9da30ea..376517d74 100644 --- a/rocketpool/api/megapool/exit-queue.go +++ b/rocketpool/api/megapool/exit-queue.go @@ -3,6 +3,7 @@ package megapool import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" @@ -76,7 +77,7 @@ func canExitQueue(c *cli.Command, validatorIndex uint32) (*api.CanExitQueueRespo } -func exitQueue(c *cli.Command, validatorIndex uint32) (*api.ExitQueueResponse, error) { +func exitQueue(c *cli.Command, validatorIndex uint32, opts *bind.TransactOpts) (*api.ExitQueueResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -102,12 +103,6 @@ func exitQueue(c *cli.Command, validatorIndex uint32) (*api.ExitQueueResponse, e // Response response := api.ExitQueueResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/megapool/notify-final-balance.go b/rocketpool/api/megapool/notify-final-balance.go index 993bed565..691c7f95e 100644 --- a/rocketpool/api/megapool/notify-final-balance.go +++ b/rocketpool/api/megapool/notify-final-balance.go @@ -4,6 +4,7 @@ import ( "fmt" "strconv" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/bindings/types" "github.com/rocket-pool/smartnode/shared/services" @@ -138,7 +139,7 @@ func canNotifyFinalBalance(c *cli.Command, validatorId uint32, withdrawalSlot ui } -func notifyFinalBalance(c *cli.Command, validatorId uint32, withdrawalSlot uint64) (*api.NotifyValidatorExitResponse, error) { +func notifyFinalBalance(c *cli.Command, validatorId uint32, withdrawalSlot uint64, opts *bind.TransactOpts) (*api.NotifyValidatorExitResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -195,12 +196,6 @@ func notifyFinalBalance(c *cli.Command, validatorId uint32, withdrawalSlot uint6 return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - validatorStatus, err := bc.GetValidatorStatus(types.ValidatorPubkey(validatorInfo.Pubkey), nil) if err != nil { return nil, fmt.Errorf("Error getting validator status from beacon chain: %w", err) diff --git a/rocketpool/api/megapool/notify-validator-exit.go b/rocketpool/api/megapool/notify-validator-exit.go index 77587104a..924793ec2 100644 --- a/rocketpool/api/megapool/notify-validator-exit.go +++ b/rocketpool/api/megapool/notify-validator-exit.go @@ -3,6 +3,7 @@ package megapool import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/bindings/types" "github.com/rocket-pool/smartnode/shared/services" @@ -89,7 +90,7 @@ func canNotifyValidatorExit(c *cli.Command, validatorId uint32) (*api.CanNotifyV } -func notifyValidatorExit(c *cli.Command, validatorId uint32) (*api.NotifyValidatorExitResponse, error) { +func notifyValidatorExit(c *cli.Command, validatorId uint32, opts *bind.TransactOpts) (*api.NotifyValidatorExitResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -148,12 +149,6 @@ func notifyValidatorExit(c *cli.Command, validatorId uint32) (*api.NotifyValidat return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/megapool/reduce-bond.go b/rocketpool/api/megapool/reduce-bond.go index b5052056d..a47b44555 100644 --- a/rocketpool/api/megapool/reduce-bond.go +++ b/rocketpool/api/megapool/reduce-bond.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/urfave/cli/v3" @@ -90,7 +91,7 @@ func canReduceBond(c *cli.Command, amount *big.Int) (*api.CanReduceBondResponse, } -func reduceBond(c *cli.Command, amount *big.Int) (*api.ReduceBondResponse, error) { +func reduceBond(c *cli.Command, amount *big.Int, opts *bind.TransactOpts) (*api.ReduceBondResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -126,12 +127,6 @@ func reduceBond(c *cli.Command, amount *big.Int) (*api.ReduceBondResponse, error return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/megapool/repay-debt.go b/rocketpool/api/megapool/repay-debt.go index fe8487794..d78bfcb34 100644 --- a/rocketpool/api/megapool/repay-debt.go +++ b/rocketpool/api/megapool/repay-debt.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/urfave/cli/v3" @@ -103,7 +104,7 @@ func canRepayDebt(c *cli.Command, amount *big.Int) (*api.CanRepayDebtResponse, e } -func repayDebt(c *cli.Command, amount *big.Int) (*api.RepayDebtResponse, error) { +func repayDebt(c *cli.Command, amount *big.Int, opts *bind.TransactOpts) (*api.RepayDebtResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -149,12 +150,6 @@ func repayDebt(c *cli.Command, amount *big.Int) (*api.RepayDebtResponse, error) return nil, fmt.Errorf("no debt to repay") } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - opts.Value = amount // Override the provided pending TX if requested diff --git a/rocketpool/api/megapool/routes.go b/rocketpool/api/megapool/routes.go index e687eed75..679370a60 100644 --- a/rocketpool/api/megapool/routes.go +++ b/rocketpool/api/megapool/routes.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) @@ -31,7 +32,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/megapool/claim-refund", func(w http.ResponseWriter, r *http.Request) { - resp, err := claimRefund(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := claimRefund(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -51,7 +57,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := repayDebt(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := repayDebt(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -71,7 +82,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := reduceBond(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := reduceBond(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -91,7 +107,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := stake(c, validatorId) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := stake(c, validatorId, opts) apiutils.WriteResponse(w, resp, err) }) @@ -111,7 +132,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := dissolveValidator(c, validatorId) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := dissolveValidator(c, validatorId, opts) apiutils.WriteResponse(w, resp, err) }) @@ -131,7 +157,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := dissolveWithProof(c, validatorId) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := dissolveWithProof(c, validatorId, opts) apiutils.WriteResponse(w, resp, err) }) @@ -171,7 +202,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := notifyValidatorExit(c, validatorId) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := notifyValidatorExit(c, validatorId, opts) apiutils.WriteResponse(w, resp, err) }) @@ -201,7 +237,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := notifyFinalBalance(c, validatorId, slot) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := notifyFinalBalance(c, validatorId, slot, opts) apiutils.WriteResponse(w, resp, err) }) @@ -221,7 +262,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := exitQueue(c, validatorIndex) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := exitQueue(c, validatorIndex, opts) apiutils.WriteResponse(w, resp, err) }) @@ -231,7 +277,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/megapool/distribute", func(w http.ResponseWriter, r *http.Request) { - resp, err := distributeMegapool(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := distributeMegapool(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -269,7 +320,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/megapool/delegate-upgrade", func(w http.ResponseWriter, r *http.Request) { address := common.HexToAddress(r.FormValue("address")) - resp, err := delegateUpgrade(c, address) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := delegateUpgrade(c, address, opts) apiutils.WriteResponse(w, resp, err) }) @@ -283,7 +339,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/megapool/set-use-latest-delegate", func(w http.ResponseWriter, r *http.Request) { address := common.HexToAddress(r.FormValue("address")) setting := r.FormValue("setting") == "true" - resp, err := setUseLatestDelegate(c, address, setting) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setUseLatestDelegate(c, address, setting, opts) apiutils.WriteResponse(w, resp, err) }) diff --git a/rocketpool/api/megapool/stake.go b/rocketpool/api/megapool/stake.go index c5a02ee31..f800241d4 100644 --- a/rocketpool/api/megapool/stake.go +++ b/rocketpool/api/megapool/stake.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/bindings/types" "github.com/urfave/cli/v3" @@ -115,7 +116,7 @@ func canStake(c *cli.Command, validatorId uint64) (*api.CanStakeResponse, error) } -func stake(c *cli.Command, validatorId uint64) (*api.StakeResponse, error) { +func stake(c *cli.Command, validatorId uint64, opts *bind.TransactOpts) (*api.StakeResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -170,12 +171,6 @@ func stake(c *cli.Command, validatorId uint64) (*api.StakeResponse, error) { return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/minipool/close.go b/rocketpool/api/minipool/close.go index 43e4d6e3e..bac072825 100644 --- a/rocketpool/api/minipool/close.go +++ b/rocketpool/api/minipool/close.go @@ -307,16 +307,12 @@ func getMinipoolCloseDetails(rp *rocketpool.RocketPool, minipoolAddress common.A } -func closeMinipool(c *cli.Command, minipoolAddress common.Address) (*api.CloseMinipoolResponse, error) { +func closeMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind.TransactOpts) (*api.CloseMinipoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -337,12 +333,6 @@ func closeMinipool(c *cli.Command, minipoolAddress common.Address) (*api.CloseMi return nil, fmt.Errorf("cannot create v3 binding for minipool %s, version %d", minipoolAddress.Hex(), mp.GetVersion()) } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/minipool/delegate.go b/rocketpool/api/minipool/delegate.go index 3c0850e22..623f243d8 100644 --- a/rocketpool/api/minipool/delegate.go +++ b/rocketpool/api/minipool/delegate.go @@ -3,6 +3,7 @@ package minipool import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/minipool" "github.com/rocket-pool/smartnode/bindings/rocketpool" @@ -60,16 +61,12 @@ func canDelegateUpgrade(c *cli.Command, minipoolAddress common.Address) (*api.Ca } -func delegateUpgrade(c *cli.Command, minipoolAddress common.Address) (*api.DelegateUpgradeResponse, error) { +func delegateUpgrade(c *cli.Command, minipoolAddress common.Address, opts *bind.TransactOpts) (*api.DelegateUpgradeResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -84,12 +81,6 @@ func delegateUpgrade(c *cli.Command, minipoolAddress common.Address) (*api.Deleg return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -174,17 +165,13 @@ func canSetUseLatestDelegate(c *cli.Command, minipoolAddress common.Address) (*a } -func setUseLatestDelegate(c *cli.Command, minipoolAddress common.Address) (*api.SetUseLatestDelegateResponse, error) { +func setUseLatestDelegate(c *cli.Command, minipoolAddress common.Address, opts *bind.TransactOpts) (*api.SetUseLatestDelegateResponse, error) { setting := true // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -225,12 +212,6 @@ func setUseLatestDelegate(c *cli.Command, minipoolAddress common.Address) (*api. } } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/minipool/dissolve.go b/rocketpool/api/minipool/dissolve.go index 8c2a6daf1..9adc95141 100644 --- a/rocketpool/api/minipool/dissolve.go +++ b/rocketpool/api/minipool/dissolve.go @@ -3,6 +3,7 @@ package minipool import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/minipool" "github.com/rocket-pool/smartnode/bindings/types" @@ -69,16 +70,12 @@ func canDissolveMinipool(c *cli.Command, minipoolAddress common.Address) (*api.C } -func dissolveMinipool(c *cli.Command, minipoolAddress common.Address) (*api.DissolveMinipoolResponse, error) { +func dissolveMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind.TransactOpts) (*api.DissolveMinipoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -93,12 +90,6 @@ func dissolveMinipool(c *cli.Command, minipoolAddress common.Address) (*api.Diss return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/minipool/distribute.go b/rocketpool/api/minipool/distribute.go index d6d8f9be7..a3c1527a0 100644 --- a/rocketpool/api/minipool/distribute.go +++ b/rocketpool/api/minipool/distribute.go @@ -5,6 +5,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/minipool" "github.com/rocket-pool/smartnode/bindings/types" @@ -191,16 +192,12 @@ func getDistributeBalanceDetails(c *cli.Command) (*api.GetDistributeBalanceDetai } -func distributeBalance(c *cli.Command, minipoolAddress common.Address) (*api.CloseMinipoolResponse, error) { +func distributeBalance(c *cli.Command, minipoolAddress common.Address, opts *bind.TransactOpts) (*api.CloseMinipoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -215,12 +212,6 @@ func distributeBalance(c *cli.Command, minipoolAddress common.Address) (*api.Clo return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/minipool/promote.go b/rocketpool/api/minipool/promote.go index 76b370f27..c81ab49ff 100644 --- a/rocketpool/api/minipool/promote.go +++ b/rocketpool/api/minipool/promote.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/minipool" "github.com/rocket-pool/smartnode/bindings/settings/trustednode" @@ -111,16 +112,12 @@ func canPromoteMinipool(c *cli.Command, minipoolAddress common.Address) (*api.Ca } -func promoteMinipool(c *cli.Command, minipoolAddress common.Address) (*api.StakeMinipoolResponse, error) { +func promoteMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind.TransactOpts) (*api.StakeMinipoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -139,12 +136,6 @@ func promoteMinipool(c *cli.Command, minipoolAddress common.Address) (*api.Stake return nil, fmt.Errorf("cannot promte minipool %s because its delegate version is too low (v%d); please update the delegate to promote it", mp.GetAddress().Hex(), mp.GetVersion()) } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/minipool/refund.go b/rocketpool/api/minipool/refund.go index ac9ec36ea..1298702bc 100644 --- a/rocketpool/api/minipool/refund.go +++ b/rocketpool/api/minipool/refund.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/minipool" "github.com/urfave/cli/v3" @@ -69,16 +70,12 @@ func canRefundMinipool(c *cli.Command, minipoolAddress common.Address) (*api.Can } -func refundMinipool(c *cli.Command, minipoolAddress common.Address) (*api.RefundMinipoolResponse, error) { +func refundMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind.TransactOpts) (*api.RefundMinipoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -93,12 +90,6 @@ func refundMinipool(c *cli.Command, minipoolAddress common.Address) (*api.Refund return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/minipool/rescue-dissolved.go b/rocketpool/api/minipool/rescue-dissolved.go index 5a3898ee0..678696473 100644 --- a/rocketpool/api/minipool/rescue-dissolved.go +++ b/rocketpool/api/minipool/rescue-dissolved.go @@ -281,7 +281,7 @@ func getDepositTx(rp *rocketpool.RocketPool, w wallet.Wallet, bc beacon.Client, } -func rescueDissolvedMinipool(c *cli.Command, minipoolAddress common.Address, amount *big.Int, submit bool) (*api.RescueDissolvedMinipoolResponse, error) { +func rescueDissolvedMinipool(c *cli.Command, minipoolAddress common.Address, amount *big.Int, submit bool, opts *bind.TransactOpts) (*api.RescueDissolvedMinipoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -303,11 +303,6 @@ func rescueDissolvedMinipool(c *cli.Command, minipoolAddress common.Address, amo // Response response := api.RescueDissolvedMinipoolResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } opts.Value = amount // Override the provided pending TX if requested diff --git a/rocketpool/api/minipool/routes.go b/rocketpool/api/minipool/routes.go index ceaf9d409..32eb2c058 100644 --- a/rocketpool/api/minipool/routes.go +++ b/rocketpool/api/minipool/routes.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) @@ -34,7 +35,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := refundMinipool(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := refundMinipool(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -54,7 +60,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := stakeMinipool(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := stakeMinipool(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -74,7 +85,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := promoteMinipool(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := promoteMinipool(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -94,7 +110,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := dissolveMinipool(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := dissolveMinipool(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -129,7 +150,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := closeMinipool(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := closeMinipool(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -149,7 +175,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := delegateUpgrade(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := delegateUpgrade(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -169,7 +200,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := setUseLatestDelegate(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setUseLatestDelegate(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -236,7 +272,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := distributeBalance(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := distributeBalance(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -291,7 +332,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { return } submit := r.FormValue("submit") == "true" - resp, err := rescueDissolvedMinipool(c, addr, amount, submit) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := rescueDissolvedMinipool(c, addr, amount, submit, opts) apiutils.WriteResponse(w, resp, err) }) diff --git a/rocketpool/api/minipool/stake.go b/rocketpool/api/minipool/stake.go index ea2bd2320..1899f85dd 100644 --- a/rocketpool/api/minipool/stake.go +++ b/rocketpool/api/minipool/stake.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/minipool" "github.com/rocket-pool/smartnode/bindings/settings/trustednode" @@ -149,7 +150,7 @@ func canStakeMinipool(c *cli.Command, minipoolAddress common.Address) (*api.CanS } -func stakeMinipool(c *cli.Command, minipoolAddress common.Address) (*api.StakeMinipoolResponse, error) { +func stakeMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind.TransactOpts) (*api.StakeMinipoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -177,12 +178,6 @@ func stakeMinipool(c *cli.Command, minipoolAddress common.Address) (*api.StakeMi return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/burn.go b/rocketpool/api/node/burn.go index d253597c4..f79ea520c 100644 --- a/rocketpool/api/node/burn.go +++ b/rocketpool/api/node/burn.go @@ -4,6 +4,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/tokens" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -103,7 +105,7 @@ func canNodeBurn(c *cli.Command, amountWei *big.Int, token string) (*api.CanNode } -func nodeBurn(c *cli.Command, amountWei *big.Int, token string) (*api.NodeBurnResponse, error) { +func nodeBurn(c *cli.Command, amountWei *big.Int, token string, opts *bind.TransactOpts) (*api.NodeBurnResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -112,10 +114,6 @@ func nodeBurn(c *cli.Command, amountWei *big.Int, token string) (*api.NodeBurnRe if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -124,12 +122,6 @@ func nodeBurn(c *cli.Command, amountWei *big.Int, token string) (*api.NodeBurnRe // Response response := api.NodeBurnResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/claim-rewards.go b/rocketpool/api/node/claim-rewards.go index dd433e0cd..a86990e13 100644 --- a/rocketpool/api/node/claim-rewards.go +++ b/rocketpool/api/node/claim-rewards.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -240,7 +241,7 @@ func canClaimRewards(c *cli.Command, indicesString string) (*api.CanNodeClaimRew return &response, nil } -func claimRewards(c *cli.Command, indicesString string) (*api.NodeClaimRewardsResponse, error) { +func claimRewards(c *cli.Command, indicesString string, opts *bind.TransactOpts) (*api.NodeClaimRewardsResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -268,12 +269,6 @@ func claimRewards(c *cli.Command, indicesString string) (*api.NodeClaimRewardsRe return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -345,7 +340,7 @@ func canClaimAndStakeRewards(c *cli.Command, indicesString string, stakeAmount * } -func claimAndStakeRewards(c *cli.Command, indicesString string, stakeAmount *big.Int) (*api.NodeClaimAndStakeRewardsResponse, error) { +func claimAndStakeRewards(c *cli.Command, indicesString string, stakeAmount *big.Int, opts *bind.TransactOpts) (*api.NodeClaimAndStakeRewardsResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -373,12 +368,6 @@ func claimAndStakeRewards(c *cli.Command, indicesString string, stakeAmount *big return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/claim-rpl.go b/rocketpool/api/node/claim-rpl.go index a67828ac5..6cfc8cb4f 100644 --- a/rocketpool/api/node/claim-rpl.go +++ b/rocketpool/api/node/claim-rpl.go @@ -4,6 +4,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/urfave/cli/v3" "github.com/rocket-pool/smartnode/bindings/legacy/v1.0.0/rewards" @@ -75,7 +77,7 @@ func canNodeClaimRpl(c *cli.Command) (*api.CanNodeClaimRplResponse, error) { return &response, nil } -func nodeClaimRpl(c *cli.Command) (*api.NodeClaimRplResponse, error) { +func nodeClaimRpl(c *cli.Command, opts *bind.TransactOpts) (*api.NodeClaimRplResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -84,10 +86,6 @@ func nodeClaimRpl(c *cli.Command) (*api.NodeClaimRplResponse, error) { if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -100,12 +98,6 @@ func nodeClaimRpl(c *cli.Command) (*api.NodeClaimRplResponse, error) { // Response response := api.NodeClaimRplResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/claim-unclaimed-rewards.go b/rocketpool/api/node/claim-unclaimed-rewards.go index 81bb93ff3..99d84eaff 100644 --- a/rocketpool/api/node/claim-unclaimed-rewards.go +++ b/rocketpool/api/node/claim-unclaimed-rewards.go @@ -3,6 +3,7 @@ package node import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" @@ -53,16 +54,12 @@ func canClaimUnclaimedRewards(c *cli.Command, nodeAddress common.Address) (*api. } -func claimUnclaimedRewards(c *cli.Command, nodeAddress common.Address) (*api.ClaimUnclaimedRewardsResponse, error) { +func claimUnclaimedRewards(c *cli.Command, nodeAddress common.Address, opts *bind.TransactOpts) (*api.ClaimUnclaimedRewardsResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -71,12 +68,6 @@ func claimUnclaimedRewards(c *cli.Command, nodeAddress common.Address) (*api.Cla // Response response := api.ClaimUnclaimedRewardsResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/create-vacant-minipool.go b/rocketpool/api/node/create-vacant-minipool.go index f97a8b2f2..57508f728 100644 --- a/rocketpool/api/node/create-vacant-minipool.go +++ b/rocketpool/api/node/create-vacant-minipool.go @@ -6,6 +6,8 @@ import ( "math/big" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/minipool" "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/bindings/settings/protocol" @@ -153,7 +155,7 @@ func canCreateVacantMinipool(c *cli.Command, amountWei *big.Int, minNodeFee floa } -func createVacantMinipool(c *cli.Command, amountWei *big.Int, minNodeFee float64, salt *big.Int, pubkey rptypes.ValidatorPubkey) (*api.CreateVacantMinipoolResponse, error) { +func createVacantMinipool(c *cli.Command, amountWei *big.Int, minNodeFee float64, salt *big.Int, pubkey rptypes.ValidatorPubkey, opts *bind.TransactOpts) (*api.CreateVacantMinipoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -220,12 +222,6 @@ func createVacantMinipool(c *cli.Command, amountWei *big.Int, minNodeFee float64 scrubPeriod := time.Duration(scrubPeriodUnix) * time.Second response.ScrubPeriod = scrubPeriod - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Get the next minipool address and withdrawal credentials minipoolAddress, err := minipool.GetExpectedAddress(rp, nodeAccount.Address, salt, nil) if err != nil { diff --git a/rocketpool/api/node/deposit.go b/rocketpool/api/node/deposit.go index 3c6e894f3..1adf57ac4 100644 --- a/rocketpool/api/node/deposit.go +++ b/rocketpool/api/node/deposit.go @@ -7,6 +7,7 @@ import ( "math/big" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" "github.com/rocket-pool/smartnode/bindings/deposit" @@ -292,7 +293,7 @@ func canNodeDeposits(c *cli.Command, count uint64, amountWei *big.Int, minNodeFe } -func nodeDeposits(c *cli.Command, count uint64, amountWei *big.Int, minNodeFee float64, salt *big.Int, useCreditBalance bool, expressTicketsRequested int64, submit bool) (*api.NodeDepositsResponse, error) { +func nodeDeposits(c *cli.Command, count uint64, amountWei *big.Int, minNodeFee float64, salt *big.Int, useCreditBalance bool, expressTicketsRequested int64, submit bool, opts *bind.TransactOpts) (*api.NodeDepositsResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -369,12 +370,6 @@ func nodeDeposits(c *cli.Command, count uint64, amountWei *big.Int, minNodeFee f return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Set the value to the total amount needed// Get how much credit to use if useCreditBalance { remainingAmount := big.NewInt(0).Sub(amountWei, creditBalanceWei) diff --git a/rocketpool/api/node/distributor.go b/rocketpool/api/node/distributor.go index dfb7e7f6c..f29a128c0 100644 --- a/rocketpool/api/node/distributor.go +++ b/rocketpool/api/node/distributor.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/bindings/utils/eth" "github.com/urfave/cli/v3" @@ -96,16 +98,12 @@ func getInitializeFeeDistributorGas(c *cli.Command) (*api.NodeInitializeFeeDistr } -func initializeFeeDistributor(c *cli.Command) (*api.NodeInitializeFeeDistributorResponse, error) { +func initializeFeeDistributor(c *cli.Command, opts *bind.TransactOpts) (*api.NodeInitializeFeeDistributorResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -114,12 +112,6 @@ func initializeFeeDistributor(c *cli.Command) (*api.NodeInitializeFeeDistributor // Response response := api.NodeInitializeFeeDistributorResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) @@ -215,7 +207,7 @@ func canDistribute(c *cli.Command) (*api.NodeCanDistributeResponse, error) { } -func distribute(c *cli.Command) (*api.NodeDistributeResponse, error) { +func distribute(c *cli.Command, opts *bind.TransactOpts) (*api.NodeDistributeResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { return nil, err @@ -254,11 +246,6 @@ func distribute(c *cli.Command) (*api.NodeDistributeResponse, error) { } // Get gas estimates - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/express-ticket.go b/rocketpool/api/node/express-ticket.go index c60d2368e..1b19ebdbe 100644 --- a/rocketpool/api/node/express-ticket.go +++ b/rocketpool/api/node/express-ticket.go @@ -3,6 +3,8 @@ package node import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" @@ -116,7 +118,7 @@ func canProvisionExpressTickets(c *cli.Command) (*api.CanProvisionExpressTickets } -func provisionExpressTickets(c *cli.Command) (*api.ProvisionExpressTicketsResponse, error) { +func provisionExpressTickets(c *cli.Command, opts *bind.TransactOpts) (*api.ProvisionExpressTicketsResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -143,12 +145,6 @@ func provisionExpressTickets(c *cli.Command) (*api.ProvisionExpressTicketsRespon // Response response := api.ProvisionExpressTicketsResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/primary-withdrawal-address.go b/rocketpool/api/node/primary-withdrawal-address.go index 27e67e12a..274395bdc 100644 --- a/rocketpool/api/node/primary-withdrawal-address.go +++ b/rocketpool/api/node/primary-withdrawal-address.go @@ -3,6 +3,7 @@ package node import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/storage" "github.com/urfave/cli/v3" @@ -54,7 +55,7 @@ func canSetPrimaryWithdrawalAddress(c *cli.Command, withdrawalAddress common.Add return &response, nil } -func setPrimaryWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address, confirm bool) (*api.SetNodePrimaryWithdrawalAddressResponse, error) { +func setPrimaryWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address, confirm bool, opts *bind.TransactOpts) (*api.SetNodePrimaryWithdrawalAddressResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -72,12 +73,6 @@ func setPrimaryWithdrawalAddress(c *cli.Command, withdrawalAddress common.Addres // Response response := api.SetNodePrimaryWithdrawalAddressResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -160,7 +155,7 @@ func canConfirmPrimaryWithdrawalAddress(c *cli.Command) (*api.CanConfirmNodePrim return &response, nil } -func confirmPrimaryWithdrawalAddress(c *cli.Command) (*api.ConfirmNodePrimaryWithdrawalAddressResponse, error) { +func confirmPrimaryWithdrawalAddress(c *cli.Command, opts *bind.TransactOpts) (*api.ConfirmNodePrimaryWithdrawalAddressResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -178,12 +173,6 @@ func confirmPrimaryWithdrawalAddress(c *cli.Command) (*api.ConfirmNodePrimaryWit // Response response := api.ConfirmNodePrimaryWithdrawalAddressResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/register.go b/rocketpool/api/node/register.go index ad24bfd0e..4bdff83fc 100644 --- a/rocketpool/api/node/register.go +++ b/rocketpool/api/node/register.go @@ -3,6 +3,8 @@ package node import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/bindings/settings/protocol" "github.com/urfave/cli/v3" @@ -84,7 +86,7 @@ func canRegisterNode(c *cli.Command, timezoneLocation string) (*api.CanRegisterN } -func registerNode(c *cli.Command, timezoneLocation string) (*api.RegisterNodeResponse, error) { +func registerNode(c *cli.Command, timezoneLocation string, opts *bind.TransactOpts) (*api.RegisterNodeResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -93,10 +95,6 @@ func registerNode(c *cli.Command, timezoneLocation string) (*api.RegisterNodeRes if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -105,12 +103,6 @@ func registerNode(c *cli.Command, timezoneLocation string) (*api.RegisterNodeRes // Response response := api.RegisterNodeResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/routes.go b/rocketpool/api/node/routes.go index 51c9425b6..b63af6851 100644 --- a/rocketpool/api/node/routes.go +++ b/rocketpool/api/node/routes.go @@ -11,6 +11,7 @@ import ( rptypes "github.com/rocket-pool/smartnode/bindings/types" "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) @@ -61,7 +62,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/register", func(w http.ResponseWriter, r *http.Request) { tz := r.FormValue("timezoneLocation") - resp, err := registerNode(c, tz) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := registerNode(c, tz, opts) apiutils.WriteResponse(w, resp, err) }) @@ -75,7 +81,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/set-timezone", func(w http.ResponseWriter, r *http.Request) { tz := r.FormValue("timezoneLocation") - resp, err := setTimezoneLocation(c, tz) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setTimezoneLocation(c, tz, opts) apiutils.WriteResponse(w, resp, err) }) @@ -91,7 +102,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/set-primary-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { addr := common.HexToAddress(r.FormValue("address")) confirm := r.FormValue("confirm") == "true" - resp, err := setPrimaryWithdrawalAddress(c, addr, confirm) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setPrimaryWithdrawalAddress(c, addr, confirm, opts) apiutils.WriteResponse(w, resp, err) }) @@ -101,7 +117,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/node/confirm-primary-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { - resp, err := confirmPrimaryWithdrawalAddress(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := confirmPrimaryWithdrawalAddress(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -117,7 +138,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/set-rpl-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { addr := common.HexToAddress(r.FormValue("address")) confirm := r.FormValue("confirm") == "true" - resp, err := setRPLWithdrawalAddress(c, addr, confirm) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setRPLWithdrawalAddress(c, addr, confirm, opts) apiutils.WriteResponse(w, resp, err) }) @@ -127,7 +153,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/node/confirm-rpl-withdrawal-address", func(w http.ResponseWriter, r *http.Request) { - resp, err := confirmRPLWithdrawalAddress(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := confirmRPLWithdrawalAddress(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -164,7 +195,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := approveFsRpl(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := approveFsRpl(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -175,7 +211,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { return } hash := common.HexToHash(r.FormValue("approvalTxHash")) - resp, err := waitForApprovalAndSwapFsRpl(c, amountWei, hash) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := waitForApprovalAndSwapFsRpl(c, amountWei, hash, opts) apiutils.WriteResponse(w, resp, err) }) @@ -185,7 +226,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := swapRpl(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := swapRpl(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -222,7 +268,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := approveRpl(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := approveRpl(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -233,7 +284,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { return } hash := common.HexToHash(r.FormValue("approvalTxHash")) - resp, err := waitForApprovalAndStakeRpl(c, amountWei, hash) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := waitForApprovalAndStakeRpl(c, amountWei, hash, opts) apiutils.WriteResponse(w, resp, err) }) @@ -243,7 +299,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := stakeRpl(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := stakeRpl(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -257,7 +318,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/set-rpl-locking-allowed", func(w http.ResponseWriter, r *http.Request) { allowed := r.FormValue("allowed") == "true" - resp, err := setRplLockAllowed(c, allowed) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setRplLockAllowed(c, allowed, opts) apiutils.WriteResponse(w, resp, err) }) @@ -273,7 +339,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/set-stake-rpl-for-allowed", func(w http.ResponseWriter, r *http.Request) { caller := common.HexToAddress(r.FormValue("caller")) allowed := r.FormValue("allowed") == "true" - resp, err := setStakeRplForAllowed(c, caller, allowed) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setStakeRplForAllowed(c, caller, allowed, opts) apiutils.WriteResponse(w, resp, err) }) @@ -285,7 +356,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/node/withdraw-rpl", func(w http.ResponseWriter, r *http.Request) { - resp, err := nodeWithdrawRpl(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeWithdrawRpl(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -305,7 +381,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := nodeUnstakeLegacyRpl(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeUnstakeLegacyRpl(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -325,7 +406,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := nodeWithdrawRplv1_3_1(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeWithdrawRplv1_3_1(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -345,7 +431,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := nodeUnstakeRpl(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeUnstakeRpl(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -367,7 +458,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := nodeWithdrawEth(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeWithdrawEth(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -387,7 +483,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := nodeWithdrawCredit(c, amountWei) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeWithdrawCredit(c, amountWei, opts) apiutils.WriteResponse(w, resp, err) }) @@ -409,7 +510,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := nodeDeposits(c, params.count, params.amountWei, params.minFee, params.salt, params.useCreditBalance, params.expressTickets, params.submit) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeDeposits(c, params.count, params.amountWei, params.minFee, params.salt, params.useCreditBalance, params.expressTickets, params.submit, opts) apiutils.WriteResponse(w, resp, err) }) @@ -435,14 +541,24 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { } token := r.FormValue("token") to := common.HexToAddress(r.FormValue("to")) - resp, err := nodeSend(c, amountRaw, token, to) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeSend(c, amountRaw, token, to, opts) apiutils.WriteResponse(w, resp, err) }) mux.HandleFunc("/api/node/send-all", func(w http.ResponseWriter, r *http.Request) { token := r.FormValue("token") to := common.HexToAddress(r.FormValue("to")) - resp, err := nodeSendAllTokens(c, token, to) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeSendAllTokens(c, token, to, opts) apiutils.WriteResponse(w, resp, err) }) @@ -464,7 +580,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { return } token := r.FormValue("token") - resp, err := nodeBurn(c, amountWei, token) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeBurn(c, amountWei, token, opts) apiutils.WriteResponse(w, resp, err) }) @@ -476,7 +597,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/node/claim-rpl-rewards", func(w http.ResponseWriter, r *http.Request) { - resp, err := nodeClaimRpl(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := nodeClaimRpl(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -493,7 +619,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/node/initialize-fee-distributor", func(w http.ResponseWriter, r *http.Request) { - resp, err := initializeFeeDistributor(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := initializeFeeDistributor(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -503,7 +634,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/node/distribute", func(w http.ResponseWriter, r *http.Request) { - resp, err := distribute(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := distribute(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -522,7 +658,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/claim-rewards", func(w http.ResponseWriter, r *http.Request) { indices := r.FormValue("indices") - resp, err := claimRewards(c, indices) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := claimRewards(c, indices, opts) apiutils.WriteResponse(w, resp, err) }) @@ -544,7 +685,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := claimAndStakeRewards(c, indices, stakeAmount) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := claimAndStakeRewards(c, indices, stakeAmount, opts) apiutils.WriteResponse(w, resp, err) }) @@ -563,7 +709,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/set-smoothing-pool-status", func(w http.ResponseWriter, r *http.Request) { status := r.FormValue("status") == "true" - resp, err := setSmoothingPoolStatus(c, status) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setSmoothingPoolStatus(c, status, opts) apiutils.WriteResponse(w, resp, err) }) @@ -613,7 +764,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := createVacantMinipool(c, params.amountWei, params.minFee, params.salt, params.pubkey) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := createVacantMinipool(c, params.amountWei, params.minFee, params.salt, params.pubkey, opts) apiutils.WriteResponse(w, resp, err) }) @@ -637,7 +793,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, fmt.Errorf("invalid message hex: %w", err)) return } - resp, err := sendMessage(c, addr, msgBytes) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := sendMessage(c, addr, msgBytes, opts) apiutils.WriteResponse(w, resp, err) }) @@ -659,7 +820,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/node/provision-express-tickets", func(w http.ResponseWriter, r *http.Request) { - resp, err := provisionExpressTickets(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := provisionExpressTickets(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -673,7 +839,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/node/claim-unclaimed-rewards", func(w http.ResponseWriter, r *http.Request) { nodeAddr := common.HexToAddress(r.FormValue("nodeAddress")) - resp, err := claimUnclaimedRewards(c, nodeAddr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := claimUnclaimedRewards(c, nodeAddr, opts) apiutils.WriteResponse(w, resp, err) }) diff --git a/rocketpool/api/node/rpl-withdrawal-address.go b/rocketpool/api/node/rpl-withdrawal-address.go index e42a28b55..97571a561 100644 --- a/rocketpool/api/node/rpl-withdrawal-address.go +++ b/rocketpool/api/node/rpl-withdrawal-address.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/bindings/storage" @@ -103,7 +104,7 @@ func canSetRPLWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address return &response, nil } -func setRPLWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address, confirm bool) (*api.SetNodeRPLWithdrawalAddressResponse, error) { +func setRPLWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address, confirm bool, opts *bind.TransactOpts) (*api.SetNodeRPLWithdrawalAddressResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err @@ -120,12 +121,6 @@ func setRPLWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address, c // Response response := api.SetNodeRPLWithdrawalAddressResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -200,7 +195,7 @@ func canConfirmRPLWithdrawalAddress(c *cli.Command) (*api.CanConfirmNodeRPLWithd return &response, nil } -func confirmRPLWithdrawalAddress(c *cli.Command) (*api.ConfirmNodeRPLWithdrawalAddressResponse, error) { +func confirmRPLWithdrawalAddress(c *cli.Command, opts *bind.TransactOpts) (*api.ConfirmNodeRPLWithdrawalAddressResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err @@ -217,12 +212,6 @@ func confirmRPLWithdrawalAddress(c *cli.Command) (*api.ConfirmNodeRPLWithdrawalA // Response response := api.ConfirmNodeRPLWithdrawalAddressResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/send-message.go b/rocketpool/api/node/send-message.go index 3d7a87da7..2ca7a2797 100644 --- a/rocketpool/api/node/send-message.go +++ b/rocketpool/api/node/send-message.go @@ -5,6 +5,7 @@ import ( "github.com/rocket-pool/smartnode/bindings/utils/eth" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" @@ -47,7 +48,7 @@ func canSendMessage(c *cli.Command, address common.Address, message []byte) (*ap } -func sendMessage(c *cli.Command, address common.Address, message []byte) (*api.NodeSendMessageResponse, error) { +func sendMessage(c *cli.Command, address common.Address, message []byte, opts *bind.TransactOpts) (*api.NodeSendMessageResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -65,12 +66,6 @@ func sendMessage(c *cli.Command, address common.Address, message []byte) (*api.N // Response response := api.NodeSendMessageResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/send.go b/rocketpool/api/node/send.go index 24bea4a6e..d1e6ee782 100644 --- a/rocketpool/api/node/send.go +++ b/rocketpool/api/node/send.go @@ -7,6 +7,7 @@ import ( "math/big" "strings" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/tokens" "github.com/rocket-pool/smartnode/bindings/utils/eth" @@ -203,7 +204,7 @@ func canNodeSend(c *cli.Command, amountRaw float64, token string, to common.Addr } -func nodeSend(c *cli.Command, amountRaw float64, token string, to common.Address) (*api.NodeSendResponse, error) { +func nodeSend(c *cli.Command, amountRaw float64, token string, to common.Address, opts *bind.TransactOpts) (*api.NodeSendResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -225,12 +226,6 @@ func nodeSend(c *cli.Command, amountRaw float64, token string, to common.Address // Response response := api.NodeSendResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -317,7 +312,7 @@ func nodeSend(c *cli.Command, amountRaw float64, token string, to common.Address // the recipient, using the exact *big.Int balance to avoid float64 rounding // errors that would cause "transfer amount exceeds balance" failures. // ETH is not supported here; use nodeSend with a pre-computed amount instead. -func nodeSendAllTokens(c *cli.Command, token string, to common.Address) (*api.NodeSendResponse, error) { +func nodeSendAllTokens(c *cli.Command, token string, to common.Address, opts *bind.TransactOpts) (*api.NodeSendResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -345,12 +340,6 @@ func nodeSendAllTokens(c *cli.Command, token string, to common.Address) (*api.No return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/set-rpl-lock-allowed.go b/rocketpool/api/node/set-rpl-lock-allowed.go index 750bcdffc..4ca37a556 100644 --- a/rocketpool/api/node/set-rpl-lock-allowed.go +++ b/rocketpool/api/node/set-rpl-lock-allowed.go @@ -3,6 +3,8 @@ package node import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/node" "github.com/urfave/cli/v3" @@ -63,7 +65,7 @@ func canSetRplLockAllowed(c *cli.Command, allowed bool) (*api.CanSetRplLockingAl } -func setRplLockAllowed(c *cli.Command, allowed bool) (*api.SetRplLockingAllowedResponse, error) { +func setRplLockAllowed(c *cli.Command, allowed bool, opts *bind.TransactOpts) (*api.SetRplLockingAllowedResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -87,10 +89,6 @@ func setRplLockAllowed(c *cli.Command, allowed bool) (*api.SetRplLockingAllowedR response := api.SetRplLockingAllowedResponse{} // Stake RPL - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) diff --git a/rocketpool/api/node/set-stake-rpl-for-allowed.go b/rocketpool/api/node/set-stake-rpl-for-allowed.go index 562537a6b..a6420d431 100644 --- a/rocketpool/api/node/set-stake-rpl-for-allowed.go +++ b/rocketpool/api/node/set-stake-rpl-for-allowed.go @@ -3,6 +3,7 @@ package node import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/node" "github.com/urfave/cli/v3" @@ -47,16 +48,12 @@ func canSetStakeRplForAllowed(c *cli.Command, caller common.Address, allowed boo } -func setStakeRplForAllowed(c *cli.Command, caller common.Address, allowed bool) (*api.SetStakeRplForAllowedResponse, error) { +func setStakeRplForAllowed(c *cli.Command, caller common.Address, allowed bool, opts *bind.TransactOpts) (*api.SetStakeRplForAllowedResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -66,10 +63,6 @@ func setStakeRplForAllowed(c *cli.Command, caller common.Address, allowed bool) response := api.SetStakeRplForAllowedResponse{} // Stake RPL - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) diff --git a/rocketpool/api/node/set-timezone.go b/rocketpool/api/node/set-timezone.go index 4ac633150..f85947abd 100644 --- a/rocketpool/api/node/set-timezone.go +++ b/rocketpool/api/node/set-timezone.go @@ -4,6 +4,8 @@ import ( "fmt" _ "time/tzdata" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/node" "github.com/urfave/cli/v3" @@ -45,16 +47,12 @@ func canSetTimezoneLocation(c *cli.Command, timezoneLocation string) (*api.CanSe } -func setTimezoneLocation(c *cli.Command, timezoneLocation string) (*api.SetNodeTimezoneResponse, error) { +func setTimezoneLocation(c *cli.Command, timezoneLocation string, opts *bind.TransactOpts) (*api.SetNodeTimezoneResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -63,12 +61,6 @@ func setTimezoneLocation(c *cli.Command, timezoneLocation string) (*api.SetNodeT // Response response := api.SetNodeTimezoneResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/smoothing-pool.go b/rocketpool/api/node/smoothing-pool.go index c06e34ce7..5b2ea3cc6 100644 --- a/rocketpool/api/node/smoothing-pool.go +++ b/rocketpool/api/node/smoothing-pool.go @@ -4,6 +4,8 @@ import ( "context" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/bindings/rewards" rocketpoolapi "github.com/rocket-pool/smartnode/bindings/rocketpool" @@ -112,7 +114,7 @@ func canSetSmoothingPoolStatus(c *cli.Command, status bool) (*api.CanSetSmoothin } -func setSmoothingPoolStatus(c *cli.Command, status bool) (*api.SetSmoothingPoolRegistrationStatusResponse, error) { +func setSmoothingPoolStatus(c *cli.Command, status bool, opts *bind.TransactOpts) (*api.SetSmoothingPoolRegistrationStatusResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -145,12 +147,6 @@ func setSmoothingPoolStatus(c *cli.Command, status bool) (*api.SetSmoothingPoolR // Response response := api.SetSmoothingPoolRegistrationStatusResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/stake-rpl.go b/rocketpool/api/node/stake-rpl.go index 35928b784..f2f39ad65 100644 --- a/rocketpool/api/node/stake-rpl.go +++ b/rocketpool/api/node/stake-rpl.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/node" @@ -144,16 +145,12 @@ func allowanceRpl(c *cli.Command) (*api.NodeStakeRplAllowanceResponse, error) { return &response, nil } -func approveRpl(c *cli.Command, amountWei *big.Int) (*api.NodeStakeRplApproveResponse, error) { +func approveRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeStakeRplApproveResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -169,10 +166,6 @@ func approveRpl(c *cli.Command, amountWei *big.Int) (*api.NodeStakeRplApproveRes } // Approve RPL allowance - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) @@ -189,7 +182,7 @@ func approveRpl(c *cli.Command, amountWei *big.Int) (*api.NodeStakeRplApproveRes } -func waitForApprovalAndStakeRpl(c *cli.Command, amountWei *big.Int, hash common.Hash) (*api.NodeStakeRplStakeResponse, error) { +func waitForApprovalAndStakeRpl(c *cli.Command, amountWei *big.Int, hash common.Hash, opts *bind.TransactOpts) (*api.NodeStakeRplStakeResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -207,20 +200,16 @@ func waitForApprovalAndStakeRpl(c *cli.Command, amountWei *big.Int, hash common. } // Perform the stake - return stakeRpl(c, amountWei) + return stakeRpl(c, amountWei, opts) } -func stakeRpl(c *cli.Command, amountWei *big.Int) (*api.NodeStakeRplStakeResponse, error) { +func stakeRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeStakeRplStakeResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -230,10 +219,6 @@ func stakeRpl(c *cli.Command, amountWei *big.Int) (*api.NodeStakeRplStakeRespons response := api.NodeStakeRplStakeResponse{} // Stake RPL - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) diff --git a/rocketpool/api/node/swap-rpl.go b/rocketpool/api/node/swap-rpl.go index 03d5b42a5..9adb23cb5 100644 --- a/rocketpool/api/node/swap-rpl.go +++ b/rocketpool/api/node/swap-rpl.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/tokens" "github.com/rocket-pool/smartnode/bindings/utils" @@ -145,7 +146,7 @@ func getSwapApprovalGas(c *cli.Command, amountWei *big.Int) (*api.NodeSwapRplApp return &response, nil } -func approveFsRpl(c *cli.Command, amountWei *big.Int) (*api.NodeSwapRplApproveResponse, error) { +func approveFsRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeSwapRplApproveResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -154,10 +155,6 @@ func approveFsRpl(c *cli.Command, amountWei *big.Int) (*api.NodeSwapRplApproveRe if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -173,10 +170,6 @@ func approveFsRpl(c *cli.Command, amountWei *big.Int) (*api.NodeSwapRplApproveRe } // Approve fixed-supply RPL allowance - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) @@ -192,7 +185,7 @@ func approveFsRpl(c *cli.Command, amountWei *big.Int) (*api.NodeSwapRplApproveRe } -func waitForApprovalAndSwapFsRpl(c *cli.Command, amountWei *big.Int, hash common.Hash) (*api.NodeSwapRplSwapResponse, error) { +func waitForApprovalAndSwapFsRpl(c *cli.Command, amountWei *big.Int, hash common.Hash, opts *bind.TransactOpts) (*api.NodeSwapRplSwapResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -212,20 +205,16 @@ func waitForApprovalAndSwapFsRpl(c *cli.Command, amountWei *big.Int, hash common return nil, err } - return swapRpl(c, amountWei) + return swapRpl(c, amountWei, opts) } -func swapRpl(c *cli.Command, amountWei *big.Int) (*api.NodeSwapRplSwapResponse, error) { +func swapRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeSwapRplSwapResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -235,10 +224,6 @@ func swapRpl(c *cli.Command, amountWei *big.Int) (*api.NodeSwapRplSwapResponse, response := api.NodeSwapRplSwapResponse{} // Swap fixed-supply RPL for RPL - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) diff --git a/rocketpool/api/node/unstake-rpl.go b/rocketpool/api/node/unstake-rpl.go index a5459bae6..a3f24d582 100644 --- a/rocketpool/api/node/unstake-rpl.go +++ b/rocketpool/api/node/unstake-rpl.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/node" "github.com/urfave/cli/v3" @@ -104,16 +105,12 @@ func canNodeUnstakeRpl(c *cli.Command, amountWei *big.Int) (*api.CanNodeUnstakeR } -func nodeUnstakeRpl(c *cli.Command, amountWei *big.Int) (*api.NodeUnstakeRplResponse, error) { +func nodeUnstakeRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeUnstakeRplResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -122,12 +119,6 @@ func nodeUnstakeRpl(c *cli.Command, amountWei *big.Int) (*api.NodeUnstakeRplResp // Response response := api.NodeUnstakeRplResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/withdraw-credit.go b/rocketpool/api/node/withdraw-credit.go index 2808a3ed9..5e3404a37 100644 --- a/rocketpool/api/node/withdraw-credit.go +++ b/rocketpool/api/node/withdraw-credit.go @@ -4,6 +4,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/node" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -74,16 +76,12 @@ func canNodeWithdrawCredit(c *cli.Command, amountWei *big.Int) (*api.CanNodeWith } -func nodeWithdrawCredit(c *cli.Command, amountWei *big.Int) (*api.NodeWithdrawCreditResponse, error) { +func nodeWithdrawCredit(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeWithdrawCreditResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -92,12 +90,6 @@ func nodeWithdrawCredit(c *cli.Command, amountWei *big.Int) (*api.NodeWithdrawCr // Response response := api.NodeWithdrawCreditResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/withdraw-eth.go b/rocketpool/api/node/withdraw-eth.go index ebe0ab628..f3242e84a 100644 --- a/rocketpool/api/node/withdraw-eth.go +++ b/rocketpool/api/node/withdraw-eth.go @@ -4,6 +4,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/node" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -84,7 +86,7 @@ func canNodeWithdrawEth(c *cli.Command, amountWei *big.Int) (*api.CanNodeWithdra } -func nodeWithdrawEth(c *cli.Command, amountWei *big.Int) (*api.NodeWithdrawRplResponse, error) { +func nodeWithdrawEth(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeWithdrawRplResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -102,12 +104,6 @@ func nodeWithdrawEth(c *cli.Command, amountWei *big.Int) (*api.NodeWithdrawRplRe // Response response := api.NodeWithdrawRplResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Get node account nodeAccount, err := w.GetNodeAccount() if err != nil { diff --git a/rocketpool/api/node/withdraw-legacy-rpl.go b/rocketpool/api/node/withdraw-legacy-rpl.go index dfcd519ce..01bee6e13 100644 --- a/rocketpool/api/node/withdraw-legacy-rpl.go +++ b/rocketpool/api/node/withdraw-legacy-rpl.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/node" "github.com/urfave/cli/v3" @@ -113,16 +114,12 @@ func canNodeUnstakeLegacyRpl(c *cli.Command, amountWei *big.Int) (*api.CanNodeUn } -func nodeUnstakeLegacyRpl(c *cli.Command, amountWei *big.Int) (*api.NodeUnstakeLegacyRplResponse, error) { +func nodeUnstakeLegacyRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeUnstakeLegacyRplResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -131,12 +128,6 @@ func nodeUnstakeLegacyRpl(c *cli.Command, amountWei *big.Int) (*api.NodeUnstakeL // Response response := api.NodeUnstakeLegacyRplResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/node/withdraw-rpl.go b/rocketpool/api/node/withdraw-rpl.go index 0c2b666c5..10b19324e 100644 --- a/rocketpool/api/node/withdraw-rpl.go +++ b/rocketpool/api/node/withdraw-rpl.go @@ -6,6 +6,7 @@ import ( "math/big" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" node131 "github.com/rocket-pool/smartnode/bindings/legacy/v1.3.1/node" "github.com/rocket-pool/smartnode/bindings/node" @@ -129,16 +130,12 @@ func canNodeWithdrawRpl(c *cli.Command) (*api.CanNodeWithdrawRplResponse, error) } -func nodeWithdrawRpl(c *cli.Command) (*api.NodeWithdrawRplResponse, error) { +func nodeWithdrawRpl(c *cli.Command, opts *bind.TransactOpts) (*api.NodeWithdrawRplResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -147,12 +144,6 @@ func nodeWithdrawRpl(c *cli.Command) (*api.NodeWithdrawRplResponse, error) { // Response response := api.NodeWithdrawRplResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -310,7 +301,7 @@ func canNodeWithdrawRplv1_3_1(c *cli.Command, amountWei *big.Int) (*api.CanNodeW } // Used if saturn is not deployed (v1.3.1) -func nodeWithdrawRplv1_3_1(c *cli.Command, amountWei *big.Int) (*api.NodeWithdrawRplResponse, error) { +func nodeWithdrawRplv1_3_1(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api.NodeWithdrawRplResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { @@ -334,12 +325,6 @@ func nodeWithdrawRplv1_3_1(c *cli.Command, amountWei *big.Int) (*api.NodeWithdra // Response response := api.NodeWithdrawRplResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/cancel-proposal.go b/rocketpool/api/odao/cancel-proposal.go index f57513e6c..8aa5caee3 100644 --- a/rocketpool/api/odao/cancel-proposal.go +++ b/rocketpool/api/odao/cancel-proposal.go @@ -4,6 +4,8 @@ import ( "bytes" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao" "github.com/rocket-pool/smartnode/bindings/dao/trustednode" rptypes "github.com/rocket-pool/smartnode/bindings/types" @@ -91,16 +93,12 @@ func canCancelProposal(c *cli.Command, proposalId uint64) (*api.CanCancelTNDAOPr } -func cancelProposal(c *cli.Command, proposalId uint64) (*api.CancelTNDAOProposalResponse, error) { +func cancelProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) (*api.CancelTNDAOProposalResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -109,12 +107,6 @@ func cancelProposal(c *cli.Command, proposalId uint64) (*api.CancelTNDAOProposal // Response response := api.CancelTNDAOProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/execute-proposal.go b/rocketpool/api/odao/execute-proposal.go index db1278f81..91b56aa75 100644 --- a/rocketpool/api/odao/execute-proposal.go +++ b/rocketpool/api/odao/execute-proposal.go @@ -3,6 +3,8 @@ package odao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao" "github.com/rocket-pool/smartnode/bindings/dao/trustednode" rptypes "github.com/rocket-pool/smartnode/bindings/types" @@ -20,13 +22,13 @@ func canExecuteProposal(c *cli.Command, proposalId uint64) (*api.CanExecuteTNDAO if err := services.RequireNodeWallet(c); err != nil { return nil, err } - if err := services.RequireRocketStorage(c); err != nil { - return nil, err - } w, err := services.GetWallet(c) if err != nil { return nil, err } + if err := services.RequireRocketStorage(c); err != nil { + return nil, err + } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -80,7 +82,7 @@ func canExecuteProposal(c *cli.Command, proposalId uint64) (*api.CanExecuteTNDAO } -func executeProposal(c *cli.Command, proposalId uint64) (*api.ExecuteTNDAOProposalResponse, error) { +func executeProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) (*api.ExecuteTNDAOProposalResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -89,10 +91,6 @@ func executeProposal(c *cli.Command, proposalId uint64) (*api.ExecuteTNDAOPropos if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -101,12 +99,6 @@ func executeProposal(c *cli.Command, proposalId uint64) (*api.ExecuteTNDAOPropos // Response response := api.ExecuteTNDAOProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/join.go b/rocketpool/api/odao/join.go index 996870fb9..2df45f731 100644 --- a/rocketpool/api/odao/join.go +++ b/rocketpool/api/odao/join.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" tndao "github.com/rocket-pool/smartnode/bindings/dao/trustednode" tnsettings "github.com/rocket-pool/smartnode/bindings/settings/trustednode" @@ -118,16 +119,12 @@ func canJoin(c *cli.Command) (*api.CanJoinTNDAOResponse, error) { } -func approveRpl(c *cli.Command) (*api.JoinTNDAOApproveResponse, error) { +func approveRpl(c *cli.Command, opts *bind.TransactOpts) (*api.JoinTNDAOApproveResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -161,10 +158,6 @@ func approveRpl(c *cli.Command) (*api.JoinTNDAOApproveResponse, error) { } // Approve RPL allowance - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) @@ -181,16 +174,12 @@ func approveRpl(c *cli.Command) (*api.JoinTNDAOApproveResponse, error) { } -func waitForApprovalAndJoin(c *cli.Command, hash common.Hash) (*api.JoinTNDAOJoinResponse, error) { +func waitForApprovalAndJoin(c *cli.Command, hash common.Hash, opts *bind.TransactOpts) (*api.JoinTNDAOJoinResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -206,10 +195,6 @@ func waitForApprovalAndJoin(c *cli.Command, hash common.Hash) (*api.JoinTNDAOJoi response := api.JoinTNDAOJoinResponse{} // Join - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) diff --git a/rocketpool/api/odao/leave.go b/rocketpool/api/odao/leave.go index 7b43a319b..d833cb7f7 100644 --- a/rocketpool/api/odao/leave.go +++ b/rocketpool/api/odao/leave.go @@ -3,6 +3,7 @@ package odao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/trustednode" "github.com/urfave/cli/v3" @@ -80,16 +81,12 @@ func canLeave(c *cli.Command) (*api.CanLeaveTNDAOResponse, error) { } -func leave(c *cli.Command, bondRefundAddress common.Address) (*api.LeaveTNDAOResponse, error) { +func leave(c *cli.Command, bondRefundAddress common.Address, opts *bind.TransactOpts) (*api.LeaveTNDAOResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -98,12 +95,6 @@ func leave(c *cli.Command, bondRefundAddress common.Address) (*api.LeaveTNDAORes // Response response := api.LeaveTNDAOResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/penalise-megapool.go b/rocketpool/api/odao/penalise-megapool.go index df02e3604..4cdd6f19e 100644 --- a/rocketpool/api/odao/penalise-megapool.go +++ b/rocketpool/api/odao/penalise-megapool.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/urfave/cli/v3" @@ -46,6 +47,7 @@ func canPenaliseMegapool(c *cli.Command, megapoolAddress common.Address, block * if err != nil { return nil, err } + gasInfo, err := megapool.EstimatePenaliseGas(rp, megapoolAddress, block, amount, opts) if err != nil { return nil, err @@ -57,16 +59,12 @@ func canPenaliseMegapool(c *cli.Command, megapoolAddress common.Address, block * } -func penaliseMegapool(c *cli.Command, megapoolAddress common.Address, block *big.Int, amount *big.Int) (*api.PenaliseMegapoolResponse, error) { +func penaliseMegapool(c *cli.Command, megapoolAddress common.Address, block *big.Int, amount *big.Int, opts *bind.TransactOpts) (*api.PenaliseMegapoolResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -75,12 +73,6 @@ func penaliseMegapool(c *cli.Command, megapoolAddress common.Address, block *big // Response response := api.PenaliseMegapoolResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/propose-invite.go b/rocketpool/api/odao/propose-invite.go index 398afae5d..a31534c5d 100644 --- a/rocketpool/api/odao/propose-invite.go +++ b/rocketpool/api/odao/propose-invite.go @@ -3,6 +3,7 @@ package odao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/trustednode" "github.com/urfave/cli/v3" @@ -81,16 +82,12 @@ func canProposeInvite(c *cli.Command, memberAddress common.Address, memberId, me } -func proposeInvite(c *cli.Command, memberAddress common.Address, memberId, memberUrl string) (*api.ProposeTNDAOInviteResponse, error) { +func proposeInvite(c *cli.Command, memberAddress common.Address, memberId, memberUrl string, opts *bind.TransactOpts) (*api.ProposeTNDAOInviteResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -99,12 +96,6 @@ func proposeInvite(c *cli.Command, memberAddress common.Address, memberId, membe // Response response := api.ProposeTNDAOInviteResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/propose-kick.go b/rocketpool/api/odao/propose-kick.go index 73d977d84..6368e22d1 100644 --- a/rocketpool/api/odao/propose-kick.go +++ b/rocketpool/api/odao/propose-kick.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/trustednode" "github.com/rocket-pool/smartnode/bindings/utils/eth" @@ -92,16 +93,12 @@ func canProposeKick(c *cli.Command, memberAddress common.Address, fineAmountWei } -func proposeKick(c *cli.Command, memberAddress common.Address, fineAmountWei *big.Int) (*api.ProposeTNDAOKickResponse, error) { +func proposeKick(c *cli.Command, memberAddress common.Address, fineAmountWei *big.Int, opts *bind.TransactOpts) (*api.ProposeTNDAOKickResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -132,12 +129,6 @@ func proposeKick(c *cli.Command, memberAddress common.Address, fineAmountWei *bi return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/propose-leave.go b/rocketpool/api/odao/propose-leave.go index 758bc442d..42aec63cc 100644 --- a/rocketpool/api/odao/propose-leave.go +++ b/rocketpool/api/odao/propose-leave.go @@ -3,6 +3,8 @@ package odao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/trustednode" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -92,7 +94,7 @@ func canProposeLeave(c *cli.Command) (*api.CanProposeTNDAOLeaveResponse, error) } -func proposeLeave(c *cli.Command) (*api.ProposeTNDAOLeaveResponse, error) { +func proposeLeave(c *cli.Command, opts *bind.TransactOpts) (*api.ProposeTNDAOLeaveResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { @@ -138,12 +140,6 @@ func proposeLeave(c *cli.Command) (*api.ProposeTNDAOLeaveResponse, error) { return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/propose-settings.go b/rocketpool/api/odao/propose-settings.go index 9d2c8b808..560403e1b 100644 --- a/rocketpool/api/odao/propose-settings.go +++ b/rocketpool/api/odao/propose-settings.go @@ -4,6 +4,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/bindings/settings/trustednode" "github.com/urfave/cli/v3" @@ -63,6 +65,7 @@ func canProposeSettingMembersQuorum(c *cli.Command, quorum float64) (*api.CanPro if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeQuorumGas(rp, quorum, opts) if err != nil { return nil, err @@ -73,16 +76,12 @@ func canProposeSettingMembersQuorum(c *cli.Command, quorum float64) (*api.CanPro } -func proposeSettingMembersQuorum(c *cli.Command, quorum float64) (*api.ProposeTNDAOSettingMembersQuorumResponse, error) { +func proposeSettingMembersQuorum(c *cli.Command, quorum float64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingMembersQuorumResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -91,12 +90,6 @@ func proposeSettingMembersQuorum(c *cli.Command, quorum float64) (*api.ProposeTN // Response response := api.ProposeTNDAOSettingMembersQuorumResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -141,6 +134,7 @@ func canProposeSettingMembersRplBond(c *cli.Command, bondAmountWei *big.Int) (*a if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeRPLBondGas(rp, bondAmountWei, opts) if err != nil { return nil, err @@ -151,16 +145,12 @@ func canProposeSettingMembersRplBond(c *cli.Command, bondAmountWei *big.Int) (*a } -func proposeSettingMembersRplBond(c *cli.Command, bondAmountWei *big.Int) (*api.ProposeTNDAOSettingMembersRplBondResponse, error) { +func proposeSettingMembersRplBond(c *cli.Command, bondAmountWei *big.Int, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingMembersRplBondResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -169,12 +159,6 @@ func proposeSettingMembersRplBond(c *cli.Command, bondAmountWei *big.Int) (*api. // Response response := api.ProposeTNDAOSettingMembersRplBondResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -219,6 +203,7 @@ func canProposeSettingMinipoolUnbondedMax(c *cli.Command, unbondedMinipoolMax ui if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeMinipoolUnbondedMaxGas(rp, unbondedMinipoolMax, opts) if err != nil { return nil, err @@ -229,16 +214,12 @@ func canProposeSettingMinipoolUnbondedMax(c *cli.Command, unbondedMinipoolMax ui } -func proposeSettingMinipoolUnbondedMax(c *cli.Command, unbondedMinipoolMax uint64) (*api.ProposeTNDAOSettingMinipoolUnbondedMaxResponse, error) { +func proposeSettingMinipoolUnbondedMax(c *cli.Command, unbondedMinipoolMax uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingMinipoolUnbondedMaxResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -247,12 +228,6 @@ func proposeSettingMinipoolUnbondedMax(c *cli.Command, unbondedMinipoolMax uint6 // Response response := api.ProposeTNDAOSettingMinipoolUnbondedMaxResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -297,6 +272,7 @@ func canProposeSettingProposalCooldown(c *cli.Command, proposalCooldownTimespan if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeProposalCooldownTimeGas(rp, proposalCooldownTimespan, opts) if err != nil { return nil, err @@ -307,16 +283,12 @@ func canProposeSettingProposalCooldown(c *cli.Command, proposalCooldownTimespan } -func proposeSettingProposalCooldown(c *cli.Command, proposalCooldownTimespan uint64) (*api.ProposeTNDAOSettingProposalCooldownResponse, error) { +func proposeSettingProposalCooldown(c *cli.Command, proposalCooldownTimespan uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingProposalCooldownResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -325,12 +297,6 @@ func proposeSettingProposalCooldown(c *cli.Command, proposalCooldownTimespan uin // Response response := api.ProposeTNDAOSettingProposalCooldownResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -375,6 +341,7 @@ func canProposeSettingProposalVoteTimespan(c *cli.Command, proposalVoteTimespan if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeProposalVoteTimeGas(rp, proposalVoteTimespan, opts) if err != nil { return nil, err @@ -385,16 +352,12 @@ func canProposeSettingProposalVoteTimespan(c *cli.Command, proposalVoteTimespan } -func proposeSettingProposalVoteTimespan(c *cli.Command, proposalVoteTimespan uint64) (*api.ProposeTNDAOSettingProposalVoteTimespanResponse, error) { +func proposeSettingProposalVoteTimespan(c *cli.Command, proposalVoteTimespan uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingProposalVoteTimespanResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -403,12 +366,6 @@ func proposeSettingProposalVoteTimespan(c *cli.Command, proposalVoteTimespan uin // Response response := api.ProposeTNDAOSettingProposalVoteTimespanResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -453,6 +410,7 @@ func canProposeSettingProposalVoteDelayTimespan(c *cli.Command, proposalDelayTim if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeProposalVoteDelayTimeGas(rp, proposalDelayTimespan, opts) if err != nil { return nil, err @@ -463,16 +421,12 @@ func canProposeSettingProposalVoteDelayTimespan(c *cli.Command, proposalDelayTim } -func proposeSettingProposalVoteDelayTimespan(c *cli.Command, proposalDelayTimespan uint64) (*api.ProposeTNDAOSettingProposalVoteDelayTimespanResponse, error) { +func proposeSettingProposalVoteDelayTimespan(c *cli.Command, proposalDelayTimespan uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingProposalVoteDelayTimespanResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -481,12 +435,6 @@ func proposeSettingProposalVoteDelayTimespan(c *cli.Command, proposalDelayTimesp // Response response := api.ProposeTNDAOSettingProposalVoteDelayTimespanResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -531,6 +479,7 @@ func canProposeSettingProposalExecuteTimespan(c *cli.Command, proposalExecuteTim if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeProposalExecuteTimeGas(rp, proposalExecuteTimespan, opts) if err != nil { return nil, err @@ -541,16 +490,12 @@ func canProposeSettingProposalExecuteTimespan(c *cli.Command, proposalExecuteTim } -func proposeSettingProposalExecuteTimespan(c *cli.Command, proposalExecuteTimespan uint64) (*api.ProposeTNDAOSettingProposalExecuteTimespanResponse, error) { +func proposeSettingProposalExecuteTimespan(c *cli.Command, proposalExecuteTimespan uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingProposalExecuteTimespanResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -559,12 +504,6 @@ func proposeSettingProposalExecuteTimespan(c *cli.Command, proposalExecuteTimesp // Response response := api.ProposeTNDAOSettingProposalExecuteTimespanResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -609,6 +548,7 @@ func canProposeSettingProposalActionTimespan(c *cli.Command, proposalActionTimes if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeProposalActionTimeGas(rp, proposalActionTimespan, opts) if err != nil { return nil, err @@ -619,16 +559,12 @@ func canProposeSettingProposalActionTimespan(c *cli.Command, proposalActionTimes } -func proposeSettingProposalActionTimespan(c *cli.Command, proposalActionTimespan uint64) (*api.ProposeTNDAOSettingProposalActionTimespanResponse, error) { +func proposeSettingProposalActionTimespan(c *cli.Command, proposalActionTimespan uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingProposalActionTimespanResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -637,12 +573,6 @@ func proposeSettingProposalActionTimespan(c *cli.Command, proposalActionTimespan // Response response := api.ProposeTNDAOSettingProposalActionTimespanResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -687,6 +617,7 @@ func canProposeSettingScrubPeriod(c *cli.Command, scrubPeriod uint64) (*api.CanP if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeScrubPeriodGas(rp, scrubPeriod, opts) if err != nil { return nil, err @@ -697,16 +628,12 @@ func canProposeSettingScrubPeriod(c *cli.Command, scrubPeriod uint64) (*api.CanP } -func proposeSettingScrubPeriod(c *cli.Command, scrubPeriod uint64) (*api.ProposeTNDAOSettingScrubPeriodResponse, error) { +func proposeSettingScrubPeriod(c *cli.Command, scrubPeriod uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingScrubPeriodResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -715,12 +642,6 @@ func proposeSettingScrubPeriod(c *cli.Command, scrubPeriod uint64) (*api.Propose // Response response := api.ProposeTNDAOSettingScrubPeriodResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -765,6 +686,7 @@ func canProposeSettingPromotionScrubPeriod(c *cli.Command, promotionScrubPeriod if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposePromotionScrubPeriodGas(rp, promotionScrubPeriod, opts) if err != nil { return nil, err @@ -775,16 +697,12 @@ func canProposeSettingPromotionScrubPeriod(c *cli.Command, promotionScrubPeriod } -func proposeSettingPromotionScrubPeriod(c *cli.Command, promotionScrubPeriod uint64) (*api.ProposeTNDAOSettingPromotionScrubPeriodResponse, error) { +func proposeSettingPromotionScrubPeriod(c *cli.Command, promotionScrubPeriod uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingPromotionScrubPeriodResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -793,12 +711,6 @@ func proposeSettingPromotionScrubPeriod(c *cli.Command, promotionScrubPeriod uin // Response response := api.ProposeTNDAOSettingPromotionScrubPeriodResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -843,6 +755,7 @@ func canProposeSettingScrubPenaltyEnabled(c *cli.Command, enabled bool) (*api.Ca if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeScrubPenaltyEnabledGas(rp, enabled, opts) if err != nil { return nil, err @@ -853,16 +766,12 @@ func canProposeSettingScrubPenaltyEnabled(c *cli.Command, enabled bool) (*api.Ca } -func proposeSettingScrubPenaltyEnabled(c *cli.Command, enabled bool) (*api.ProposeTNDAOSettingScrubPeriodResponse, error) { +func proposeSettingScrubPenaltyEnabled(c *cli.Command, enabled bool, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingScrubPeriodResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -871,12 +780,6 @@ func proposeSettingScrubPenaltyEnabled(c *cli.Command, enabled bool) (*api.Propo // Response response := api.ProposeTNDAOSettingScrubPeriodResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -921,6 +824,7 @@ func canProposeSettingBondReductionWindowStart(c *cli.Command, bondReductionWind if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeBondReductionWindowStartGas(rp, bondReductionWindowStart, opts) if err != nil { return nil, err @@ -931,16 +835,12 @@ func canProposeSettingBondReductionWindowStart(c *cli.Command, bondReductionWind } -func proposeSettingBondReductionWindowStart(c *cli.Command, bondReductionWindowStart uint64) (*api.ProposeTNDAOSettingScrubPeriodResponse, error) { +func proposeSettingBondReductionWindowStart(c *cli.Command, bondReductionWindowStart uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingScrubPeriodResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -949,12 +849,6 @@ func proposeSettingBondReductionWindowStart(c *cli.Command, bondReductionWindowS // Response response := api.ProposeTNDAOSettingScrubPeriodResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -999,6 +893,7 @@ func canProposeSettingBondReductionWindowLength(c *cli.Command, bondReductionWin if err != nil { return nil, err } + gasInfo, err := trustednode.EstimateProposeBondReductionWindowLengthGas(rp, bondReductionWindowLength, opts) if err != nil { return nil, err @@ -1009,16 +904,12 @@ func canProposeSettingBondReductionWindowLength(c *cli.Command, bondReductionWin } -func proposeSettingBondReductionWindowLength(c *cli.Command, bondReductionWindowLength uint64) (*api.ProposeTNDAOSettingScrubPeriodResponse, error) { +func proposeSettingBondReductionWindowLength(c *cli.Command, bondReductionWindowLength uint64, opts *bind.TransactOpts) (*api.ProposeTNDAOSettingScrubPeriodResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -1027,12 +918,6 @@ func proposeSettingBondReductionWindowLength(c *cli.Command, bondReductionWindow // Response response := api.ProposeTNDAOSettingScrubPeriodResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/odao/routes.go b/rocketpool/api/odao/routes.go index b2978c72c..55de36b6b 100644 --- a/rocketpool/api/odao/routes.go +++ b/rocketpool/api/odao/routes.go @@ -9,6 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) @@ -55,7 +56,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeInvite(c, addr, memberId, memberUrl) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeInvite(c, addr, memberId, memberUrl, opts) apiutils.WriteResponse(w, resp, err) }) @@ -65,7 +71,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/odao/propose-leave", func(w http.ResponseWriter, r *http.Request) { - resp, err := proposeLeave(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeLeave(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -85,7 +96,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeKick(c, addr, fine) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeKick(c, addr, fine, opts) apiutils.WriteResponse(w, resp, err) }) @@ -105,7 +121,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := cancelProposal(c, id) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := cancelProposal(c, id, opts) apiutils.WriteResponse(w, resp, err) }) @@ -127,7 +148,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { } supportStr := r.FormValue("support") support := supportStr == "true" - resp, err := voteOnProposal(c, id, support) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := voteOnProposal(c, id, support, opts) apiutils.WriteResponse(w, resp, err) }) @@ -147,7 +173,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := executeProposal(c, id) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := executeProposal(c, id, opts) apiutils.WriteResponse(w, resp, err) }) @@ -157,7 +188,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/odao/join-approve-rpl", func(w http.ResponseWriter, r *http.Request) { - resp, err := approveRpl(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := approveRpl(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -168,7 +204,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { return } hash := common.HexToHash(hashStr) - resp, err := waitForApprovalAndJoin(c, hash) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := waitForApprovalAndJoin(c, hash, opts) apiutils.WriteResponse(w, resp, err) }) @@ -183,7 +224,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, fmt.Errorf("missing required parameter: bondRefundAddress")) return } - resp, err := leave(c, common.HexToAddress(bondRefundStr)) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := leave(c, common.HexToAddress(bondRefundStr), opts) apiutils.WriteResponse(w, resp, err) }) @@ -218,7 +264,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := penaliseMegapool(c, megapool, block, amount) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := penaliseMegapool(c, megapool, block, amount, opts) apiutils.WriteResponse(w, resp, err) }) @@ -239,7 +290,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingMembersQuorum(c, quorum) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingMembersQuorum(c, quorum, opts) apiutils.WriteResponse(w, resp, err) }) @@ -259,7 +315,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingMembersRplBond(c, bond) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingMembersRplBond(c, bond, opts) apiutils.WriteResponse(w, resp, err) }) @@ -279,7 +340,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingMinipoolUnbondedMax(c, max) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingMinipoolUnbondedMax(c, max, opts) apiutils.WriteResponse(w, resp, err) }) @@ -299,7 +365,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingProposalCooldown(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalCooldown(c, val, opts) apiutils.WriteResponse(w, resp, err) }) @@ -319,7 +390,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingProposalVoteTimespan(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalVoteTimespan(c, val, opts) apiutils.WriteResponse(w, resp, err) }) @@ -339,7 +415,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingProposalVoteDelayTimespan(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalVoteDelayTimespan(c, val, opts) apiutils.WriteResponse(w, resp, err) }) @@ -359,7 +440,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingProposalExecuteTimespan(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalExecuteTimespan(c, val, opts) apiutils.WriteResponse(w, resp, err) }) @@ -379,7 +465,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingProposalActionTimespan(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingProposalActionTimespan(c, val, opts) apiutils.WriteResponse(w, resp, err) }) @@ -399,7 +490,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingScrubPeriod(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingScrubPeriod(c, val, opts) apiutils.WriteResponse(w, resp, err) }) @@ -419,7 +515,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingPromotionScrubPeriod(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingPromotionScrubPeriod(c, val, opts) apiutils.WriteResponse(w, resp, err) }) @@ -431,7 +532,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/odao/propose-scrub-penalty-enabled", func(w http.ResponseWriter, r *http.Request) { enabledStr := r.FormValue("enabled") - resp, err := proposeSettingScrubPenaltyEnabled(c, enabledStr == "true") + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingScrubPenaltyEnabled(c, enabledStr == "true", opts) apiutils.WriteResponse(w, resp, err) }) @@ -451,7 +557,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingBondReductionWindowStart(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingBondReductionWindowStart(c, val, opts) apiutils.WriteResponse(w, resp, err) }) @@ -471,7 +582,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSettingBondReductionWindowLength(c, val) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSettingBondReductionWindowLength(c, val, opts) apiutils.WriteResponse(w, resp, err) }) } diff --git a/rocketpool/api/odao/vote-proposal.go b/rocketpool/api/odao/vote-proposal.go index b22b06579..596309d21 100644 --- a/rocketpool/api/odao/vote-proposal.go +++ b/rocketpool/api/odao/vote-proposal.go @@ -3,6 +3,8 @@ package odao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao" "github.com/rocket-pool/smartnode/bindings/dao/trustednode" rptypes "github.com/rocket-pool/smartnode/bindings/types" @@ -111,16 +113,12 @@ func canVoteOnProposal(c *cli.Command, proposalId uint64) (*api.CanVoteOnTNDAOPr } -func voteOnProposal(c *cli.Command, proposalId uint64, support bool) (*api.VoteOnTNDAOProposalResponse, error) { +func voteOnProposal(c *cli.Command, proposalId uint64, support bool, opts *bind.TransactOpts) (*api.VoteOnTNDAOProposalResponse, error) { // Get services if err := services.RequireNodeTrusted(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -129,12 +127,6 @@ func voteOnProposal(c *cli.Command, proposalId uint64, support bool) (*api.VoteO // Response response := api.VoteOnTNDAOProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/claim-bonds.go b/rocketpool/api/pdao/claim-bonds.go index 228450038..da7cf6976 100644 --- a/rocketpool/api/pdao/claim-bonds.go +++ b/rocketpool/api/pdao/claim-bonds.go @@ -3,6 +3,8 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/bindings/types" @@ -104,7 +106,7 @@ func canClaimBonds(c *cli.Command, proposalId uint64, indices []uint64) (*api.PD return &response, nil } -func claimBonds(c *cli.Command, isProposer bool, proposalId uint64, indices []uint64) (*api.PDAOClaimBondsResponse, error) { +func claimBonds(c *cli.Command, isProposer bool, proposalId uint64, indices []uint64, opts *bind.TransactOpts) (*api.PDAOClaimBondsResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { return nil, err @@ -112,10 +114,6 @@ func claimBonds(c *cli.Command, isProposer bool, proposalId uint64, indices []ui if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -124,12 +122,6 @@ func claimBonds(c *cli.Command, isProposer bool, proposalId uint64, indices []ui // Response response := api.PDAOClaimBondsResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/defeat-proposal.go b/rocketpool/api/pdao/defeat-proposal.go index d3e6f601b..b562a8aee 100644 --- a/rocketpool/api/pdao/defeat-proposal.go +++ b/rocketpool/api/pdao/defeat-proposal.go @@ -4,6 +4,8 @@ import ( "fmt" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/types" "github.com/urfave/cli/v3" @@ -108,7 +110,7 @@ func canDefeatProposal(c *cli.Command, proposalId uint64, index uint64) (*api.PD return &response, nil } -func defeatProposal(c *cli.Command, proposalId uint64, index uint64) (*api.PDAODefeatProposalResponse, error) { +func defeatProposal(c *cli.Command, proposalId uint64, index uint64, opts *bind.TransactOpts) (*api.PDAODefeatProposalResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { return nil, err @@ -116,10 +118,6 @@ func defeatProposal(c *cli.Command, proposalId uint64, index uint64) (*api.PDAOD if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -128,12 +126,6 @@ func defeatProposal(c *cli.Command, proposalId uint64, index uint64) (*api.PDAOD // Response response := api.PDAODefeatProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/execute-proposal.go b/rocketpool/api/pdao/execute-proposal.go index 597db0881..77e56bdea 100644 --- a/rocketpool/api/pdao/execute-proposal.go +++ b/rocketpool/api/pdao/execute-proposal.go @@ -3,6 +3,8 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/protocol" rptypes "github.com/rocket-pool/smartnode/bindings/types" "github.com/urfave/cli/v3" @@ -79,7 +81,7 @@ func canExecuteProposal(c *cli.Command, proposalId uint64) (*api.CanExecutePDAOP } -func executeProposal(c *cli.Command, proposalId uint64) (*api.ExecutePDAOProposalResponse, error) { +func executeProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) (*api.ExecutePDAOProposalResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -88,10 +90,6 @@ func executeProposal(c *cli.Command, proposalId uint64) (*api.ExecutePDAOProposa if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -100,12 +98,6 @@ func executeProposal(c *cli.Command, proposalId uint64) (*api.ExecutePDAOProposa // Response response := api.ExecutePDAOProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/finalize-proposal.go b/rocketpool/api/pdao/finalize-proposal.go index 0ac0a805b..6a4054103 100644 --- a/rocketpool/api/pdao/finalize-proposal.go +++ b/rocketpool/api/pdao/finalize-proposal.go @@ -3,6 +3,8 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/types" "github.com/urfave/cli/v3" @@ -87,7 +89,7 @@ func canFinalizeProposal(c *cli.Command, proposalId uint64) (*api.PDAOCanFinaliz return &response, nil } -func finalizeProposal(c *cli.Command, proposalId uint64) (*api.PDAOFinalizeProposalResponse, error) { +func finalizeProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) (*api.PDAOFinalizeProposalResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { return nil, err @@ -95,10 +97,6 @@ func finalizeProposal(c *cli.Command, proposalId uint64) (*api.PDAOFinalizePropo if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -107,12 +105,6 @@ func finalizeProposal(c *cli.Command, proposalId uint64) (*api.PDAOFinalizePropo // Response response := api.PDAOFinalizeProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/invite-security.go b/rocketpool/api/pdao/invite-security.go index 99c8846c0..9b0ee6178 100644 --- a/rocketpool/api/pdao/invite-security.go +++ b/rocketpool/api/pdao/invite-security.go @@ -3,6 +3,7 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/dao/security" @@ -97,16 +98,12 @@ func canProposeInviteToSecurityCouncil(c *cli.Command, id string, address common return &response, nil } -func proposeInviteToSecurityCouncil(c *cli.Command, id string, address common.Address, blockNumber uint32) (*api.PDAOProposeInviteToSecurityCouncilResponse, error) { +func proposeInviteToSecurityCouncil(c *cli.Command, id string, address common.Address, blockNumber uint32, opts *bind.TransactOpts) (*api.PDAOProposeInviteToSecurityCouncilResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -120,11 +117,6 @@ func proposeInviteToSecurityCouncil(c *cli.Command, id string, address common.Ad response := api.PDAOProposeInviteToSecurityCouncilResponse{} // Get node account - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/kick-multi-security.go b/rocketpool/api/pdao/kick-multi-security.go index 85c78d51f..d2588affd 100644 --- a/rocketpool/api/pdao/kick-multi-security.go +++ b/rocketpool/api/pdao/kick-multi-security.go @@ -3,6 +3,7 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/shared/services" @@ -56,16 +57,12 @@ func canProposeKickMultiFromSecurityCouncil(c *cli.Command, addresses []common.A return &response, nil } -func proposeKickMultiFromSecurityCouncil(c *cli.Command, addresses []common.Address, blockNumber uint32) (*api.PDAOProposeKickMultiFromSecurityCouncilResponse, error) { +func proposeKickMultiFromSecurityCouncil(c *cli.Command, addresses []common.Address, blockNumber uint32, opts *bind.TransactOpts) (*api.PDAOProposeKickMultiFromSecurityCouncilResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -79,11 +76,6 @@ func proposeKickMultiFromSecurityCouncil(c *cli.Command, addresses []common.Addr response := api.PDAOProposeKickMultiFromSecurityCouncilResponse{} // Get node account - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/kick-security.go b/rocketpool/api/pdao/kick-security.go index e846b4afa..9e33ad736 100644 --- a/rocketpool/api/pdao/kick-security.go +++ b/rocketpool/api/pdao/kick-security.go @@ -3,6 +3,7 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/node" @@ -81,16 +82,12 @@ func canProposeKickFromSecurityCouncil(c *cli.Command, address common.Address) ( return &response, nil } -func proposeKickFromSecurityCouncil(c *cli.Command, address common.Address, blockNumber uint32) (*api.PDAOProposeKickFromSecurityCouncilResponse, error) { +func proposeKickFromSecurityCouncil(c *cli.Command, address common.Address, blockNumber uint32, opts *bind.TransactOpts) (*api.PDAOProposeKickFromSecurityCouncilResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -104,11 +101,6 @@ func proposeKickFromSecurityCouncil(c *cli.Command, address common.Address, bloc response := api.PDAOProposeKickFromSecurityCouncilResponse{} // Get node account - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/one-time-spend.go b/rocketpool/api/pdao/one-time-spend.go index 5eaac52a1..898f29260 100644 --- a/rocketpool/api/pdao/one-time-spend.go +++ b/rocketpool/api/pdao/one-time-spend.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/node" @@ -81,16 +82,12 @@ func canProposeOneTimeSpend(c *cli.Command, invoiceID string, recipient common.A return &response, nil } -func proposeOneTimeSpend(c *cli.Command, invoiceID string, recipient common.Address, amount *big.Int, blockNumber uint32, customMessage string) (*api.PDAOProposeOneTimeSpendResponse, error) { +func proposeOneTimeSpend(c *cli.Command, invoiceID string, recipient common.Address, amount *big.Int, blockNumber uint32, customMessage string, opts *bind.TransactOpts) (*api.PDAOProposeOneTimeSpendResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -104,11 +101,6 @@ func proposeOneTimeSpend(c *cli.Command, invoiceID string, recipient common.Addr response := api.PDAOProposeOneTimeSpendResponse{} // Get node account - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/override-vote.go b/rocketpool/api/pdao/override-vote.go index 6d73ffb78..3c757ebce 100644 --- a/rocketpool/api/pdao/override-vote.go +++ b/rocketpool/api/pdao/override-vote.go @@ -3,6 +3,7 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/network" @@ -106,12 +107,8 @@ func canOverrideVote(c *cli.Command, proposalId uint64, voteDirection types.Vote return &response, nil } -func overrideVote(c *cli.Command, proposalId uint64, voteDirection types.VoteDirection) (*api.VoteOnPDAOProposalResponse, error) { +func overrideVote(c *cli.Command, proposalId uint64, voteDirection types.VoteDirection, opts *bind.TransactOpts) (*api.VoteOnPDAOProposalResponse, error) { // Get services - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -120,12 +117,6 @@ func overrideVote(c *cli.Command, proposalId uint64, voteDirection types.VoteDir // Response response := api.VoteOnPDAOProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/percentages.go b/rocketpool/api/pdao/percentages.go index a35c621ec..00cbd6115 100644 --- a/rocketpool/api/pdao/percentages.go +++ b/rocketpool/api/pdao/percentages.go @@ -4,6 +4,8 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/protocol" rpnode "github.com/rocket-pool/smartnode/bindings/node" psettings "github.com/rocket-pool/smartnode/bindings/settings/protocol" @@ -125,7 +127,7 @@ func canProposeRewardsPercentages(c *cli.Command, node *big.Int, odao *big.Int, return &response, nil } -func proposeRewardsPercentages(c *cli.Command, node *big.Int, odao *big.Int, pdao *big.Int, blockNumber uint32) (*api.PDAOProposeRewardsPercentagesResponse, error) { +func proposeRewardsPercentages(c *cli.Command, node *big.Int, odao *big.Int, pdao *big.Int, blockNumber uint32, opts *bind.TransactOpts) (*api.PDAOProposeRewardsPercentagesResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { return nil, err @@ -137,10 +139,6 @@ func proposeRewardsPercentages(c *cli.Command, node *big.Int, odao *big.Int, pda if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -154,11 +152,6 @@ func proposeRewardsPercentages(c *cli.Command, node *big.Int, odao *big.Int, pda response := api.PDAOProposeRewardsPercentagesResponse{} // Get the account transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Decode the pollard pollard, err := getPollard(rp, cfg, bc, blockNumber) if err != nil { diff --git a/rocketpool/api/pdao/propose-settings.go b/rocketpool/api/pdao/propose-settings.go index 76b65e5b2..c095e0079 100644 --- a/rocketpool/api/pdao/propose-settings.go +++ b/rocketpool/api/pdao/propose-settings.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" protocol131 "github.com/rocket-pool/smartnode/bindings/legacy/v1.3.1/protocol" @@ -939,7 +940,7 @@ func canProposeSetting(c *cli.Command, contractName string, settingName string, } -func proposeSetting(c *cli.Command, contractName string, settingName string, value string, blockNumber uint32) (*api.ProposePDAOSettingResponse, error) { +func proposeSetting(c *cli.Command, contractName string, settingName string, value string, blockNumber uint32, opts *bind.TransactOpts) (*api.ProposePDAOSettingResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -952,10 +953,6 @@ func proposeSetting(c *cli.Command, contractName string, settingName string, val if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -974,12 +971,6 @@ func proposeSetting(c *cli.Command, contractName string, settingName string, val return nil, fmt.Errorf("error regenerating pollard: %w", err) } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/recurring-spend.go b/rocketpool/api/pdao/recurring-spend.go index 7138a8ce6..5be04f4e3 100644 --- a/rocketpool/api/pdao/recurring-spend.go +++ b/rocketpool/api/pdao/recurring-spend.go @@ -5,6 +5,7 @@ import ( "math/big" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/node" @@ -82,16 +83,12 @@ func canProposeRecurringSpend(c *cli.Command, contractName string, recipient com return &response, nil } -func proposeRecurringSpend(c *cli.Command, contractName string, recipient common.Address, amountPerPeriod *big.Int, periodLength time.Duration, startTime time.Time, numberOfPeriods uint64, blockNumber uint32, customMessage string) (*api.PDAOProposeOneTimeSpendResponse, error) { +func proposeRecurringSpend(c *cli.Command, contractName string, recipient common.Address, amountPerPeriod *big.Int, periodLength time.Duration, startTime time.Time, numberOfPeriods uint64, blockNumber uint32, customMessage string, opts *bind.TransactOpts) (*api.PDAOProposeOneTimeSpendResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -105,11 +102,6 @@ func proposeRecurringSpend(c *cli.Command, contractName string, recipient common response := api.PDAOProposeOneTimeSpendResponse{} // Get node account - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/replace-security.go b/rocketpool/api/pdao/replace-security.go index 68b492b40..72a4aca42 100644 --- a/rocketpool/api/pdao/replace-security.go +++ b/rocketpool/api/pdao/replace-security.go @@ -3,6 +3,7 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/dao/security" @@ -88,16 +89,12 @@ func canProposeReplaceMemberOfSecurityCouncil(c *cli.Command, existingMemberAddr return &response, nil } -func proposeReplaceMemberOfSecurityCouncil(c *cli.Command, existingMemberAddress common.Address, newMemberID string, newMemberAddress common.Address, blockNumber uint32) (*api.PDAOProposeReplaceMemberOfSecurityCouncilResponse, error) { +func proposeReplaceMemberOfSecurityCouncil(c *cli.Command, existingMemberAddress common.Address, newMemberID string, newMemberAddress common.Address, blockNumber uint32, opts *bind.TransactOpts) (*api.PDAOProposeReplaceMemberOfSecurityCouncilResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -111,11 +108,6 @@ func proposeReplaceMemberOfSecurityCouncil(c *cli.Command, existingMemberAddress response := api.PDAOProposeReplaceMemberOfSecurityCouncilResponse{} // Get node account - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Get the existing member existingID, err := security.GetMemberID(rp, existingMemberAddress, nil) if err != nil { diff --git a/rocketpool/api/pdao/routes.go b/rocketpool/api/pdao/routes.go index 893a6a0b3..ae09560fd 100644 --- a/rocketpool/api/pdao/routes.go +++ b/rocketpool/api/pdao/routes.go @@ -12,6 +12,7 @@ import ( "github.com/urfave/cli/v3" bindtypes "github.com/rocket-pool/smartnode/bindings/types" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" ) @@ -54,7 +55,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := voteOnProposal(c, id, voteDir) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := voteOnProposal(c, id, voteDir, opts) apiutils.WriteResponse(w, resp, err) }) @@ -74,7 +80,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := overrideVote(c, id, voteDir) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := overrideVote(c, id, voteDir, opts) apiutils.WriteResponse(w, resp, err) }) @@ -94,7 +105,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := executeProposal(c, id) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := executeProposal(c, id, opts) apiutils.WriteResponse(w, resp, err) }) @@ -120,7 +136,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeSetting(c, contract, setting, value, blockNumber) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSetting(c, contract, setting, value, blockNumber, opts) apiutils.WriteResponse(w, resp, err) }) @@ -150,7 +171,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeRewardsPercentages(c, node, odaoAmt, pdaoAmt, blockNumber) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeRewardsPercentages(c, node, odaoAmt, pdaoAmt, blockNumber, opts) apiutils.WriteResponse(w, resp, err) }) @@ -175,7 +201,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeOneTimeSpend(c, invoiceID, recipient, amount, blockNumber, customMessage) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeOneTimeSpend(c, invoiceID, recipient, amount, blockNumber, customMessage, opts) apiutils.WriteResponse(w, resp, err) }) @@ -200,7 +231,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeRecurringSpend(c, contractName, recipient, amountPerPeriod, periodLength, startTime, numberOfPeriods, blockNumber, customMessage) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeRecurringSpend(c, contractName, recipient, amountPerPeriod, periodLength, startTime, numberOfPeriods, blockNumber, customMessage, opts) apiutils.WriteResponse(w, resp, err) }) @@ -225,7 +261,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeRecurringSpendUpdate(c, contractName, recipient, amountPerPeriod, periodLength, numberOfPeriods, blockNumber, customMessage) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeRecurringSpendUpdate(c, contractName, recipient, amountPerPeriod, periodLength, numberOfPeriods, blockNumber, customMessage, opts) apiutils.WriteResponse(w, resp, err) }) @@ -244,7 +285,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeInviteToSecurityCouncil(c, id, addr, blockNumber) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeInviteToSecurityCouncil(c, id, addr, blockNumber, opts) apiutils.WriteResponse(w, resp, err) }) @@ -261,7 +307,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeKickFromSecurityCouncil(c, addr, blockNumber) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeKickFromSecurityCouncil(c, addr, blockNumber, opts) apiutils.WriteResponse(w, resp, err) }) @@ -286,7 +337,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeKickMultiFromSecurityCouncil(c, addresses, blockNumber) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeKickMultiFromSecurityCouncil(c, addresses, blockNumber, opts) apiutils.WriteResponse(w, resp, err) }) @@ -307,7 +363,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeReplaceMemberOfSecurityCouncil(c, existing, newID, newAddr, blockNumber) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeReplaceMemberOfSecurityCouncil(c, existing, newID, newAddr, blockNumber, opts) apiutils.WriteResponse(w, resp, err) }) @@ -333,7 +394,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { return } isProposer := paramVal(r, "isProposer") == "true" - resp, err := claimBonds(c, isProposer, proposalID, indices) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := claimBonds(c, isProposer, proposalID, indices, opts) apiutils.WriteResponse(w, resp, err) }) @@ -363,7 +429,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := defeatProposal(c, id, index) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := defeatProposal(c, id, index, opts) apiutils.WriteResponse(w, resp, err) }) @@ -383,7 +454,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := finalizeProposal(c, id) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := finalizeProposal(c, id, opts) apiutils.WriteResponse(w, resp, err) }) @@ -395,7 +471,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/pdao/set-voting-delegate", func(w http.ResponseWriter, r *http.Request) { addr := common.HexToAddress(paramVal(r, "address")) - resp, err := setVotingDelegate(c, addr) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setVotingDelegate(c, addr, opts) apiutils.WriteResponse(w, resp, err) }) @@ -414,7 +495,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { mux.HandleFunc("/api/pdao/set-signalling-address", func(w http.ResponseWriter, r *http.Request) { addr := common.HexToAddress(paramVal(r, "address")) sig := paramVal(r, "signature") - resp, err := setSignallingAddress(c, addr, sig) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setSignallingAddress(c, addr, sig, opts) apiutils.WriteResponse(w, resp, err) }) @@ -424,7 +510,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/pdao/clear-signalling-address", func(w http.ResponseWriter, r *http.Request) { - resp, err := clearSignallingAddress(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := clearSignallingAddress(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -450,7 +541,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := proposeAllowListedControllers(c, addresses, blockNumber) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeAllowListedControllers(c, addresses, blockNumber, opts) apiutils.WriteResponse(w, resp, err) }) } diff --git a/rocketpool/api/pdao/set-allow-list.go b/rocketpool/api/pdao/set-allow-list.go index dde59a23a..c89e44812 100644 --- a/rocketpool/api/pdao/set-allow-list.go +++ b/rocketpool/api/pdao/set-allow-list.go @@ -3,6 +3,7 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/bindings/settings/protocol" @@ -80,16 +81,12 @@ func canProposeAllowListedControllers(c *cli.Command, addressList []common.Addre return &response, nil } -func proposeAllowListedControllers(c *cli.Command, addressList []common.Address, blockNumber uint32) (*api.PDAOProposeAllowListedControllersResponse, error) { +func proposeAllowListedControllers(c *cli.Command, addressList []common.Address, blockNumber uint32, opts *bind.TransactOpts) (*api.PDAOProposeAllowListedControllersResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -103,11 +100,6 @@ func proposeAllowListedControllers(c *cli.Command, addressList []common.Address, response := api.PDAOProposeAllowListedControllersResponse{} // Get node account - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/set-snapshot-address.go b/rocketpool/api/pdao/set-snapshot-address.go index 44809fa92..69b026605 100644 --- a/rocketpool/api/pdao/set-snapshot-address.go +++ b/rocketpool/api/pdao/set-snapshot-address.go @@ -107,16 +107,12 @@ func canSetSignallingAddress(c *cli.Command, signallingAddress common.Address, s return &response, nil } -func setSignallingAddress(c *cli.Command, signallingAddress common.Address, signature string) (*api.PDAOSetSignallingAddressResponse, error) { +func setSignallingAddress(c *cli.Command, signallingAddress common.Address, signature string, opts *bind.TransactOpts) (*api.PDAOSetSignallingAddressResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } cfg, err := services.GetConfig(c) if err != nil { return nil, err @@ -138,12 +134,6 @@ func setSignallingAddress(c *cli.Command, signallingAddress common.Address, sign fmt.Println("Error parsing signature", err) } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { @@ -243,15 +233,11 @@ func canClearSignallingAddress(c *cli.Command) (*api.PDAOCanClearSignallingAddre return &response, nil } -func clearSignallingAddress(c *cli.Command) (*api.PDAOClearSignallingAddressResponse, error) { +func clearSignallingAddress(c *cli.Command, opts *bind.TransactOpts) (*api.PDAOClearSignallingAddressResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } cfg, err := services.GetConfig(c) if err != nil { return nil, err @@ -266,12 +252,6 @@ func clearSignallingAddress(c *cli.Command) (*api.PDAOClearSignallingAddressResp response := api.PDAOClearSignallingAddressResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/update-recurring-spend.go b/rocketpool/api/pdao/update-recurring-spend.go index 60150ce9c..69dcc3192 100644 --- a/rocketpool/api/pdao/update-recurring-spend.go +++ b/rocketpool/api/pdao/update-recurring-spend.go @@ -5,6 +5,7 @@ import ( "math/big" "time" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/node" @@ -82,16 +83,12 @@ func canProposeRecurringSpendUpdate(c *cli.Command, contractName string, recipie return &response, nil } -func proposeRecurringSpendUpdate(c *cli.Command, contractName string, recipient common.Address, amountPerPeriod *big.Int, periodLength time.Duration, numberOfPeriods uint64, blockNumber uint32, customMessage string) (*api.PDAOProposeOneTimeSpendResponse, error) { +func proposeRecurringSpendUpdate(c *cli.Command, contractName string, recipient common.Address, amountPerPeriod *big.Int, periodLength time.Duration, numberOfPeriods uint64, blockNumber uint32, customMessage string, opts *bind.TransactOpts) (*api.PDAOProposeOneTimeSpendResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -105,11 +102,6 @@ func proposeRecurringSpendUpdate(c *cli.Command, contractName string, recipient response := api.PDAOProposeOneTimeSpendResponse{} // Get node account - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/pdao/vote-proposal.go b/rocketpool/api/pdao/vote-proposal.go index e08b30f65..6d5496450 100644 --- a/rocketpool/api/pdao/vote-proposal.go +++ b/rocketpool/api/pdao/vote-proposal.go @@ -3,6 +3,7 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/bindings/types" @@ -120,7 +121,7 @@ func canVoteOnProposal(c *cli.Command, proposalId uint64, voteDirection types.Vo return &response, nil } -func voteOnProposal(c *cli.Command, proposalId uint64, voteDirection types.VoteDirection) (*api.VoteOnPDAOProposalResponse, error) { +func voteOnProposal(c *cli.Command, proposalId uint64, voteDirection types.VoteDirection, opts *bind.TransactOpts) (*api.VoteOnPDAOProposalResponse, error) { // Get services cfg, err := services.GetConfig(c) if err != nil { @@ -148,12 +149,6 @@ func voteOnProposal(c *cli.Command, proposalId uint64, voteDirection types.VoteD return nil, err } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Get the block used by the proposal proposalBlock, err := protocol.GetProposalBlock(rp, proposalId, nil) if err != nil { diff --git a/rocketpool/api/pdao/voting.go b/rocketpool/api/pdao/voting.go index 50eddf953..e308e06b6 100644 --- a/rocketpool/api/pdao/voting.go +++ b/rocketpool/api/pdao/voting.go @@ -3,6 +3,7 @@ package pdao import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" @@ -48,7 +49,7 @@ func estimateSetVotingDelegateGas(c *cli.Command, address common.Address) (*api. } -func setVotingDelegate(c *cli.Command, address common.Address) (*api.PDAOSetVotingDelegateResponse, error) { +func setVotingDelegate(c *cli.Command, address common.Address, opts *bind.TransactOpts) (*api.PDAOSetVotingDelegateResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -58,20 +59,9 @@ func setVotingDelegate(c *cli.Command, address common.Address) (*api.PDAOSetVoti if err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } - // Response response := api.PDAOSetVotingDelegateResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/queue/assign-deposits.go b/rocketpool/api/queue/assign-deposits.go index 3344ee622..4541df2c2 100644 --- a/rocketpool/api/queue/assign-deposits.go +++ b/rocketpool/api/queue/assign-deposits.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/deposit" "github.com/rocket-pool/smartnode/bindings/settings/protocol" "github.com/urfave/cli/v3" @@ -70,7 +71,7 @@ func canAssignDeposits(c *cli.Command, max int64) (*api.CanAssignDepositsRespons } -func assignDeposits(c *cli.Command, max int64) (*api.AssignDepositsResponse, error) { +func assignDeposits(c *cli.Command, max int64, opts *bind.TransactOpts) (*api.AssignDepositsResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -79,10 +80,6 @@ func assignDeposits(c *cli.Command, max int64) (*api.AssignDepositsResponse, err if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -91,12 +88,6 @@ func assignDeposits(c *cli.Command, max int64) (*api.AssignDepositsResponse, err // Response response := api.AssignDepositsResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/queue/process.go b/rocketpool/api/queue/process.go index a37690101..565256ebe 100644 --- a/rocketpool/api/queue/process.go +++ b/rocketpool/api/queue/process.go @@ -4,6 +4,7 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/deposit" "github.com/rocket-pool/smartnode/bindings/settings/protocol" "github.com/urfave/cli/v3" @@ -71,7 +72,7 @@ func canProcessQueue(c *cli.Command, max int64) (*api.CanProcessQueueResponse, e } -func processQueue(c *cli.Command, max int64) (*api.ProcessQueueResponse, error) { +func processQueue(c *cli.Command, max int64, opts *bind.TransactOpts) (*api.ProcessQueueResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -80,10 +81,6 @@ func processQueue(c *cli.Command, max int64) (*api.ProcessQueueResponse, error) if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -92,12 +89,6 @@ func processQueue(c *cli.Command, max int64) (*api.ProcessQueueResponse, error) // Response response := api.ProcessQueueResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/queue/routes.go b/rocketpool/api/queue/routes.go index 40e2c7a5c..2a0e662d9 100644 --- a/rocketpool/api/queue/routes.go +++ b/rocketpool/api/queue/routes.go @@ -6,6 +6,7 @@ import ( "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) @@ -32,7 +33,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := processQueue(c, int64(max)) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := processQueue(c, int64(max), opts) apiutils.WriteResponse(w, resp, err) }) @@ -57,7 +63,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := assignDeposits(c, int64(max)) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := assignDeposits(c, int64(max), opts) apiutils.WriteResponse(w, resp, err) }) } diff --git a/rocketpool/api/security/cancel-proposal.go b/rocketpool/api/security/cancel-proposal.go index 166bbadcf..2f6275fc4 100644 --- a/rocketpool/api/security/cancel-proposal.go +++ b/rocketpool/api/security/cancel-proposal.go @@ -4,6 +4,8 @@ import ( "bytes" "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao" "github.com/rocket-pool/smartnode/bindings/dao/security" rptypes "github.com/rocket-pool/smartnode/bindings/types" @@ -91,16 +93,12 @@ func canCancelProposal(c *cli.Command, proposalId uint64) (*api.SecurityCanCance } -func cancelProposal(c *cli.Command, proposalId uint64) (*api.SecurityCancelProposalResponse, error) { +func cancelProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) (*api.SecurityCancelProposalResponse, error) { // Get services if err := services.RequireNodeSecurityMember(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -109,12 +107,6 @@ func cancelProposal(c *cli.Command, proposalId uint64) (*api.SecurityCancelPropo // Response response := api.SecurityCancelProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/security/execute-proposal.go b/rocketpool/api/security/execute-proposal.go index 6a5194603..bd19ca5dd 100644 --- a/rocketpool/api/security/execute-proposal.go +++ b/rocketpool/api/security/execute-proposal.go @@ -3,6 +3,8 @@ package security import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao" "github.com/rocket-pool/smartnode/bindings/dao/security" rptypes "github.com/rocket-pool/smartnode/bindings/types" @@ -80,7 +82,7 @@ func canExecuteProposal(c *cli.Command, proposalId uint64) (*api.SecurityCanExec } -func executeProposal(c *cli.Command, proposalId uint64) (*api.SecurityExecuteProposalResponse, error) { +func executeProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) (*api.SecurityExecuteProposalResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -89,10 +91,6 @@ func executeProposal(c *cli.Command, proposalId uint64) (*api.SecurityExecutePro if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -101,12 +99,6 @@ func executeProposal(c *cli.Command, proposalId uint64) (*api.SecurityExecutePro // Response response := api.SecurityExecuteProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/security/join.go b/rocketpool/api/security/join.go index 6e785a008..58e09896b 100644 --- a/rocketpool/api/security/join.go +++ b/rocketpool/api/security/join.go @@ -3,6 +3,8 @@ package security import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/security" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -80,16 +82,12 @@ func canJoin(c *cli.Command) (*api.SecurityCanJoinResponse, error) { } -func join(c *cli.Command) (*api.SecurityJoinResponse, error) { +func join(c *cli.Command, opts *bind.TransactOpts) (*api.SecurityJoinResponse, error) { // Get services if err := services.RequireNodeRegistered(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -99,10 +97,6 @@ func join(c *cli.Command) (*api.SecurityJoinResponse, error) { response := api.SecurityJoinResponse{} // Join - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } err = eth1.CheckForNonceOverride(c, opts) if err != nil { return nil, fmt.Errorf("Error checking for nonce override: %w", err) diff --git a/rocketpool/api/security/leave.go b/rocketpool/api/security/leave.go index 3ce339ba8..920b1d45c 100644 --- a/rocketpool/api/security/leave.go +++ b/rocketpool/api/security/leave.go @@ -3,6 +3,8 @@ package security import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/security" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" @@ -70,16 +72,12 @@ func canLeave(c *cli.Command) (*api.SecurityCanLeaveResponse, error) { } -func leave(c *cli.Command) (*api.SecurityLeaveResponse, error) { +func leave(c *cli.Command, opts *bind.TransactOpts) (*api.SecurityLeaveResponse, error) { // Get services if err := services.RequireNodeSecurityMember(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -88,12 +86,6 @@ func leave(c *cli.Command) (*api.SecurityLeaveResponse, error) { // Response response := api.SecurityLeaveResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/security/propose-leave.go b/rocketpool/api/security/propose-leave.go index 35d5c2c34..fcbe5076d 100644 --- a/rocketpool/api/security/propose-leave.go +++ b/rocketpool/api/security/propose-leave.go @@ -3,6 +3,8 @@ package security import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/security" "github.com/urfave/cli/v3" @@ -64,16 +66,12 @@ func canProposeLeave(c *cli.Command) (*api.SecurityCanProposeLeaveResponse, erro } -func proposeLeave(c *cli.Command) (*api.SecurityProposeLeaveResponse, error) { +func proposeLeave(c *cli.Command, opts *bind.TransactOpts) (*api.SecurityProposeLeaveResponse, error) { // Get services if err := services.RequireNodeSecurityMember(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -82,12 +80,6 @@ func proposeLeave(c *cli.Command) (*api.SecurityProposeLeaveResponse, error) { // Response response := api.SecurityProposeLeaveResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/security/propose-settings.go b/rocketpool/api/security/propose-settings.go index 405aeb7e8..ed9c31bf4 100644 --- a/rocketpool/api/security/propose-settings.go +++ b/rocketpool/api/security/propose-settings.go @@ -3,6 +3,7 @@ package security import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/bindings/settings/protocol" @@ -215,7 +216,7 @@ func canProposeSetting(c *cli.Command, contractName string, settingName string, } -func proposeSetting(c *cli.Command, contractName string, settingName string, value string) (*api.ProposePDAOSettingResponse, error) { +func proposeSetting(c *cli.Command, contractName string, settingName string, value string, opts *bind.TransactOpts) (*api.ProposePDAOSettingResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -224,10 +225,6 @@ func proposeSetting(c *cli.Command, contractName string, settingName string, val if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -236,12 +233,6 @@ func proposeSetting(c *cli.Command, contractName string, settingName string, val // Response response := api.ProposePDAOSettingResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/security/routes.go b/rocketpool/api/security/routes.go index c217c18e7..2446a17ef 100644 --- a/rocketpool/api/security/routes.go +++ b/rocketpool/api/security/routes.go @@ -6,6 +6,7 @@ import ( "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) @@ -42,7 +43,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/security/propose-leave", func(w http.ResponseWriter, r *http.Request) { - resp, err := proposeLeave(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeLeave(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -58,7 +64,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { contractName := r.FormValue("contractName") settingName := r.FormValue("settingName") value := r.FormValue("value") - resp, err := proposeSetting(c, contractName, settingName, value) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := proposeSetting(c, contractName, settingName, value, opts) apiutils.WriteResponse(w, resp, err) }) @@ -78,7 +89,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := cancelProposal(c, id) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := cancelProposal(c, id, opts) apiutils.WriteResponse(w, resp, err) }) @@ -99,7 +115,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { return } support := r.FormValue("support") == "true" - resp, err := voteOnProposal(c, id, support) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := voteOnProposal(c, id, support, opts) apiutils.WriteResponse(w, resp, err) }) @@ -119,7 +140,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteErrorResponse(w, err) return } - resp, err := executeProposal(c, id) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := executeProposal(c, id, opts) apiutils.WriteResponse(w, resp, err) }) @@ -129,7 +155,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/security/join", func(w http.ResponseWriter, r *http.Request) { - resp, err := join(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := join(c, opts) apiutils.WriteResponse(w, resp, err) }) @@ -139,7 +170,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { }) mux.HandleFunc("/api/security/leave", func(w http.ResponseWriter, r *http.Request) { - resp, err := leave(c) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := leave(c, opts) apiutils.WriteResponse(w, resp, err) }) } diff --git a/rocketpool/api/security/vote-proposal.go b/rocketpool/api/security/vote-proposal.go index 21fa354e2..45407f74e 100644 --- a/rocketpool/api/security/vote-proposal.go +++ b/rocketpool/api/security/vote-proposal.go @@ -3,6 +3,8 @@ package security import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao" "github.com/rocket-pool/smartnode/bindings/dao/security" rptypes "github.com/rocket-pool/smartnode/bindings/types" @@ -111,16 +113,12 @@ func canVoteOnProposal(c *cli.Command, proposalId uint64) (*api.SecurityCanVoteO } -func voteOnProposal(c *cli.Command, proposalId uint64, support bool) (*api.SecurityVoteOnProposalResponse, error) { +func voteOnProposal(c *cli.Command, proposalId uint64, support bool, opts *bind.TransactOpts) (*api.SecurityVoteOnProposalResponse, error) { // Get services if err := services.RequireNodeSecurityMember(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -129,12 +127,6 @@ func voteOnProposal(c *cli.Command, proposalId uint64, support bool) (*api.Secur // Response response := api.SecurityVoteOnProposalResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/upgrade/execute-upgrade.go b/rocketpool/api/upgrade/execute-upgrade.go index 8c745e0b5..98d1ec82f 100644 --- a/rocketpool/api/upgrade/execute-upgrade.go +++ b/rocketpool/api/upgrade/execute-upgrade.go @@ -3,6 +3,8 @@ package upgrade import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/rocket-pool/smartnode/bindings/dao/trustednode" "github.com/rocket-pool/smartnode/bindings/dao/upgrades" rptypes "github.com/rocket-pool/smartnode/bindings/types" @@ -94,7 +96,7 @@ func canExecuteUpgrade(c *cli.Command, upgradeProposalId uint64) (*api.CanExecut } -func executeUpgrade(c *cli.Command, upgradeProposalId uint64) (*api.ExecuteTNDAOUpgradeResponse, error) { +func executeUpgrade(c *cli.Command, upgradeProposalId uint64, opts *bind.TransactOpts) (*api.ExecuteTNDAOUpgradeResponse, error) { // Get services if err := services.RequireNodeWallet(c); err != nil { @@ -103,10 +105,6 @@ func executeUpgrade(c *cli.Command, upgradeProposalId uint64) (*api.ExecuteTNDAO if err := services.RequireRocketStorage(c); err != nil { return nil, err } - w, err := services.GetWallet(c) - if err != nil { - return nil, err - } rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -115,12 +113,6 @@ func executeUpgrade(c *cli.Command, upgradeProposalId uint64) (*api.ExecuteTNDAO // Response response := api.ExecuteTNDAOUpgradeResponse{} - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // Override the provided pending TX if requested err = eth1.CheckForNonceOverride(c, opts) if err != nil { diff --git a/rocketpool/api/upgrade/routes.go b/rocketpool/api/upgrade/routes.go index 9c19a2626..4eb0912ce 100644 --- a/rocketpool/api/upgrade/routes.go +++ b/rocketpool/api/upgrade/routes.go @@ -6,6 +6,7 @@ import ( "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" ) @@ -33,7 +34,12 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiutils.WriteResponse(w, nil, err) return } - resp, err := executeUpgrade(c, id) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := executeUpgrade(c, id, opts) apiutils.WriteResponse(w, resp, err) }) } diff --git a/rocketpool/api/wallet/ens-name.go b/rocketpool/api/wallet/ens-name.go index a36fb0308..6dc147ca7 100644 --- a/rocketpool/api/wallet/ens-name.go +++ b/rocketpool/api/wallet/ens-name.go @@ -3,6 +3,7 @@ package wallet import ( "fmt" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" @@ -16,7 +17,7 @@ const ( ) // Set a name to the node wallet's ENS reverse record. -func setEnsName(c *cli.Command, name string, onlyEstimateGas bool) (*api.SetEnsNameResponse, error) { +func setEnsName(c *cli.Command, name string, onlyEstimateGas bool, opts *bind.TransactOpts) (*api.SetEnsNameResponse, error) { rp, err := services.GetRocketPool(c) if err != nil { return nil, err @@ -54,12 +55,6 @@ func setEnsName(c *cli.Command, name string, onlyEstimateGas bool) (*api.SetEnsN return nil, fmt.Errorf("error: the ENS record already points to the name '%s'", name) } - // Get transactor - opts, err := w.GetNodeAccountTransactor() - if err != nil { - return nil, err - } - // If onlyEstimateGas is set, then don't send the tx, only simulates and returns the gas estimate opts.NoSend = onlyEstimateGas diff --git a/rocketpool/api/wallet/routes.go b/rocketpool/api/wallet/routes.go index d99ab0650..3d8059935 100644 --- a/rocketpool/api/wallet/routes.go +++ b/rocketpool/api/wallet/routes.go @@ -7,6 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" + "github.com/rocket-pool/smartnode/shared/services" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) @@ -92,13 +93,23 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { if name == "" { name = r.FormValue("name") } - resp, err := setEnsName(c, name, true) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setEnsName(c, name, true, opts) apiutils.WriteResponse(w, resp, err) }) mux.HandleFunc("/api/wallet/set-ens-name", func(w http.ResponseWriter, r *http.Request) { name := r.FormValue("name") - resp, err := setEnsName(c, name, false) + opts, err := services.GetNodeAccountTransactorFromRequest(c, r) + if err != nil { + apiutils.WriteErrorResponse(w, err) + return + } + resp, err := setEnsName(c, name, false, opts) apiutils.WriteResponse(w, resp, err) }) } diff --git a/shared/services/gas/gas.go b/shared/services/gas/gas.go index 146f06094..b90340be5 100644 --- a/shared/services/gas/gas.go +++ b/shared/services/gas/gas.go @@ -180,7 +180,7 @@ func GetHeadlessMaxFeeWeiWithLatestBlock(cfg *config.RocketPoolConfig, rp *rocke func handleEtherscanGasPrices(gasSuggestion etherscan.GasFeeSuggestion, gasInfo rocketpool.GasInfo, priorityFee float64, gasLimit uint64) float64 { fastGwei := gasSuggestion.FastGwei + priorityFee - fastEth := gasSuggestion.FastGwei / eth.WeiPerGwei + fastEth := fastGwei / eth.WeiPerGwei var fastLowLimit float64 var fastHighLimit float64 @@ -193,7 +193,7 @@ func handleEtherscanGasPrices(gasSuggestion etherscan.GasFeeSuggestion, gasInfo } standardGwei := gasSuggestion.StandardGwei + priorityFee - standardEth := gasSuggestion.StandardGwei / eth.WeiPerGwei + standardEth := standardGwei / eth.WeiPerGwei var standardLowLimit float64 var standardHighLimit float64 @@ -206,7 +206,7 @@ func handleEtherscanGasPrices(gasSuggestion etherscan.GasFeeSuggestion, gasInfo } slowGwei := gasSuggestion.SlowGwei + priorityFee - slowEth := gasSuggestion.SlowGwei / eth.WeiPerGwei + slowEth := slowGwei / eth.WeiPerGwei var slowLowLimit float64 var slowHighLimit float64 @@ -229,7 +229,7 @@ func handleEtherscanGasPrices(gasSuggestion etherscan.GasFeeSuggestion, gasInfo color.LightBluePrintln("+====================================================+") fmt.Println() - fmt.Printf("These prices include a maximum priority fee of %.3f gwei.\n", priorityFee) + fmt.Printf("These prices include a maximum priority fee of %.4f gwei.\n", priorityFee) for { desiredPrice := prompt.Prompt( diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index 85999cd23..71e3c112b 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -16,6 +16,7 @@ import ( "os/exec" "path/filepath" "slices" + "strconv" "strings" "sync" "time" @@ -1279,6 +1280,19 @@ func (c *Client) callHTTPAPICtx(ctx context.Context, method, path string, params } req, err = http.NewRequestWithContext(ctx, http.MethodGet, target, nil) case http.MethodPost: + if params == nil { + params = url.Values{} + } + // Propagate the gas settings + if c.globals.MaxFee > 0 { + params.Set("maxFee", strconv.FormatFloat(c.globals.MaxFee, 'f', -1, 64)) + } + if c.globals.MaxPrioFee > 0 { + params.Set("maxPrioFee", strconv.FormatFloat(c.globals.MaxPrioFee, 'f', -1, 64)) + } + if c.globals.GasLimit > 0 { + params.Set("gasLimit", strconv.FormatFloat(float64(c.globals.GasLimit), 'f', 0, 64)) + } body := []byte(params.Encode()) req, err = http.NewRequestWithContext(ctx, http.MethodPost, target, bytes.NewReader(body)) if err == nil { diff --git a/shared/services/services.go b/shared/services/services.go index 365d5e8d9..77a79d034 100644 --- a/shared/services/services.go +++ b/shared/services/services.go @@ -3,11 +3,14 @@ package services import ( "fmt" "math/big" + "net/http" "os" "path/filepath" + "strconv" "sync" "github.com/docker/docker/client" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/rocket-pool/smartnode/bindings/rocketpool" @@ -86,6 +89,39 @@ func GetWallet(c *cli.Command) (wallet.Wallet, error) { return getWallet(c, cfg, pm, am, false) } +// GetNodeAccountTransactorFromRequest returns a transactor for the node +// account, with gas settings overridden by values sent in the HTTP request +// body (maxFee, maxPrioFee, gasLimit fields in Gwei / uint64). This ensures +// the fee cap and tip cap the user selected interactively in the CLI are +// honoured by the daemon, which otherwise only knows about the values in the +// config file. +func GetNodeAccountTransactorFromRequest(c *cli.Command, r *http.Request) (*bind.TransactOpts, error) { + w, err := GetWallet(c) + if err != nil { + return nil, err + } + opts, err := w.GetNodeAccountTransactor() + if err != nil { + return nil, err + } + if maxFeeStr := r.FormValue("maxFee"); maxFeeStr != "" { + if maxFeeGwei, parseErr := strconv.ParseFloat(maxFeeStr, 64); parseErr == nil && maxFeeGwei > 0 { + opts.GasFeeCap = eth.GweiToWei(maxFeeGwei) + } + } + if maxPrioFeeStr := r.FormValue("maxPrioFee"); maxPrioFeeStr != "" { + if maxPrioFeeGwei, parseErr := strconv.ParseFloat(maxPrioFeeStr, 64); parseErr == nil && maxPrioFeeGwei > 0 { + opts.GasTipCap = eth.GweiToWei(maxPrioFeeGwei) + } + } + if gasLimitStr := r.FormValue("gasLimit"); gasLimitStr != "" { + if gasLimit, parseErr := strconv.ParseUint(gasLimitStr, 10, 64); parseErr == nil { + opts.GasLimit = gasLimit + } + } + return opts, nil +} + func GetHdWallet(c *cli.Command) (wallet.Wallet, error) { cfg, err := getConfig(c) if err != nil { From 352bca4b43a3a5ac29927589c35a7262917ad1cb Mon Sep 17 00:00:00 2001 From: Fornax <23104993+fornax2@users.noreply.github.com> Date: Mon, 30 Mar 2026 11:15:37 -0300 Subject: [PATCH 18/24] Pass the nonce override on the request body --- rocketpool/api/auction/bid-lot.go | 8 -- rocketpool/api/auction/claim-lot.go | 8 -- rocketpool/api/auction/create-lot.go | 9 --- rocketpool/api/auction/recover-lot.go | 8 -- rocketpool/api/megapool/claim-refunds.go | 8 -- rocketpool/api/megapool/delegate.go | 13 --- rocketpool/api/megapool/dissolve-validator.go | 9 --- .../api/megapool/dissolve-with-proof.go | 7 -- rocketpool/api/megapool/distribute.go | 9 --- rocketpool/api/megapool/exit-queue.go | 9 --- .../api/megapool/notify-final-balance.go | 7 -- .../api/megapool/notify-validator-exit.go | 9 --- rocketpool/api/megapool/reduce-bond.go | 8 -- rocketpool/api/megapool/repay-debt.go | 7 -- rocketpool/api/megapool/stake.go | 8 -- rocketpool/api/minipool/close.go | 7 -- rocketpool/api/minipool/delegate.go | 13 --- rocketpool/api/minipool/dissolve.go | 9 --- rocketpool/api/minipool/distribute.go | 7 -- rocketpool/api/minipool/promote.go | 7 -- rocketpool/api/minipool/refund.go | 8 -- rocketpool/api/minipool/rescue-dissolved.go | 7 -- rocketpool/api/minipool/stake.go | 7 -- rocketpool/api/node/burn.go | 8 -- rocketpool/api/node/claim-rewards.go | 13 --- rocketpool/api/node/claim-rpl.go | 7 -- .../api/node/claim-unclaimed-rewards.go | 9 --- rocketpool/api/node/create-vacant-minipool.go | 7 -- rocketpool/api/node/deposit.go | 7 -- rocketpool/api/node/distributor.go | 13 --- rocketpool/api/node/express-ticket.go | 9 --- .../api/node/primary-withdrawal-address.go | 13 --- rocketpool/api/node/register.go | 9 --- rocketpool/api/node/rpl-withdrawal-address.go | 14 ---- rocketpool/api/node/send-message.go | 7 -- rocketpool/api/node/send.go | 13 --- rocketpool/api/node/set-rpl-lock-allowed.go | 7 -- .../api/node/set-stake-rpl-for-allowed.go | 7 -- rocketpool/api/node/set-timezone.go | 8 -- rocketpool/api/node/smoothing-pool.go | 7 -- rocketpool/api/node/stake-rpl.go | 10 --- rocketpool/api/node/swap-rpl.go | 10 --- rocketpool/api/node/unstake-rpl.go | 7 -- rocketpool/api/node/withdraw-credit.go | 8 -- rocketpool/api/node/withdraw-eth.go | 8 -- rocketpool/api/node/withdraw-legacy-rpl.go | 7 -- rocketpool/api/node/withdraw-rpl.go | 12 --- rocketpool/api/odao/cancel-proposal.go | 8 -- rocketpool/api/odao/execute-proposal.go | 9 --- rocketpool/api/odao/join.go | 10 --- rocketpool/api/odao/leave.go | 9 --- rocketpool/api/odao/penalise-megapool.go | 8 -- rocketpool/api/odao/propose-invite.go | 7 -- rocketpool/api/odao/propose-kick.go | 7 -- rocketpool/api/odao/propose-leave.go | 7 -- rocketpool/api/odao/propose-settings.go | 80 ------------------- rocketpool/api/odao/vote-proposal.go | 9 --- rocketpool/api/pdao/claim-bonds.go | 9 --- rocketpool/api/pdao/defeat-proposal.go | 8 -- rocketpool/api/pdao/execute-proposal.go | 9 --- rocketpool/api/pdao/finalize-proposal.go | 9 --- rocketpool/api/pdao/invite-security.go | 8 -- rocketpool/api/pdao/kick-multi-security.go | 10 --- rocketpool/api/pdao/kick-security.go | 8 -- rocketpool/api/pdao/one-time-spend.go | 9 --- rocketpool/api/pdao/override-vote.go | 9 --- rocketpool/api/pdao/percentages.go | 7 -- rocketpool/api/pdao/propose-settings.go | 7 -- rocketpool/api/pdao/recurring-spend.go | 9 --- rocketpool/api/pdao/replace-security.go | 7 -- rocketpool/api/pdao/set-allow-list.go | 10 --- rocketpool/api/pdao/set-snapshot-address.go | 13 --- rocketpool/api/pdao/update-recurring-spend.go | 9 --- rocketpool/api/pdao/vote-proposal.go | 9 --- rocketpool/api/pdao/voting.go | 9 --- rocketpool/api/queue/assign-deposits.go | 8 -- rocketpool/api/queue/process.go | 8 -- rocketpool/api/security/cancel-proposal.go | 8 -- rocketpool/api/security/execute-proposal.go | 9 --- rocketpool/api/security/join.go | 7 -- rocketpool/api/security/leave.go | 9 --- rocketpool/api/security/propose-leave.go | 9 --- rocketpool/api/security/propose-settings.go | 7 -- rocketpool/api/security/vote-proposal.go | 9 --- rocketpool/api/upgrade/execute-upgrade.go | 9 --- rocketpool/rocketpool.go | 4 - shared/services/rocketpool/client.go | 3 + shared/services/services.go | 5 ++ shared/utils/eth1/eth1.go | 48 ----------- 89 files changed, 8 insertions(+), 860 deletions(-) diff --git a/rocketpool/api/auction/bid-lot.go b/rocketpool/api/auction/bid-lot.go index 59906fd49..3dd57714c 100644 --- a/rocketpool/api/auction/bid-lot.go +++ b/rocketpool/api/auction/bid-lot.go @@ -1,7 +1,6 @@ package auction import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canBidOnLot(c *cli.Command, lotIndex uint64, amountWei *big.Int) (*api.CanBidOnLotResponse, error) { @@ -119,12 +117,6 @@ func bidOnLot(c *cli.Command, lotIndex uint64, amountWei *big.Int, opts *bind.Tr opts.Value = amountWei - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Bid on lot hash, err := auction.PlaceBid(rp, lotIndex, opts) if err != nil { diff --git a/rocketpool/api/auction/claim-lot.go b/rocketpool/api/auction/claim-lot.go index 4c8c44372..99c1a4778 100644 --- a/rocketpool/api/auction/claim-lot.go +++ b/rocketpool/api/auction/claim-lot.go @@ -1,7 +1,6 @@ package auction import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -11,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canClaimFromLot(c *cli.Command, lotIndex uint64) (*api.CanClaimFromLotResponse, error) { @@ -110,12 +108,6 @@ func claimFromLot(c *cli.Command, lotIndex uint64, opts *bind.TransactOpts) (*ap // Response response := api.ClaimFromLotResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Claim from lot hash, err := auction.ClaimBid(rp, lotIndex, opts) if err != nil { diff --git a/rocketpool/api/auction/create-lot.go b/rocketpool/api/auction/create-lot.go index f1a8eaea2..63baceb3d 100644 --- a/rocketpool/api/auction/create-lot.go +++ b/rocketpool/api/auction/create-lot.go @@ -1,8 +1,6 @@ package auction import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/auction" "github.com/rocket-pool/smartnode/bindings/settings/protocol" @@ -11,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canCreateLot(c *cli.Command) (*api.CanCreateLotResponse, error) { @@ -97,12 +94,6 @@ func createLot(c *cli.Command, opts *bind.TransactOpts) (*api.CreateLotResponse, // Response response := api.CreateLotResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Create lot lotIndex, hash, err := auction.CreateLot(rp, opts) if err != nil { diff --git a/rocketpool/api/auction/recover-lot.go b/rocketpool/api/auction/recover-lot.go index 0299de07c..6c211bf3d 100644 --- a/rocketpool/api/auction/recover-lot.go +++ b/rocketpool/api/auction/recover-lot.go @@ -1,7 +1,6 @@ package auction import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -11,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canRecoverRplFromLot(c *cli.Command, lotIndex uint64) (*api.CanRecoverRPLFromLotResponse, error) { @@ -115,12 +113,6 @@ func recoverRplFromLot(c *cli.Command, lotIndex uint64, opts *bind.TransactOpts) // Response response := api.RecoverRPLFromLotResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Recover unclaimed RPL from lot hash, err := auction.RecoverUnclaimedRPL(rp, lotIndex, opts) if err != nil { diff --git a/rocketpool/api/megapool/claim-refunds.go b/rocketpool/api/megapool/claim-refunds.go index 8e72c9fca..356876510 100644 --- a/rocketpool/api/megapool/claim-refunds.go +++ b/rocketpool/api/megapool/claim-refunds.go @@ -1,7 +1,6 @@ package megapool import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -10,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canClaimRefund(c *cli.Command) (*api.CanClaimRefundResponse, error) { @@ -120,12 +118,6 @@ func claimRefund(c *cli.Command, opts *bind.TransactOpts) (*api.ClaimRefundRespo return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Dissolve hash, err := mp.ClaimRefund(opts) if err != nil { diff --git a/rocketpool/api/megapool/delegate.go b/rocketpool/api/megapool/delegate.go index 630e39aef..19bcc04f6 100644 --- a/rocketpool/api/megapool/delegate.go +++ b/rocketpool/api/megapool/delegate.go @@ -8,7 +8,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -70,12 +69,6 @@ func delegateUpgrade(c *cli.Command, megapoolAddress common.Address, opts *bind. return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Upgrade hash, err := mega.DelegateUpgrade(opts) if err != nil { @@ -188,12 +181,6 @@ func setUseLatestDelegate(c *cli.Command, megapoolAddress common.Address, useLat return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Set the new setting hash, err := mega.SetUseLatestDelegate(useLatest, opts) if err != nil { diff --git a/rocketpool/api/megapool/dissolve-validator.go b/rocketpool/api/megapool/dissolve-validator.go index 03a4e82a1..de6d40e8b 100644 --- a/rocketpool/api/megapool/dissolve-validator.go +++ b/rocketpool/api/megapool/dissolve-validator.go @@ -1,13 +1,10 @@ package megapool import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -120,12 +117,6 @@ func dissolveValidator(c *cli.Command, validatorId uint32, opts *bind.TransactOp return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Dissolve hash, err := mp.DissolveValidator(validatorId, opts) if err != nil { diff --git a/rocketpool/api/megapool/dissolve-with-proof.go b/rocketpool/api/megapool/dissolve-with-proof.go index c864eedde..34f360f42 100644 --- a/rocketpool/api/megapool/dissolve-with-proof.go +++ b/rocketpool/api/megapool/dissolve-with-proof.go @@ -9,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/types" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -166,12 +165,6 @@ func dissolveWithProof(c *cli.Command, validatorId uint32, opts *bind.TransactOp return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Dissolve tx, err := megapool.DissolveWithProof(rp, megapoolAddress, validatorId, slotTimestamp, validatorProof, slotProof, opts) if err != nil { diff --git a/rocketpool/api/megapool/distribute.go b/rocketpool/api/megapool/distribute.go index 09cae91e7..f2de45f57 100644 --- a/rocketpool/api/megapool/distribute.go +++ b/rocketpool/api/megapool/distribute.go @@ -1,13 +1,10 @@ package megapool import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -116,12 +113,6 @@ func distributeMegapool(c *cli.Command, opts *bind.TransactOpts) (*api.Distribut return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Response response := api.DistributeMegapoolResponse{} diff --git a/rocketpool/api/megapool/exit-queue.go b/rocketpool/api/megapool/exit-queue.go index 376517d74..e69ce609b 100644 --- a/rocketpool/api/megapool/exit-queue.go +++ b/rocketpool/api/megapool/exit-queue.go @@ -1,13 +1,10 @@ package megapool import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -103,12 +100,6 @@ func exitQueue(c *cli.Command, validatorIndex uint32, opts *bind.TransactOpts) ( // Response response := api.ExitQueueResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get the megapool address megapoolAddress, err := megapool.GetMegapoolExpectedAddress(rp, nodeAccount.Address, nil) if err != nil { diff --git a/rocketpool/api/megapool/notify-final-balance.go b/rocketpool/api/megapool/notify-final-balance.go index 691c7f95e..dc1cbacb9 100644 --- a/rocketpool/api/megapool/notify-final-balance.go +++ b/rocketpool/api/megapool/notify-final-balance.go @@ -10,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" cfgtypes "github.com/rocket-pool/smartnode/shared/types/config" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -250,12 +249,6 @@ func notifyFinalBalance(c *cli.Command, validatorId uint32, withdrawalSlot uint6 return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Notify the validator exit tx, err := megapool.NotifyFinalBalance(rp, megapoolAddress, validatorId, slotTimestamp, finalBalanceProof, validatorProof, slotProof, opts) if err != nil { diff --git a/rocketpool/api/megapool/notify-validator-exit.go b/rocketpool/api/megapool/notify-validator-exit.go index 924793ec2..064bb3189 100644 --- a/rocketpool/api/megapool/notify-validator-exit.go +++ b/rocketpool/api/megapool/notify-validator-exit.go @@ -1,14 +1,11 @@ package megapool import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/megapool" "github.com/rocket-pool/smartnode/bindings/types" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -149,12 +146,6 @@ func notifyValidatorExit(c *cli.Command, validatorId uint32, opts *bind.Transact return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Notify the validator exit tx, err := megapool.NotifyExit(rp, megapoolAddress, validatorId, slotTimetamp, validatorProof, slotProof, opts) if err != nil { diff --git a/rocketpool/api/megapool/reduce-bond.go b/rocketpool/api/megapool/reduce-bond.go index a47b44555..745b0ea4b 100644 --- a/rocketpool/api/megapool/reduce-bond.go +++ b/rocketpool/api/megapool/reduce-bond.go @@ -1,7 +1,6 @@ package megapool import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -10,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canReduceBond(c *cli.Command, amount *big.Int) (*api.CanReduceBondResponse, error) { @@ -127,12 +125,6 @@ func reduceBond(c *cli.Command, amount *big.Int, opts *bind.TransactOpts) (*api. return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Reduce bond hash, err := mp.ReduceBond(amount, opts) if err != nil { diff --git a/rocketpool/api/megapool/repay-debt.go b/rocketpool/api/megapool/repay-debt.go index d78bfcb34..259880aae 100644 --- a/rocketpool/api/megapool/repay-debt.go +++ b/rocketpool/api/megapool/repay-debt.go @@ -11,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canRepayDebt(c *cli.Command, amount *big.Int) (*api.CanRepayDebtResponse, error) { @@ -152,12 +151,6 @@ func repayDebt(c *cli.Command, amount *big.Int, opts *bind.TransactOpts) (*api.R opts.Value = amount - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Repay debt hash, err := mp.RepayDebt(opts) if err != nil { diff --git a/rocketpool/api/megapool/stake.go b/rocketpool/api/megapool/stake.go index f800241d4..290d0f237 100644 --- a/rocketpool/api/megapool/stake.go +++ b/rocketpool/api/megapool/stake.go @@ -1,7 +1,6 @@ package megapool import ( - "fmt" "strings" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -11,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canStake(c *cli.Command, validatorId uint64) (*api.CanStakeResponse, error) { @@ -171,12 +169,6 @@ func stake(c *cli.Command, validatorId uint64, opts *bind.TransactOpts) (*api.St return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Stake tx, err := megapool.Stake(rp, megapoolAddress, uint32(validatorId), slotTimestamp, validatorProof, slotProof, opts) if err != nil { diff --git a/rocketpool/api/minipool/close.go b/rocketpool/api/minipool/close.go index bac072825..70f8e23cb 100644 --- a/rocketpool/api/minipool/close.go +++ b/rocketpool/api/minipool/close.go @@ -18,7 +18,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/beacon" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func getMinipoolCloseDetailsForNode(c *cli.Command) (*api.GetMinipoolCloseDetailsForNodeResponse, error) { @@ -333,12 +332,6 @@ func closeMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind.Tr return nil, fmt.Errorf("cannot create v3 binding for minipool %s, version %d", minipoolAddress.Hex(), mp.GetVersion()) } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get some details var status types.MinipoolStatus var distributed bool diff --git a/rocketpool/api/minipool/delegate.go b/rocketpool/api/minipool/delegate.go index 623f243d8..39461ad3e 100644 --- a/rocketpool/api/minipool/delegate.go +++ b/rocketpool/api/minipool/delegate.go @@ -12,7 +12,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canDelegateUpgrade(c *cli.Command, minipoolAddress common.Address) (*api.CanDelegateUpgradeResponse, error) { @@ -81,12 +80,6 @@ func delegateUpgrade(c *cli.Command, minipoolAddress common.Address, opts *bind. return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Upgrade hash, err := mp.DelegateUpgrade(opts) if err != nil { @@ -212,12 +205,6 @@ func setUseLatestDelegate(c *cli.Command, minipoolAddress common.Address, opts * } } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Set the new setting hash, err := mp.SetUseLatestDelegate(opts) if err != nil { diff --git a/rocketpool/api/minipool/dissolve.go b/rocketpool/api/minipool/dissolve.go index 9adc95141..95fec9633 100644 --- a/rocketpool/api/minipool/dissolve.go +++ b/rocketpool/api/minipool/dissolve.go @@ -1,8 +1,6 @@ package minipool import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/minipool" @@ -11,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canDissolveMinipool(c *cli.Command, minipoolAddress common.Address) (*api.CanDissolveMinipoolResponse, error) { @@ -90,12 +87,6 @@ func dissolveMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Dissolve hash, err := mp.Dissolve(opts) if err != nil { diff --git a/rocketpool/api/minipool/distribute.go b/rocketpool/api/minipool/distribute.go index a3c1527a0..3ea08a3e1 100644 --- a/rocketpool/api/minipool/distribute.go +++ b/rocketpool/api/minipool/distribute.go @@ -15,7 +15,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func getDistributeBalanceDetails(c *cli.Command) (*api.GetDistributeBalanceDetailsResponse, error) { @@ -212,12 +211,6 @@ func distributeBalance(c *cli.Command, minipoolAddress common.Address, opts *bin return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Distribute the minipool's balance mpv3, success := minipool.GetMinipoolAsV3(mp) if !success { diff --git a/rocketpool/api/minipool/promote.go b/rocketpool/api/minipool/promote.go index c81ab49ff..c9299f991 100644 --- a/rocketpool/api/minipool/promote.go +++ b/rocketpool/api/minipool/promote.go @@ -13,7 +13,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canPromoteMinipool(c *cli.Command, minipoolAddress common.Address) (*api.CanPromoteMinipoolResponse, error) { @@ -136,12 +135,6 @@ func promoteMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind. return nil, fmt.Errorf("cannot promte minipool %s because its delegate version is too low (v%d); please update the delegate to promote it", mp.GetAddress().Hex(), mp.GetVersion()) } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Promote hash, err := mpv3.Promote(opts) if err != nil { diff --git a/rocketpool/api/minipool/refund.go b/rocketpool/api/minipool/refund.go index 1298702bc..78f7ce15b 100644 --- a/rocketpool/api/minipool/refund.go +++ b/rocketpool/api/minipool/refund.go @@ -1,7 +1,6 @@ package minipool import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -11,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canRefundMinipool(c *cli.Command, minipoolAddress common.Address) (*api.CanRefundMinipoolResponse, error) { @@ -90,12 +88,6 @@ func refundMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind.T return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Refund hash, err := mp.Refund(opts) if err != nil { diff --git a/rocketpool/api/minipool/rescue-dissolved.go b/rocketpool/api/minipool/rescue-dissolved.go index 678696473..99b527d75 100644 --- a/rocketpool/api/minipool/rescue-dissolved.go +++ b/rocketpool/api/minipool/rescue-dissolved.go @@ -19,7 +19,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services/contracts" "github.com/rocket-pool/smartnode/shared/services/wallet" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/rocket-pool/smartnode/shared/utils/validator" ) @@ -305,12 +304,6 @@ func rescueDissolvedMinipool(c *cli.Command, minipoolAddress common.Address, amo opts.Value = amount - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - opts.NoSend = !submit // Submit the rescue deposit diff --git a/rocketpool/api/minipool/stake.go b/rocketpool/api/minipool/stake.go index 1899f85dd..72a2337a9 100644 --- a/rocketpool/api/minipool/stake.go +++ b/rocketpool/api/minipool/stake.go @@ -14,7 +14,6 @@ import ( rptypes "github.com/rocket-pool/smartnode/bindings/types" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/rocket-pool/smartnode/shared/utils/validator" ) @@ -178,12 +177,6 @@ func stakeMinipool(c *cli.Command, minipoolAddress common.Address, opts *bind.Tr return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get eth2 config eth2Config, err := bc.GetEth2Config() if err != nil { diff --git a/rocketpool/api/node/burn.go b/rocketpool/api/node/burn.go index f79ea520c..ae75e0632 100644 --- a/rocketpool/api/node/burn.go +++ b/rocketpool/api/node/burn.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeBurn(c *cli.Command, amountWei *big.Int, token string) (*api.CanNodeBurnResponse, error) { @@ -122,12 +120,6 @@ func nodeBurn(c *cli.Command, amountWei *big.Int, token string, opts *bind.Trans // Response response := api.NodeBurnResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Handle token type switch token { case "reth": diff --git a/rocketpool/api/node/claim-rewards.go b/rocketpool/api/node/claim-rewards.go index a86990e13..d6a62ca60 100644 --- a/rocketpool/api/node/claim-rewards.go +++ b/rocketpool/api/node/claim-rewards.go @@ -22,7 +22,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services/config" rprewards "github.com/rocket-pool/smartnode/shared/services/rewards" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" rputils "github.com/rocket-pool/smartnode/shared/utils/rp" ) @@ -269,12 +268,6 @@ func claimRewards(c *cli.Command, indicesString string, opts *bind.TransactOpts) return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get the rewards claims, err := getRewardsForIntervals(rp, cfg, nodeAccount.Address, indicesString) if err != nil { @@ -368,12 +361,6 @@ func claimAndStakeRewards(c *cli.Command, indicesString string, stakeAmount *big return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get the rewards claims, err := getRewardsForIntervals(rp, cfg, nodeAccount.Address, indicesString) if err != nil { diff --git a/rocketpool/api/node/claim-rpl.go b/rocketpool/api/node/claim-rpl.go index 6cfc8cb4f..f813be4d8 100644 --- a/rocketpool/api/node/claim-rpl.go +++ b/rocketpool/api/node/claim-rpl.go @@ -11,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/legacy/v1.0.0/rewards" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeClaimRpl(c *cli.Command) (*api.CanNodeClaimRplResponse, error) { @@ -98,12 +97,6 @@ func nodeClaimRpl(c *cli.Command, opts *bind.TransactOpts) (*api.NodeClaimRplRes // Response response := api.NodeClaimRplResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Claim rewards legacyClaimNodeAddress := cfg.Smartnode.GetV100ClaimNodeAddress() hash, err := rewards.ClaimNodeRewards(rp, opts, &legacyClaimNodeAddress) diff --git a/rocketpool/api/node/claim-unclaimed-rewards.go b/rocketpool/api/node/claim-unclaimed-rewards.go index 99d84eaff..cfb3fcf17 100644 --- a/rocketpool/api/node/claim-unclaimed-rewards.go +++ b/rocketpool/api/node/claim-unclaimed-rewards.go @@ -1,8 +1,6 @@ package node import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" @@ -10,7 +8,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canClaimUnclaimedRewards(c *cli.Command, nodeAddress common.Address) (*api.CanClaimUnclaimedRewardsResponse, error) { @@ -68,12 +65,6 @@ func claimUnclaimedRewards(c *cli.Command, nodeAddress common.Address, opts *bin // Response response := api.ClaimUnclaimedRewardsResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Claim unclaimed rewards hash, err := node.ClaimUnclaimedRewards(rp, nodeAddress, opts) if err != nil { diff --git a/rocketpool/api/node/create-vacant-minipool.go b/rocketpool/api/node/create-vacant-minipool.go index 57508f728..de75b8bbc 100644 --- a/rocketpool/api/node/create-vacant-minipool.go +++ b/rocketpool/api/node/create-vacant-minipool.go @@ -18,7 +18,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services/beacon" "github.com/rocket-pool/smartnode/shared/types/api" cfgtypes "github.com/rocket-pool/smartnode/shared/types/config" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" ) @@ -252,12 +251,6 @@ func createVacantMinipool(c *cli.Command, amountWei *big.Int, minNodeFee float64 balanceWei := big.NewInt(0).SetUint64(validatorStatus.Balance) balanceWei.Mul(balanceWei, big.NewInt(1e9)) - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Create the minipool tx, err := node.CreateVacantMinipool(rp, amountWei, minNodeFee, pubkey, salt, minipoolAddress, balanceWei, opts) if err != nil { diff --git a/rocketpool/api/node/deposit.go b/rocketpool/api/node/deposit.go index 1adf57ac4..c3d5c9e5d 100644 --- a/rocketpool/api/node/deposit.go +++ b/rocketpool/api/node/deposit.go @@ -24,7 +24,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/beacon" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/rocket-pool/smartnode/shared/utils/validator" eth2types "github.com/wealdtech/go-eth2-types/v2" ) @@ -469,12 +468,6 @@ func nodeDeposits(c *cli.Command, count uint64, amountWei *big.Int, minNodeFee f expressTicketsRequested-- } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Do not send transaction unless requested opts.NoSend = !submit diff --git a/rocketpool/api/node/distributor.go b/rocketpool/api/node/distributor.go index f29a128c0..0063db488 100644 --- a/rocketpool/api/node/distributor.go +++ b/rocketpool/api/node/distributor.go @@ -13,7 +13,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func isFeeDistributorInitialized(c *cli.Command) (*api.NodeIsFeeDistributorInitializedResponse, error) { @@ -112,11 +111,6 @@ func initializeFeeDistributor(c *cli.Command, opts *bind.TransactOpts) (*api.Nod // Response response := api.NodeInitializeFeeDistributorResponse{} - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Initialize the fee distributor hash, err := node.InitializeFeeDistributor(rp, opts) if err != nil { @@ -245,13 +239,6 @@ func distribute(c *cli.Command, opts *bind.TransactOpts) (*api.NodeDistributeRes return nil, err } - // Get gas estimates - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - hash, err := distributor.Distribute(opts) if err != nil { return nil, err diff --git a/rocketpool/api/node/express-ticket.go b/rocketpool/api/node/express-ticket.go index 1b19ebdbe..bcc1a6d2b 100644 --- a/rocketpool/api/node/express-ticket.go +++ b/rocketpool/api/node/express-ticket.go @@ -1,14 +1,11 @@ package node import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -145,12 +142,6 @@ func provisionExpressTickets(c *cli.Command, opts *bind.TransactOpts) (*api.Prov // Response response := api.ProvisionExpressTicketsResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("error checking for nonce override: %w", err) - } - // Provision express tickets hash, err := node.ProvisionExpressTickets(rp, nodeAccount.Address, opts) if err != nil { diff --git a/rocketpool/api/node/primary-withdrawal-address.go b/rocketpool/api/node/primary-withdrawal-address.go index 274395bdc..046f0a20b 100644 --- a/rocketpool/api/node/primary-withdrawal-address.go +++ b/rocketpool/api/node/primary-withdrawal-address.go @@ -10,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canSetPrimaryWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address, confirm bool) (*api.CanSetNodePrimaryWithdrawalAddressResponse, error) { @@ -73,12 +72,6 @@ func setPrimaryWithdrawalAddress(c *cli.Command, withdrawalAddress common.Addres // Response response := api.SetNodePrimaryWithdrawalAddressResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get the node's account nodeAccount, err := w.GetNodeAccount() if err != nil { @@ -173,12 +166,6 @@ func confirmPrimaryWithdrawalAddress(c *cli.Command, opts *bind.TransactOpts) (* // Response response := api.ConfirmNodePrimaryWithdrawalAddressResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get the node's account nodeAccount, err := w.GetNodeAccount() if err != nil { diff --git a/rocketpool/api/node/register.go b/rocketpool/api/node/register.go index 4bdff83fc..443a54e1c 100644 --- a/rocketpool/api/node/register.go +++ b/rocketpool/api/node/register.go @@ -1,8 +1,6 @@ package node import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/node" @@ -12,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canRegisterNode(c *cli.Command, timezoneLocation string) (*api.CanRegisterNodeResponse, error) { @@ -103,12 +100,6 @@ func registerNode(c *cli.Command, timezoneLocation string, opts *bind.TransactOp // Response response := api.RegisterNodeResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Register node hash, err := node.RegisterNode(rp, timezoneLocation, opts) if err != nil { diff --git a/rocketpool/api/node/rpl-withdrawal-address.go b/rocketpool/api/node/rpl-withdrawal-address.go index 97571a561..1a91a99aa 100644 --- a/rocketpool/api/node/rpl-withdrawal-address.go +++ b/rocketpool/api/node/rpl-withdrawal-address.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -13,7 +12,6 @@ import ( "golang.org/x/sync/errgroup" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canSetRPLWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address, confirm bool) (*api.CanSetNodeRPLWithdrawalAddressResponse, error) { @@ -121,12 +119,6 @@ func setRPLWithdrawalAddress(c *cli.Command, withdrawalAddress common.Address, c // Response response := api.SetNodeRPLWithdrawalAddressResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get the node's account nodeAccount, err := w.GetNodeAccount() if err != nil { @@ -212,12 +204,6 @@ func confirmRPLWithdrawalAddress(c *cli.Command, opts *bind.TransactOpts) (*api. // Response response := api.ConfirmNodeRPLWithdrawalAddressResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get the node's account nodeAccount, err := w.GetNodeAccount() if err != nil { diff --git a/rocketpool/api/node/send-message.go b/rocketpool/api/node/send-message.go index 2ca7a2797..5d114e834 100644 --- a/rocketpool/api/node/send-message.go +++ b/rocketpool/api/node/send-message.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -66,12 +65,6 @@ func sendMessage(c *cli.Command, address common.Address, message []byte, opts *b // Response response := api.NodeSendMessageResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Send the message hash, err := eth.SendTransaction(ec, address, w.GetChainID(), message, true, opts) if err != nil { diff --git a/rocketpool/api/node/send.go b/rocketpool/api/node/send.go index d1e6ee782..663481176 100644 --- a/rocketpool/api/node/send.go +++ b/rocketpool/api/node/send.go @@ -15,7 +15,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeSend(c *cli.Command, amountRaw float64, token string, to common.Address) (*api.CanNodeSendResponse, error) { @@ -226,12 +225,6 @@ func nodeSend(c *cli.Command, amountRaw float64, token string, to common.Address // Response response := api.NodeSendResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Handle explicit token addresses if strings.HasPrefix(token, "0x") { tokenAddress := common.HexToAddress(token) @@ -340,12 +333,6 @@ func nodeSendAllTokens(c *cli.Command, token string, to common.Address, opts *bi return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Handle explicit token addresses if strings.HasPrefix(token, "0x") { tokenAddress := common.HexToAddress(token) diff --git a/rocketpool/api/node/set-rpl-lock-allowed.go b/rocketpool/api/node/set-rpl-lock-allowed.go index 4ca37a556..35947dde8 100644 --- a/rocketpool/api/node/set-rpl-lock-allowed.go +++ b/rocketpool/api/node/set-rpl-lock-allowed.go @@ -1,8 +1,6 @@ package node import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/node" @@ -10,7 +8,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canSetRplLockAllowed(c *cli.Command, allowed bool) (*api.CanSetRplLockingAllowedResponse, error) { @@ -89,10 +86,6 @@ func setRplLockAllowed(c *cli.Command, allowed bool, opts *bind.TransactOpts) (* response := api.SetRplLockingAllowedResponse{} // Stake RPL - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } hash, err := node.SetRPLLockingAllowed(rp, account.Address, allowed, opts) if err != nil { return nil, err diff --git a/rocketpool/api/node/set-stake-rpl-for-allowed.go b/rocketpool/api/node/set-stake-rpl-for-allowed.go index a6420d431..ddf6fdb62 100644 --- a/rocketpool/api/node/set-stake-rpl-for-allowed.go +++ b/rocketpool/api/node/set-stake-rpl-for-allowed.go @@ -1,8 +1,6 @@ package node import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/node" @@ -10,7 +8,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canSetStakeRplForAllowed(c *cli.Command, caller common.Address, allowed bool) (*api.CanSetStakeRplForAllowedResponse, error) { @@ -63,10 +60,6 @@ func setStakeRplForAllowed(c *cli.Command, caller common.Address, allowed bool, response := api.SetStakeRplForAllowedResponse{} // Stake RPL - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } hash, err := node.SetStakeRPLForAllowed(rp, caller, allowed, opts) if err != nil { return nil, err diff --git a/rocketpool/api/node/set-timezone.go b/rocketpool/api/node/set-timezone.go index f85947abd..9a2a95105 100644 --- a/rocketpool/api/node/set-timezone.go +++ b/rocketpool/api/node/set-timezone.go @@ -1,7 +1,6 @@ package node import ( - "fmt" _ "time/tzdata" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -11,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canSetTimezoneLocation(c *cli.Command, timezoneLocation string) (*api.CanSetNodeTimezoneResponse, error) { @@ -61,12 +59,6 @@ func setTimezoneLocation(c *cli.Command, timezoneLocation string, opts *bind.Tra // Response response := api.SetNodeTimezoneResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Set timezone location hash, err := node.SetTimezoneLocation(rp, timezoneLocation, opts) if err != nil { diff --git a/rocketpool/api/node/smoothing-pool.go b/rocketpool/api/node/smoothing-pool.go index 5b2ea3cc6..a1bc9d6b7 100644 --- a/rocketpool/api/node/smoothing-pool.go +++ b/rocketpool/api/node/smoothing-pool.go @@ -12,7 +12,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/rocketpool" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/rocket-pool/smartnode/shared/utils/validator" "github.com/urfave/cli/v3" ) @@ -147,12 +146,6 @@ func setSmoothingPoolStatus(c *cli.Command, status bool, opts *bind.TransactOpts // Response response := api.SetSmoothingPoolRegistrationStatusResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Get node account and distributor address nodeAccount, err := w.GetNodeAccount() if err != nil { diff --git a/rocketpool/api/node/stake-rpl.go b/rocketpool/api/node/stake-rpl.go index f2f39ad65..6ed4fc8a9 100644 --- a/rocketpool/api/node/stake-rpl.go +++ b/rocketpool/api/node/stake-rpl.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -14,7 +13,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeStakeRpl(c *cli.Command, amountWei *big.Int) (*api.CanNodeStakeRplResponse, error) { @@ -166,10 +164,6 @@ func approveRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*a } // Approve RPL allowance - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } hash, err := tokens.ApproveRPL(rp, *rocketNodeStakingAddress, amountWei, opts) if err != nil { return nil, err @@ -219,10 +213,6 @@ func stakeRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api response := api.NodeStakeRplStakeResponse{} // Stake RPL - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } hash, err := node.StakeRPL(rp, amountWei, opts) if err != nil { return nil, err diff --git a/rocketpool/api/node/swap-rpl.go b/rocketpool/api/node/swap-rpl.go index 9adb23cb5..74e2d2dbb 100644 --- a/rocketpool/api/node/swap-rpl.go +++ b/rocketpool/api/node/swap-rpl.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeSwapRpl(c *cli.Command, amountWei *big.Int) (*api.CanNodeSwapRplResponse, error) { @@ -170,10 +168,6 @@ func approveFsRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) ( } // Approve fixed-supply RPL allowance - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } if hash, err := tokens.ApproveFixedSupplyRPL(rp, *rocketTokenRPLAddress, amountWei, opts); err != nil { return nil, err } else { @@ -224,10 +218,6 @@ func swapRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) (*api. response := api.NodeSwapRplSwapResponse{} // Swap fixed-supply RPL for RPL - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } if hash, err := tokens.SwapFixedSupplyRPLForRPL(rp, amountWei, opts); err != nil { return nil, err } else { diff --git a/rocketpool/api/node/unstake-rpl.go b/rocketpool/api/node/unstake-rpl.go index a3f24d582..4a2d0d542 100644 --- a/rocketpool/api/node/unstake-rpl.go +++ b/rocketpool/api/node/unstake-rpl.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeUnstakeRpl(c *cli.Command, amountWei *big.Int) (*api.CanNodeUnstakeRplResponse, error) { @@ -119,11 +117,6 @@ func nodeUnstakeRpl(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts) // Response response := api.NodeUnstakeRplResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } var hash common.Hash // Withdraw RPL hash, err = node.UnstakeRPL(rp, amountWei, opts) diff --git a/rocketpool/api/node/withdraw-credit.go b/rocketpool/api/node/withdraw-credit.go index 5e3404a37..42c07e83b 100644 --- a/rocketpool/api/node/withdraw-credit.go +++ b/rocketpool/api/node/withdraw-credit.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeWithdrawCredit(c *cli.Command, amountWei *big.Int) (*api.CanNodeWithdrawCreditResponse, error) { @@ -90,12 +88,6 @@ func nodeWithdrawCredit(c *cli.Command, amountWei *big.Int, opts *bind.TransactO // Response response := api.NodeWithdrawCreditResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Withdraw credit tx, err := node.WithdrawCredit(rp, amountWei, opts) if err != nil { diff --git a/rocketpool/api/node/withdraw-eth.go b/rocketpool/api/node/withdraw-eth.go index f3242e84a..f9dfd5f3a 100644 --- a/rocketpool/api/node/withdraw-eth.go +++ b/rocketpool/api/node/withdraw-eth.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeWithdrawEth(c *cli.Command, amountWei *big.Int) (*api.CanNodeWithdrawEthResponse, error) { @@ -110,12 +108,6 @@ func nodeWithdrawEth(c *cli.Command, amountWei *big.Int, opts *bind.TransactOpts return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Withdraw ETH tx, err := node.WithdrawEth(rp, nodeAccount.Address, amountWei, opts) if err != nil { diff --git a/rocketpool/api/node/withdraw-legacy-rpl.go b/rocketpool/api/node/withdraw-legacy-rpl.go index 01bee6e13..d26d75316 100644 --- a/rocketpool/api/node/withdraw-legacy-rpl.go +++ b/rocketpool/api/node/withdraw-legacy-rpl.go @@ -1,7 +1,6 @@ package node import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeUnstakeLegacyRpl(c *cli.Command, amountWei *big.Int) (*api.CanNodeUnstakeLegacyRplResponse, error) { @@ -128,11 +126,6 @@ func nodeUnstakeLegacyRpl(c *cli.Command, amountWei *big.Int, opts *bind.Transac // Response response := api.NodeUnstakeLegacyRplResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } var hash common.Hash // Unstake legacy RPL hash, err = node.UnstakeLegacyRPL(rp, amountWei, opts) diff --git a/rocketpool/api/node/withdraw-rpl.go b/rocketpool/api/node/withdraw-rpl.go index 10b19324e..3bd444c07 100644 --- a/rocketpool/api/node/withdraw-rpl.go +++ b/rocketpool/api/node/withdraw-rpl.go @@ -2,7 +2,6 @@ package node import ( "context" - "fmt" "math/big" "time" @@ -16,7 +15,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canNodeWithdrawRpl(c *cli.Command) (*api.CanNodeWithdrawRplResponse, error) { @@ -144,11 +142,6 @@ func nodeWithdrawRpl(c *cli.Command, opts *bind.TransactOpts) (*api.NodeWithdraw // Response response := api.NodeWithdrawRplResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } var hash common.Hash // Withdraw RPL hash, err = node.WithdrawRPL(rp, opts) @@ -325,11 +318,6 @@ func nodeWithdrawRplv1_3_1(c *cli.Command, amountWei *big.Int, opts *bind.Transa // Response response := api.NodeWithdrawRplResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } var hash common.Hash // Withdraw RPL hash, err = node131.WithdrawRPL(rp, nodeAccount.Address, amountWei, opts) diff --git a/rocketpool/api/odao/cancel-proposal.go b/rocketpool/api/odao/cancel-proposal.go index 8aa5caee3..9976f126c 100644 --- a/rocketpool/api/odao/cancel-proposal.go +++ b/rocketpool/api/odao/cancel-proposal.go @@ -2,7 +2,6 @@ package odao import ( "bytes" - "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -14,7 +13,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canCancelProposal(c *cli.Command, proposalId uint64) (*api.CanCancelTNDAOProposalResponse, error) { @@ -107,12 +105,6 @@ func cancelProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) // Response response := api.CancelTNDAOProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Cancel proposal hash, err := trustednode.CancelProposal(rp, proposalId, opts) if err != nil { diff --git a/rocketpool/api/odao/execute-proposal.go b/rocketpool/api/odao/execute-proposal.go index 91b56aa75..14ac9d759 100644 --- a/rocketpool/api/odao/execute-proposal.go +++ b/rocketpool/api/odao/execute-proposal.go @@ -1,8 +1,6 @@ package odao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao" @@ -13,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canExecuteProposal(c *cli.Command, proposalId uint64) (*api.CanExecuteTNDAOProposalResponse, error) { @@ -99,12 +96,6 @@ func executeProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) // Response response := api.ExecuteTNDAOProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Cancel proposal hash, err := trustednode.ExecuteProposal(rp, proposalId, opts) if err != nil { diff --git a/rocketpool/api/odao/join.go b/rocketpool/api/odao/join.go index 2df45f731..f5ce226c9 100644 --- a/rocketpool/api/odao/join.go +++ b/rocketpool/api/odao/join.go @@ -1,7 +1,6 @@ package odao import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -15,7 +14,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canJoin(c *cli.Command) (*api.CanJoinTNDAOResponse, error) { @@ -158,10 +156,6 @@ func approveRpl(c *cli.Command, opts *bind.TransactOpts) (*api.JoinTNDAOApproveR } // Approve RPL allowance - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } hash, err := tokens.ApproveRPL(rp, *rocketDAONodeTrustedActionsAddress, rplBondAmount, opts) if err != nil { return nil, err @@ -195,10 +189,6 @@ func waitForApprovalAndJoin(c *cli.Command, hash common.Hash, opts *bind.Transac response := api.JoinTNDAOJoinResponse{} // Join - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } joinHash, err := tndao.Join(rp, opts) if err != nil { return nil, err diff --git a/rocketpool/api/odao/leave.go b/rocketpool/api/odao/leave.go index d833cb7f7..868015609 100644 --- a/rocketpool/api/odao/leave.go +++ b/rocketpool/api/odao/leave.go @@ -1,8 +1,6 @@ package odao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/trustednode" @@ -11,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canLeave(c *cli.Command) (*api.CanLeaveTNDAOResponse, error) { @@ -95,12 +92,6 @@ func leave(c *cli.Command, bondRefundAddress common.Address, opts *bind.Transact // Response response := api.LeaveTNDAOResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Leave hash, err := trustednode.Leave(rp, bondRefundAddress, opts) if err != nil { diff --git a/rocketpool/api/odao/penalise-megapool.go b/rocketpool/api/odao/penalise-megapool.go index 4cdd6f19e..a066cf56f 100644 --- a/rocketpool/api/odao/penalise-megapool.go +++ b/rocketpool/api/odao/penalise-megapool.go @@ -1,7 +1,6 @@ package odao import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -11,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canPenaliseMegapool(c *cli.Command, megapoolAddress common.Address, block *big.Int, amount *big.Int) (*api.CanPenaliseMegapoolResponse, error) { @@ -73,12 +71,6 @@ func penaliseMegapool(c *cli.Command, megapoolAddress common.Address, block *big // Response response := api.PenaliseMegapoolResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Repay debt hash, err := megapool.Penalise(rp, megapoolAddress, block, amount, opts) if err != nil { diff --git a/rocketpool/api/odao/propose-invite.go b/rocketpool/api/odao/propose-invite.go index a31534c5d..e1933f4ff 100644 --- a/rocketpool/api/odao/propose-invite.go +++ b/rocketpool/api/odao/propose-invite.go @@ -11,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canProposeInvite(c *cli.Command, memberAddress common.Address, memberId, memberUrl string) (*api.CanProposeTNDAOInviteResponse, error) { @@ -96,12 +95,6 @@ func proposeInvite(c *cli.Command, memberAddress common.Address, memberId, membe // Response response := api.ProposeTNDAOInviteResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal message := fmt.Sprintf("invite %s (%s)", memberId, memberUrl) proposalId, hash, err := trustednode.ProposeInviteMember(rp, message, memberAddress, memberId, memberUrl, opts) diff --git a/rocketpool/api/odao/propose-kick.go b/rocketpool/api/odao/propose-kick.go index 6368e22d1..56ef6893f 100644 --- a/rocketpool/api/odao/propose-kick.go +++ b/rocketpool/api/odao/propose-kick.go @@ -13,7 +13,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/rocket-pool/smartnode/shared/utils/math" ) @@ -129,12 +128,6 @@ func proposeKick(c *cli.Command, memberAddress common.Address, fineAmountWei *bi return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal message := fmt.Sprintf("kick %s (%s) with %.6f RPL fine", memberId, memberUrl, math.RoundDown(eth.WeiToEth(fineAmountWei), 6)) proposalId, hash, err := trustednode.ProposeKickMember(rp, message, memberAddress, fineAmountWei, opts) diff --git a/rocketpool/api/odao/propose-leave.go b/rocketpool/api/odao/propose-leave.go index 42aec63cc..bd9c51d48 100644 --- a/rocketpool/api/odao/propose-leave.go +++ b/rocketpool/api/odao/propose-leave.go @@ -11,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canProposeLeave(c *cli.Command) (*api.CanProposeTNDAOLeaveResponse, error) { @@ -140,12 +139,6 @@ func proposeLeave(c *cli.Command, opts *bind.TransactOpts) (*api.ProposeTNDAOLea return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal message := fmt.Sprintf("%s (%s) leaves", nodeMemberId, nodeMemberUrl) proposalId, hash, err := trustednode.ProposeMemberLeave(rp, message, nodeAccount.Address, opts) diff --git a/rocketpool/api/odao/propose-settings.go b/rocketpool/api/odao/propose-settings.go index 560403e1b..6a6479318 100644 --- a/rocketpool/api/odao/propose-settings.go +++ b/rocketpool/api/odao/propose-settings.go @@ -1,7 +1,6 @@ package odao import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -13,7 +12,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/wallet" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canProposeSetting(c *cli.Command, w wallet.Wallet, rp *rocketpool.RocketPool) (*api.CanProposeTNDAOSettingResponse, error) { @@ -90,12 +88,6 @@ func proposeSettingMembersQuorum(c *cli.Command, quorum float64, opts *bind.Tran // Response response := api.ProposeTNDAOSettingMembersQuorumResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeQuorum(rp, quorum, opts) if err != nil { @@ -159,12 +151,6 @@ func proposeSettingMembersRplBond(c *cli.Command, bondAmountWei *big.Int, opts * // Response response := api.ProposeTNDAOSettingMembersRplBondResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeRPLBond(rp, bondAmountWei, opts) if err != nil { @@ -228,12 +214,6 @@ func proposeSettingMinipoolUnbondedMax(c *cli.Command, unbondedMinipoolMax uint6 // Response response := api.ProposeTNDAOSettingMinipoolUnbondedMaxResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeMinipoolUnbondedMax(rp, unbondedMinipoolMax, opts) if err != nil { @@ -297,12 +277,6 @@ func proposeSettingProposalCooldown(c *cli.Command, proposalCooldownTimespan uin // Response response := api.ProposeTNDAOSettingProposalCooldownResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeProposalCooldownTime(rp, proposalCooldownTimespan, opts) if err != nil { @@ -366,12 +340,6 @@ func proposeSettingProposalVoteTimespan(c *cli.Command, proposalVoteTimespan uin // Response response := api.ProposeTNDAOSettingProposalVoteTimespanResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeProposalVoteTime(rp, proposalVoteTimespan, opts) if err != nil { @@ -435,12 +403,6 @@ func proposeSettingProposalVoteDelayTimespan(c *cli.Command, proposalDelayTimesp // Response response := api.ProposeTNDAOSettingProposalVoteDelayTimespanResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeProposalVoteDelayTime(rp, proposalDelayTimespan, opts) if err != nil { @@ -504,12 +466,6 @@ func proposeSettingProposalExecuteTimespan(c *cli.Command, proposalExecuteTimesp // Response response := api.ProposeTNDAOSettingProposalExecuteTimespanResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeProposalExecuteTime(rp, proposalExecuteTimespan, opts) if err != nil { @@ -573,12 +529,6 @@ func proposeSettingProposalActionTimespan(c *cli.Command, proposalActionTimespan // Response response := api.ProposeTNDAOSettingProposalActionTimespanResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeProposalActionTime(rp, proposalActionTimespan, opts) if err != nil { @@ -642,12 +592,6 @@ func proposeSettingScrubPeriod(c *cli.Command, scrubPeriod uint64, opts *bind.Tr // Response response := api.ProposeTNDAOSettingScrubPeriodResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeScrubPeriod(rp, scrubPeriod, opts) if err != nil { @@ -711,12 +655,6 @@ func proposeSettingPromotionScrubPeriod(c *cli.Command, promotionScrubPeriod uin // Response response := api.ProposeTNDAOSettingPromotionScrubPeriodResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposePromotionScrubPeriod(rp, promotionScrubPeriod, opts) if err != nil { @@ -780,12 +718,6 @@ func proposeSettingScrubPenaltyEnabled(c *cli.Command, enabled bool, opts *bind. // Response response := api.ProposeTNDAOSettingScrubPeriodResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeScrubPenaltyEnabled(rp, enabled, opts) if err != nil { @@ -849,12 +781,6 @@ func proposeSettingBondReductionWindowStart(c *cli.Command, bondReductionWindowS // Response response := api.ProposeTNDAOSettingScrubPeriodResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeBondReductionWindowStart(rp, bondReductionWindowStart, opts) if err != nil { @@ -918,12 +844,6 @@ func proposeSettingBondReductionWindowLength(c *cli.Command, bondReductionWindow // Response response := api.ProposeTNDAOSettingScrubPeriodResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal proposalId, hash, err := trustednode.ProposeBondReductionWindowLength(rp, bondReductionWindowLength, opts) if err != nil { diff --git a/rocketpool/api/odao/vote-proposal.go b/rocketpool/api/odao/vote-proposal.go index 596309d21..e2860fe2d 100644 --- a/rocketpool/api/odao/vote-proposal.go +++ b/rocketpool/api/odao/vote-proposal.go @@ -1,8 +1,6 @@ package odao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao" @@ -13,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canVoteOnProposal(c *cli.Command, proposalId uint64) (*api.CanVoteOnTNDAOProposalResponse, error) { @@ -127,12 +124,6 @@ func voteOnProposal(c *cli.Command, proposalId uint64, support bool, opts *bind. // Response response := api.VoteOnTNDAOProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Vote on proposal hash, err := trustednode.VoteOnProposal(rp, proposalId, support, opts) if err != nil { diff --git a/rocketpool/api/pdao/claim-bonds.go b/rocketpool/api/pdao/claim-bonds.go index da7cf6976..a71015808 100644 --- a/rocketpool/api/pdao/claim-bonds.go +++ b/rocketpool/api/pdao/claim-bonds.go @@ -1,8 +1,6 @@ package pdao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao/protocol" @@ -13,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canClaimBonds(c *cli.Command, proposalId uint64, indices []uint64) (*api.PDAOCanClaimBondsResponse, error) { @@ -122,12 +119,6 @@ func claimBonds(c *cli.Command, isProposer bool, proposalId uint64, indices []ui // Response response := api.PDAOClaimBondsResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Claim bonds if isProposer { response.TxHash, err = protocol.ClaimBondProposer(rp, proposalId, indices, opts) diff --git a/rocketpool/api/pdao/defeat-proposal.go b/rocketpool/api/pdao/defeat-proposal.go index b562a8aee..2d3a7ced1 100644 --- a/rocketpool/api/pdao/defeat-proposal.go +++ b/rocketpool/api/pdao/defeat-proposal.go @@ -1,7 +1,6 @@ package pdao import ( - "fmt" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -13,7 +12,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canDefeatProposal(c *cli.Command, proposalId uint64, index uint64) (*api.PDAOCanDefeatProposalResponse, error) { @@ -126,12 +124,6 @@ func defeatProposal(c *cli.Command, proposalId uint64, index uint64, opts *bind. // Response response := api.PDAODefeatProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Execute proposal hash, err := protocol.DefeatProposal(rp, proposalId, index, opts) if err != nil { diff --git a/rocketpool/api/pdao/execute-proposal.go b/rocketpool/api/pdao/execute-proposal.go index 77e56bdea..a6680e556 100644 --- a/rocketpool/api/pdao/execute-proposal.go +++ b/rocketpool/api/pdao/execute-proposal.go @@ -1,8 +1,6 @@ package pdao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao/protocol" @@ -12,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canExecuteProposal(c *cli.Command, proposalId uint64) (*api.CanExecutePDAOProposalResponse, error) { @@ -98,12 +95,6 @@ func executeProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) // Response response := api.ExecutePDAOProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Execute proposal hash, err := protocol.ExecuteProposal(rp, proposalId, opts) if err != nil { diff --git a/rocketpool/api/pdao/finalize-proposal.go b/rocketpool/api/pdao/finalize-proposal.go index 6a4054103..05f04a330 100644 --- a/rocketpool/api/pdao/finalize-proposal.go +++ b/rocketpool/api/pdao/finalize-proposal.go @@ -1,8 +1,6 @@ package pdao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao/protocol" @@ -12,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canFinalizeProposal(c *cli.Command, proposalId uint64) (*api.PDAOCanFinalizeProposalResponse, error) { @@ -105,12 +102,6 @@ func finalizeProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts // Response response := api.PDAOFinalizeProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Execute proposal hash, err := protocol.Finalize(rp, proposalId, opts) if err != nil { diff --git a/rocketpool/api/pdao/invite-security.go b/rocketpool/api/pdao/invite-security.go index 9b0ee6178..896ef8c79 100644 --- a/rocketpool/api/pdao/invite-security.go +++ b/rocketpool/api/pdao/invite-security.go @@ -10,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" ) @@ -116,13 +115,6 @@ func proposeInviteToSecurityCouncil(c *cli.Command, id string, address common.Ad // Response response := api.PDAOProposeInviteToSecurityCouncilResponse{} - // Get node account - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Propose message := fmt.Sprintf("invite %s (%s) to the security council", id, address.Hex()) pollard, err := getPollard(rp, cfg, bc, blockNumber) diff --git a/rocketpool/api/pdao/kick-multi-security.go b/rocketpool/api/pdao/kick-multi-security.go index d2588affd..365b99f7d 100644 --- a/rocketpool/api/pdao/kick-multi-security.go +++ b/rocketpool/api/pdao/kick-multi-security.go @@ -1,14 +1,11 @@ package pdao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -75,13 +72,6 @@ func proposeKickMultiFromSecurityCouncil(c *cli.Command, addresses []common.Addr // Response response := api.PDAOProposeKickMultiFromSecurityCouncilResponse{} - // Get node account - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Propose message := "kick multiple members from the security council" pollard, err := getPollard(rp, cfg, bc, blockNumber) diff --git a/rocketpool/api/pdao/kick-security.go b/rocketpool/api/pdao/kick-security.go index 9e33ad736..4c0fcd257 100644 --- a/rocketpool/api/pdao/kick-security.go +++ b/rocketpool/api/pdao/kick-security.go @@ -9,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -100,13 +99,6 @@ func proposeKickFromSecurityCouncil(c *cli.Command, address common.Address, bloc // Response response := api.PDAOProposeKickFromSecurityCouncilResponse{} - // Get node account - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Propose message := fmt.Sprintf("kick %s from the security council", address.Hex()) pollard, err := getPollard(rp, cfg, bc, blockNumber) diff --git a/rocketpool/api/pdao/one-time-spend.go b/rocketpool/api/pdao/one-time-spend.go index 898f29260..47c25259f 100644 --- a/rocketpool/api/pdao/one-time-spend.go +++ b/rocketpool/api/pdao/one-time-spend.go @@ -1,7 +1,6 @@ package pdao import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -10,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -100,13 +98,6 @@ func proposeOneTimeSpend(c *cli.Command, invoiceID string, recipient common.Addr // Response response := api.PDAOProposeOneTimeSpendResponse{} - // Get node account - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Propose pollard, err := getPollard(rp, cfg, bc, blockNumber) if err != nil { diff --git a/rocketpool/api/pdao/override-vote.go b/rocketpool/api/pdao/override-vote.go index 3c757ebce..33595e5a1 100644 --- a/rocketpool/api/pdao/override-vote.go +++ b/rocketpool/api/pdao/override-vote.go @@ -1,8 +1,6 @@ package pdao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" @@ -13,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canOverrideVote(c *cli.Command, proposalId uint64, voteDirection types.VoteDirection) (*api.CanVoteOnPDAOProposalResponse, error) { @@ -117,12 +114,6 @@ func overrideVote(c *cli.Command, proposalId uint64, voteDirection types.VoteDir // Response response := api.VoteOnPDAOProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Vote on proposal hash, err := protocol.OverrideVote(rp, proposalId, voteDirection, opts) if err != nil { diff --git a/rocketpool/api/pdao/percentages.go b/rocketpool/api/pdao/percentages.go index 00cbd6115..4e8c7fdd9 100644 --- a/rocketpool/api/pdao/percentages.go +++ b/rocketpool/api/pdao/percentages.go @@ -12,7 +12,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/utils/eth" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -158,12 +157,6 @@ func proposeRewardsPercentages(c *cli.Command, node *big.Int, odao *big.Int, pda return nil, fmt.Errorf("error regenerating pollard: %w", err) } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit the proposal proposalID, hash, err := protocol.ProposeSetRewardsPercentage(rp, "update RPL rewards distribution", odao, pdao, node, blockNumber, pollard, opts) if err != nil { diff --git a/rocketpool/api/pdao/propose-settings.go b/rocketpool/api/pdao/propose-settings.go index c095e0079..ef42e6def 100644 --- a/rocketpool/api/pdao/propose-settings.go +++ b/rocketpool/api/pdao/propose-settings.go @@ -14,7 +14,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" "golang.org/x/sync/errgroup" ) @@ -971,12 +970,6 @@ func proposeSetting(c *cli.Command, contractName string, settingName string, val return nil, fmt.Errorf("error regenerating pollard: %w", err) } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit the proposal var proposalID uint64 var hash common.Hash diff --git a/rocketpool/api/pdao/recurring-spend.go b/rocketpool/api/pdao/recurring-spend.go index 5be04f4e3..1430d1efb 100644 --- a/rocketpool/api/pdao/recurring-spend.go +++ b/rocketpool/api/pdao/recurring-spend.go @@ -1,7 +1,6 @@ package pdao import ( - "fmt" "math/big" "time" @@ -11,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -101,13 +99,6 @@ func proposeRecurringSpend(c *cli.Command, contractName string, recipient common // Response response := api.PDAOProposeOneTimeSpendResponse{} - // Get node account - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Propose pollard, err := getPollard(rp, cfg, bc, blockNumber) diff --git a/rocketpool/api/pdao/replace-security.go b/rocketpool/api/pdao/replace-security.go index 72a4aca42..047b2dd4e 100644 --- a/rocketpool/api/pdao/replace-security.go +++ b/rocketpool/api/pdao/replace-security.go @@ -10,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -114,12 +113,6 @@ func proposeReplaceMemberOfSecurityCouncil(c *cli.Command, existingMemberAddress return nil, fmt.Errorf("error getting ID of existing member: %w", err) } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Propose message := fmt.Sprintf("replace %s (%s) on the security council with %s (%s)", existingID, existingMemberAddress.Hex(), newMemberID, newMemberAddress.Hex()) pollard, err := getPollard(rp, cfg, bc, blockNumber) diff --git a/rocketpool/api/pdao/set-allow-list.go b/rocketpool/api/pdao/set-allow-list.go index c89e44812..dfc867104 100644 --- a/rocketpool/api/pdao/set-allow-list.go +++ b/rocketpool/api/pdao/set-allow-list.go @@ -1,15 +1,12 @@ package pdao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/bindings/settings/protocol" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -99,13 +96,6 @@ func proposeAllowListedControllers(c *cli.Command, addressList []common.Address, // Response response := api.PDAOProposeAllowListedControllersResponse{} - // Get node account - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Propose pollard, err := getPollard(rp, cfg, bc, blockNumber) if err != nil { diff --git a/rocketpool/api/pdao/set-snapshot-address.go b/rocketpool/api/pdao/set-snapshot-address.go index 69b026605..a0f1a677e 100644 --- a/rocketpool/api/pdao/set-snapshot-address.go +++ b/rocketpool/api/pdao/set-snapshot-address.go @@ -13,7 +13,6 @@ import ( "github.com/rocket-pool/smartnode/shared/types/api" cfgtypes "github.com/rocket-pool/smartnode/shared/types/config" apiutils "github.com/rocket-pool/smartnode/shared/utils/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -134,12 +133,6 @@ func setSignallingAddress(c *cli.Command, signallingAddress common.Address, sign fmt.Println("Error parsing signature", err) } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Call SetSigner on RocketSignerRegistry tx, err := reg.SetSigner(opts, signallingAddress, sig.V, sig.R, sig.S) if err != nil { @@ -252,12 +245,6 @@ func clearSignallingAddress(c *cli.Command, opts *bind.TransactOpts) (*api.PDAOC response := api.PDAOClearSignallingAddressResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Clear the signalling address tx, err := reg.ClearSigner(opts) if err != nil { diff --git a/rocketpool/api/pdao/update-recurring-spend.go b/rocketpool/api/pdao/update-recurring-spend.go index 69dcc3192..77a2916df 100644 --- a/rocketpool/api/pdao/update-recurring-spend.go +++ b/rocketpool/api/pdao/update-recurring-spend.go @@ -1,7 +1,6 @@ package pdao import ( - "fmt" "math/big" "time" @@ -11,7 +10,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/node" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -101,13 +99,6 @@ func proposeRecurringSpendUpdate(c *cli.Command, contractName string, recipient // Response response := api.PDAOProposeOneTimeSpendResponse{} - // Get node account - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Propose pollard, err := getPollard(rp, cfg, bc, blockNumber) if err != nil { diff --git a/rocketpool/api/pdao/vote-proposal.go b/rocketpool/api/pdao/vote-proposal.go index 6d5496450..6cb3ad237 100644 --- a/rocketpool/api/pdao/vote-proposal.go +++ b/rocketpool/api/pdao/vote-proposal.go @@ -1,8 +1,6 @@ package pdao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/rocket-pool/smartnode/bindings/dao/protocol" @@ -13,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/proposals" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canVoteOnProposal(c *cli.Command, proposalId uint64, voteDirection types.VoteDirection) (*api.CanVoteOnPDAOProposalResponse, error) { @@ -165,12 +162,6 @@ func voteOnProposal(c *cli.Command, proposalId uint64, voteDirection types.VoteD return nil, err } - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Vote on proposal hash, err := protocol.VoteOnProposal(rp, proposalId, voteDirection, totalDelegatedVP, nodeIndex, proof, opts) if err != nil { diff --git a/rocketpool/api/pdao/voting.go b/rocketpool/api/pdao/voting.go index e308e06b6..fabf4095f 100644 --- a/rocketpool/api/pdao/voting.go +++ b/rocketpool/api/pdao/voting.go @@ -1,8 +1,6 @@ package pdao import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/urfave/cli/v3" @@ -10,7 +8,6 @@ import ( "github.com/rocket-pool/smartnode/bindings/network" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func estimateSetVotingDelegateGas(c *cli.Command, address common.Address) (*api.PDAOCanSetVotingDelegateResponse, error) { @@ -62,12 +59,6 @@ func setVotingDelegate(c *cli.Command, address common.Address, opts *bind.Transa // Response response := api.PDAOSetVotingDelegateResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Set the delegate tx, err := network.SetVotingDelegate(rp, address, opts) if err != nil { diff --git a/rocketpool/api/queue/assign-deposits.go b/rocketpool/api/queue/assign-deposits.go index 4541df2c2..014e527a9 100644 --- a/rocketpool/api/queue/assign-deposits.go +++ b/rocketpool/api/queue/assign-deposits.go @@ -1,7 +1,6 @@ package queue import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canAssignDeposits(c *cli.Command, max int64) (*api.CanAssignDepositsResponse, error) { @@ -88,12 +86,6 @@ func assignDeposits(c *cli.Command, max int64, opts *bind.TransactOpts) (*api.As // Response response := api.AssignDepositsResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Assign deposits hash, err := deposit.AssignDeposits(rp, big.NewInt(max), opts) if err != nil { diff --git a/rocketpool/api/queue/process.go b/rocketpool/api/queue/process.go index 565256ebe..2845a3ddf 100644 --- a/rocketpool/api/queue/process.go +++ b/rocketpool/api/queue/process.go @@ -1,7 +1,6 @@ package queue import ( - "fmt" "math/big" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canProcessQueue(c *cli.Command, max int64) (*api.CanProcessQueueResponse, error) { @@ -89,12 +87,6 @@ func processQueue(c *cli.Command, max int64, opts *bind.TransactOpts) (*api.Proc // Response response := api.ProcessQueueResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Process queue hash, err := deposit.AssignDeposits(rp, big.NewInt(max), opts) diff --git a/rocketpool/api/security/cancel-proposal.go b/rocketpool/api/security/cancel-proposal.go index 2f6275fc4..f67c8c9b4 100644 --- a/rocketpool/api/security/cancel-proposal.go +++ b/rocketpool/api/security/cancel-proposal.go @@ -2,7 +2,6 @@ package security import ( "bytes" - "fmt" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -14,7 +13,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canCancelProposal(c *cli.Command, proposalId uint64) (*api.SecurityCanCancelProposalResponse, error) { @@ -107,12 +105,6 @@ func cancelProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) // Response response := api.SecurityCancelProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Cancel proposal hash, err := security.CancelProposal(rp, proposalId, opts) if err != nil { diff --git a/rocketpool/api/security/execute-proposal.go b/rocketpool/api/security/execute-proposal.go index bd19ca5dd..8042b6e14 100644 --- a/rocketpool/api/security/execute-proposal.go +++ b/rocketpool/api/security/execute-proposal.go @@ -1,8 +1,6 @@ package security import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao" @@ -13,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canExecuteProposal(c *cli.Command, proposalId uint64) (*api.SecurityCanExecuteProposalResponse, error) { @@ -99,12 +96,6 @@ func executeProposal(c *cli.Command, proposalId uint64, opts *bind.TransactOpts) // Response response := api.SecurityExecuteProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Cancel proposal hash, err := security.ExecuteProposal(rp, proposalId, opts) if err != nil { diff --git a/rocketpool/api/security/join.go b/rocketpool/api/security/join.go index 58e09896b..cd9422065 100644 --- a/rocketpool/api/security/join.go +++ b/rocketpool/api/security/join.go @@ -1,8 +1,6 @@ package security import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao/security" @@ -11,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canJoin(c *cli.Command) (*api.SecurityCanJoinResponse, error) { @@ -97,10 +94,6 @@ func join(c *cli.Command, opts *bind.TransactOpts) (*api.SecurityJoinResponse, e response := api.SecurityJoinResponse{} // Join - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } hash, err := security.Join(rp, opts) if err != nil { return nil, err diff --git a/rocketpool/api/security/leave.go b/rocketpool/api/security/leave.go index 920b1d45c..8db9737c1 100644 --- a/rocketpool/api/security/leave.go +++ b/rocketpool/api/security/leave.go @@ -1,8 +1,6 @@ package security import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao/security" @@ -11,7 +9,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canLeave(c *cli.Command) (*api.SecurityCanLeaveResponse, error) { @@ -86,12 +83,6 @@ func leave(c *cli.Command, opts *bind.TransactOpts) (*api.SecurityLeaveResponse, // Response response := api.SecurityLeaveResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Leave hash, err := security.Leave(rp, opts) if err != nil { diff --git a/rocketpool/api/security/propose-leave.go b/rocketpool/api/security/propose-leave.go index fcbe5076d..bc4fe3061 100644 --- a/rocketpool/api/security/propose-leave.go +++ b/rocketpool/api/security/propose-leave.go @@ -1,8 +1,6 @@ package security import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao/security" @@ -10,7 +8,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canProposeLeave(c *cli.Command) (*api.SecurityCanProposeLeaveResponse, error) { @@ -80,12 +77,6 @@ func proposeLeave(c *cli.Command, opts *bind.TransactOpts) (*api.SecurityPropose // Response response := api.SecurityProposeLeaveResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit proposal hash, err := security.RequestLeave(rp, opts) if err != nil { diff --git a/rocketpool/api/security/propose-settings.go b/rocketpool/api/security/propose-settings.go index ed9c31bf4..3b44f2871 100644 --- a/rocketpool/api/security/propose-settings.go +++ b/rocketpool/api/security/propose-settings.go @@ -11,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" cliutils "github.com/rocket-pool/smartnode/shared/utils/cli" - "github.com/rocket-pool/smartnode/shared/utils/eth1" "github.com/urfave/cli/v3" ) @@ -233,12 +232,6 @@ func proposeSetting(c *cli.Command, contractName string, settingName string, val // Response response := api.ProposePDAOSettingResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Submit the proposal var proposalID uint64 var hash common.Hash diff --git a/rocketpool/api/security/vote-proposal.go b/rocketpool/api/security/vote-proposal.go index 45407f74e..54b097fbe 100644 --- a/rocketpool/api/security/vote-proposal.go +++ b/rocketpool/api/security/vote-proposal.go @@ -1,8 +1,6 @@ package security import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao" @@ -13,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canVoteOnProposal(c *cli.Command, proposalId uint64) (*api.SecurityCanVoteOnProposalResponse, error) { @@ -127,12 +124,6 @@ func voteOnProposal(c *cli.Command, proposalId uint64, support bool, opts *bind. // Response response := api.SecurityVoteOnProposalResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Vote on proposal hash, err := security.VoteOnProposal(rp, proposalId, support, opts) if err != nil { diff --git a/rocketpool/api/upgrade/execute-upgrade.go b/rocketpool/api/upgrade/execute-upgrade.go index 98d1ec82f..fde627447 100644 --- a/rocketpool/api/upgrade/execute-upgrade.go +++ b/rocketpool/api/upgrade/execute-upgrade.go @@ -1,8 +1,6 @@ package upgrade import ( - "fmt" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/rocket-pool/smartnode/bindings/dao/trustednode" @@ -13,7 +11,6 @@ import ( "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/types/api" - "github.com/rocket-pool/smartnode/shared/utils/eth1" ) func canExecuteUpgrade(c *cli.Command, upgradeProposalId uint64) (*api.CanExecuteTNDAOUpgradeResponse, error) { @@ -113,12 +110,6 @@ func executeUpgrade(c *cli.Command, upgradeProposalId uint64, opts *bind.Transac // Response response := api.ExecuteTNDAOUpgradeResponse{} - // Override the provided pending TX if requested - err = eth1.CheckForNonceOverride(c, opts) - if err != nil { - return nil, fmt.Errorf("Error checking for nonce override: %w", err) - } - // Execute upgrade hash, err := upgrades.ExecuteUpgrade(rp, upgradeProposalId, opts) if err != nil { diff --git a/rocketpool/rocketpool.go b/rocketpool/rocketpool.go index ed2c971fc..f2edbf96c 100644 --- a/rocketpool/rocketpool.go +++ b/rocketpool/rocketpool.go @@ -51,10 +51,6 @@ func main() { Aliases: []string{"l"}, Usage: "Desired gas limit", }, - &cli.StringFlag{ - Name: "nonce", - Usage: "Use this flag to explicitly specify the nonce that this transaction should use, so it can override an existing 'stuck' transaction", - }, &cli.StringFlag{ Name: "metricsAddress", Aliases: []string{"m"}, diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index 71e3c112b..b6a1f3604 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -1293,6 +1293,9 @@ func (c *Client) callHTTPAPICtx(ctx context.Context, method, path string, params if c.globals.GasLimit > 0 { params.Set("gasLimit", strconv.FormatFloat(float64(c.globals.GasLimit), 'f', 0, 64)) } + if c.globals.CustomNonce != nil { + params.Set("nonce", c.globals.CustomNonce.String()) + } body := []byte(params.Encode()) req, err = http.NewRequestWithContext(ctx, http.MethodPost, target, bytes.NewReader(body)) if err == nil { diff --git a/shared/services/services.go b/shared/services/services.go index 77a79d034..17619af2d 100644 --- a/shared/services/services.go +++ b/shared/services/services.go @@ -119,6 +119,11 @@ func GetNodeAccountTransactorFromRequest(c *cli.Command, r *http.Request) (*bind opts.GasLimit = gasLimit } } + if nonceStr := r.FormValue("nonce"); nonceStr != "" { + if nonce, ok := new(big.Int).SetString(nonceStr, 0); ok { + opts.Nonce = nonce + } + } return opts, nil } diff --git a/shared/utils/eth1/eth1.go b/shared/utils/eth1/eth1.go index 3f0260ee1..c7edf738a 100644 --- a/shared/utils/eth1/eth1.go +++ b/shared/utils/eth1/eth1.go @@ -1,7 +1,6 @@ package eth1 import ( - "context" "fmt" "math/big" @@ -11,55 +10,8 @@ import ( "github.com/rocket-pool/smartnode/bindings/rocketpool" "github.com/rocket-pool/smartnode/shared/services" "github.com/rocket-pool/smartnode/shared/services/config" - "github.com/urfave/cli/v3" ) -// Sets the nonce of the provided transaction options to the latest nonce if requested -func CheckForNonceOverride(c *cli.Command, opts *bind.TransactOpts) error { - - customNonceString := c.Root().String("nonce") - if customNonceString != "" { - customNonce, success := big.NewInt(0).SetString(customNonceString, 0) - if !success { - return fmt.Errorf("Invalid nonce: %s", customNonceString) - } - - // Do a sanity check to make sure the provided nonce is for a pending transaction - // otherwise the user is burning gas for no reason - ec, err := services.GetEthClient(c) - if err != nil { - return fmt.Errorf("Could not retrieve ETH1 client: %w", err) - } - - // Make sure it's not higher than the next available nonce - nextNonceUint, err := ec.PendingNonceAt(context.Background(), opts.From) - if err != nil { - return fmt.Errorf("Could not get next available nonce: %w", err) - } - - nextNonce := big.NewInt(0).SetUint64(nextNonceUint) - if customNonce.Cmp(nextNonce) == 1 { - return fmt.Errorf("Can't use nonce %s because it's greater than the next available nonce (%d).", customNonceString, nextNonceUint) - } - - // Make sure the nonce hasn't already been included in a block - latestProposedNonceUint, err := ec.NonceAt(context.Background(), opts.From, nil) - if err != nil { - return fmt.Errorf("Could not get latest nonce: %w", err) - } - - latestProposedNonce := big.NewInt(0).SetUint64(latestProposedNonceUint) - if customNonce.Cmp(latestProposedNonce) == -1 { - return fmt.Errorf("Can't use nonce %s because it has already been included in a block.", customNonceString) - } - - // It points to a pending transaction, so this is a valid thing to do - opts.Nonce = customNonce - } - return nil - -} - // Determines if the primary EC can be used for historical queries, or if the Archive EC is required func GetBestApiClient(primary *rocketpool.RocketPool, cfg *config.RocketPoolConfig, printMessage func(string), blockNumber *big.Int) (*rocketpool.RocketPool, error) { From d0d0f4687a2a03058c07af713dae87b7b110816c Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:39:06 -0300 Subject: [PATCH 19/24] Remove timeout when waiting for tx to be included in a block --- bindings/utils/wait.go | 41 ++++++++++++++-------------- rocketpool/api/wait.go | 2 +- shared/services/rocketpool/api.go | 5 ++-- shared/services/rocketpool/client.go | 1 - 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/bindings/utils/wait.go b/bindings/utils/wait.go index 7a9649c42..f68ae61d9 100644 --- a/bindings/utils/wait.go +++ b/bindings/utils/wait.go @@ -3,7 +3,6 @@ package utils import ( "context" "errors" - "fmt" "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,32 +11,30 @@ import ( "github.com/rocket-pool/smartnode/bindings/rocketpool" ) -// Wait for a transaction to get mined -func WaitForTransaction(client rocketpool.ExecutionClient, hash common.Hash) (*types.Receipt, error) { - +// Wait for a transaction to get included, respecting the provided context for cancellation. +// The transaction lookup retries indefinitely (with 1-second pauses) until found or ctx is done. +func WaitForTransactionWithContext(ctx context.Context, client rocketpool.ExecutionClient, hash common.Hash) (*types.Receipt, error) { var tx *types.Transaction - var err error - // Get the transaction from its hash, retrying for 30 sec if it wasn't found - for i := 0; i < 30; i++ { - if i == 29 { - return nil, fmt.Errorf("Transaction not found after 30 seconds.") + // Get the transaction from its hash, retrying until found or ctx is cancelled. + for { + var err error + tx, _, err = client.TransactionByHash(ctx, hash) + if err == nil { + break } - - tx, _, err = client.TransactionByHash(context.Background(), hash) - if err != nil { - if err.Error() == "not found" { - time.Sleep(1 * time.Second) - continue - } + if err.Error() != "not found" { return nil, err - } else { - break + } + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-time.After(1 * time.Second): } } // Wait for transaction to be mined - txReceipt, err := bind.WaitMined(context.Background(), client, tx) + txReceipt, err := bind.WaitMined(ctx, client, tx) if err != nil { return nil, err } @@ -47,6 +44,10 @@ func WaitForTransaction(client rocketpool.ExecutionClient, hash common.Hash) (*t return txReceipt, errors.New("Transaction failed with status 0") } - // Return return txReceipt, nil } + +// Wait for a transaction to get mined +func WaitForTransaction(client rocketpool.ExecutionClient, hash common.Hash) (*types.Receipt, error) { + return WaitForTransactionWithContext(context.Background(), client, hash) +} diff --git a/rocketpool/api/wait.go b/rocketpool/api/wait.go index dc30b51b2..0dc873a80 100644 --- a/rocketpool/api/wait.go +++ b/rocketpool/api/wait.go @@ -23,7 +23,7 @@ func RegisterWaitRoute(mux *http.ServeMux, c *cli.Command) { return } response := apitypes.APIResponse{} - _, err = utils.WaitForTransaction(rp.Client, hash) + _, err = utils.WaitForTransactionWithContext(r.Context(), rp.Client, hash) apiutils.WriteResponse(w, &response, err) }) } diff --git a/shared/services/rocketpool/api.go b/shared/services/rocketpool/api.go index d2a633272..ccc80b24e 100644 --- a/shared/services/rocketpool/api.go +++ b/shared/services/rocketpool/api.go @@ -1,6 +1,7 @@ package rocketpool import ( + "context" "fmt" "net/url" @@ -9,9 +10,9 @@ import ( "github.com/rocket-pool/smartnode/shared/types/api" ) -// Wait for a transaction +// Wait for a transaction — no timeout; blocks until the tx is included or the caller cancels. func (c *Client) WaitForTransaction(txHash common.Hash) (api.APIResponse, error) { - responseBytes, err := c.callHTTPAPI("GET", "/api/wait", url.Values{"txHash": {txHash.Hex()}}) + responseBytes, err := c.callHTTPAPICtx(context.Background(), "GET", "/api/wait", url.Values{"txHash": {txHash.Hex()}}) if err != nil { return api.APIResponse{}, fmt.Errorf("Error waiting for tx: %w", err) } diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index b6a1f3604..51299916d 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -1253,7 +1253,6 @@ func (c *Client) getAPIURL() string { // path is the URL path, e.g. "/api/node/status". // params are appended as query string parameters for GET or as a form body for POST. // The response body is returned as-is; callers unmarshal it the same way -// The response body is returned as-is; callers unmarshal it. func (c *Client) callHTTPAPI(method, path string, params url.Values) ([]byte, error) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() From c72e6cc8c6adf4b885b5ec406ca49aee33bd11a0 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Tue, 31 Mar 2026 13:52:26 -0300 Subject: [PATCH 20/24] Remove the daemon-path flag --- README.md | 1 - rocketpool-cli/rocketpool-cli.go | 6 ------ shared/services/rocketpool/client.go | 13 ++++++------- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 95553f5f4..9426d9444 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,6 @@ The following commands are available via the Smart Node client: - `rocketpool --allow-root, -r` - Allow rocketpool to be run as the root user - `rocketpool --config-path path, -c path` - Rocket Pool config asset path (default: "~/.rocketpool") -- `rocketpool --daemon-path path, -d path` - Interact with a Rocket Pool service daemon at a path on the host OS, running outside of docker - `rocketpool --maxFee value, -f value` - The max fee (including the priority fee) you want a transaction to cost, in gwei (default: 0) - `rocketpool --maxPrioFee value, -i value` - The max priority fee you want a transaction to use, in gwei (default: 0) - `rocketpool --gasLimit value, -l value` - [DEPRECATED] Desired gas limit (default: 0) diff --git a/rocketpool-cli/rocketpool-cli.go b/rocketpool-cli/rocketpool-cli.go index d3edfcdab..1f89713ee 100644 --- a/rocketpool-cli/rocketpool-cli.go +++ b/rocketpool-cli/rocketpool-cli.go @@ -62,11 +62,6 @@ func main() { Usage: "Rocket Pool config asset `path`", Value: "~/.rocketpool", }, - &cli.StringFlag{ - Name: "daemon-path", - Aliases: []string{"d"}, - Usage: "Interact with a Rocket Pool service daemon at a `path` on the host OS, running outside of docker", - }, &cli.Float64Flag{ Name: "maxFee", Aliases: []string{"f"}, @@ -153,7 +148,6 @@ func main() { Defaults := rocketpool.Globals{ ConfigPath: os.ExpandEnv(c.Root().String("config-path")), - DaemonPath: os.ExpandEnv(c.Root().String("daemon-path")), MaxFee: c.Root().Float64("maxFee"), MaxPrioFee: c.Root().Float64("maxPrioFee"), GasLimit: c.Root().Uint64("gasLimit"), diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index 51299916d..f06b359bc 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -70,7 +70,6 @@ func SyncRatioToPercent(in float64) float64 { type Globals struct { ConfigPath string - DaemonPath string MaxFee float64 MaxPrioFee float64 GasLimit uint64 @@ -217,7 +216,7 @@ func (c *Client) LoadConfig() (*config.RocketPoolConfig, bool, error) { } // Config wasn't loaded, but there was no error- we should create one. - return config.NewRocketPoolConfig(c.ConfigPath(), c.globals.DaemonPath != ""), true, nil + return config.NewRocketPoolConfig(c.ConfigPath(), false), true, nil } // Load the backup config @@ -1028,11 +1027,6 @@ func (c *Client) checkIfCommandExists(command string) (bool, error) { // Build a docker compose command func (c *Client) compose(composeFiles []string, args string) (string, error) { - // Cancel if running in non-docker mode - if c.globals.DaemonPath != "" { - return "", errors.New("command unavailable in Native Mode (with '--daemon-path' option specified)") - } - // Get the expanded config path expandedConfigPath, err := homedir.Expand(c.ConfigPath()) if err != nil { @@ -1049,6 +1043,11 @@ func (c *Client) compose(composeFiles []string, args string) (string, error) { return "", fmt.Errorf("Settings file not found. Please run `rocketpool service config` to set up your Smart Node before starting it.") } + // Cancel if running in native mode + if cfg.IsNativeMode { + return "", errors.New("command unavailable in Native Mode") + } + // Check config if cfg.ExecutionClientMode.Value.(cfgtypes.Mode) == cfgtypes.Mode_Unknown { return "", fmt.Errorf("You haven't selected local or external mode for your Execution (ETH1) client.\nPlease run 'rocketpool service config' before running this command.") From c66b31f4eb2d5097a1ab67ea57820ca42506d5a7 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Tue, 31 Mar 2026 15:51:22 -0300 Subject: [PATCH 21/24] use-latest-delegate as a cmd flag --- rocketpool-cli/megapool/commands.go | 32 ++++++++++++++-------------- rocketpool-cli/megapool/delegate.go | 33 ++++++++++++++++++++++++----- rocketpool-cli/rocketpool-cli.go | 1 + 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/rocketpool-cli/megapool/commands.go b/rocketpool-cli/megapool/commands.go index a0230890f..cc4ba4a12 100644 --- a/rocketpool-cli/megapool/commands.go +++ b/rocketpool-cli/megapool/commands.go @@ -409,35 +409,35 @@ func RegisterCommands(app *cli.Command, name string, aliases []string) { return distribute(c.Bool("yes")) }, }, - // Add set-use-latest-delegate command { Name: "set-use-latest-delegate", Aliases: []string{"l"}, Usage: "Set the megapool to always use the latest delegate", - UsageText: "rocketpool megapool set-use-latest-delegate [true|false]", - Arguments: []cli.Argument{ - &cli.StringArgs{ - Name: "use-latest-delegate", - Min: 1, - Max: 1, + UsageText: "rocketpool megapool set-use-latest-delegate", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "use-latest-delegate", + Usage: "Enable (true) or disable (false) automatic using the latest delegate; omit to be prompted based on the current setting", + }, + &cli.BoolFlag{ + Name: "yes", + Usage: "Automatically confirm the action", }, }, Action: func(ctx context.Context, c *cli.Command) error { - vals := c.StringArgs("use-latest-delegate") - useLatest, err := cliutils.ValidateBool("use-latest-delegate", vals[0]) - if err != nil { + if err := cliutils.ValidateArgCount(c, 0); err != nil { return err } + var useLatest *bool + if c.IsSet("use-latest-delegate") { + val := c.Bool("use-latest-delegate") + useLatest = &val + } + return setUseLatestDelegateMegapool(useLatest, c.Bool("yes")) }, - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "yes", - Usage: "Automatically confirm the action", - }, - }, }, }, }) diff --git a/rocketpool-cli/megapool/delegate.go b/rocketpool-cli/megapool/delegate.go index 78dc9d873..c5d4cb531 100644 --- a/rocketpool-cli/megapool/delegate.go +++ b/rocketpool-cli/megapool/delegate.go @@ -9,7 +9,7 @@ import ( "github.com/rocket-pool/smartnode/shared/utils/cli/prompt" ) -func setUseLatestDelegateMegapool(setting bool, yes bool) error { +func setUseLatestDelegateMegapool(setting *bool, yes bool) error { // Get RP client rp, err := rocketpool.NewClient().WithReady() if err != nil { @@ -29,26 +29,49 @@ func setUseLatestDelegateMegapool(setting bool, yes bool) error { return nil } + // If no flag was provided, prompt the user based on the current setting + if setting == nil { + currentSetting := status.Megapool.UseLatestDelegate + var desired bool + if currentSetting { + fmt.Println("Your megapool currently has automatic delegate upgrades enabled.") + if !prompt.Confirm("Would you like to disable automatic delegate upgrades?") { + fmt.Println("No changes made.") + return nil + } + desired = false + } else { + fmt.Println("Your megapool currently has automatic delegate upgrades disabled.") + if !prompt.Confirm("Would you like to enable automatic delegate upgrades?") { + fmt.Println("No changes made.") + return nil + } + desired = true + } + setting = &desired + } + megapoolAddress := status.Megapool.Address // Print message we're updating the setting - if setting == true { + if *setting { fmt.Printf("Updating the use-latest-delegate setting for megapool %s to enabled...\n", megapoolAddress.Hex()) } else { fmt.Printf("Updating the use-latest-delegate setting for megapool %s to disabled...\n", megapoolAddress.Hex()) } // Get the gas estimate - canResponse, err := rp.CanSetUseLatestDelegateMegapool(megapoolAddress, setting) + canResponse, err := rp.CanSetUseLatestDelegateMegapool(megapoolAddress, *setting) if err != nil { return fmt.Errorf("error checking if megapool %s could have its use-latest-delegate flag changed: %w", megapoolAddress.Hex(), err) } if canResponse.MatchesCurrentSetting { - if setting == true { + if *setting { fmt.Printf("Could not enable use-latest-delegate on the node's megapool, the setting is already enabled.") } else { fmt.Printf("Could not disable use-latest-delegate on the node's megapool, the setting is already disabled.") } + fmt.Println() return nil } @@ -65,7 +88,7 @@ func setUseLatestDelegateMegapool(setting bool, yes bool) error { } // Update flag - response, err := rp.SetUseLatestDelegateMegapool(megapoolAddress, setting) + response, err := rp.SetUseLatestDelegateMegapool(megapoolAddress, *setting) if err != nil { fmt.Printf("Could not set use latest delegate for megapool %s: %s. \n", megapoolAddress.Hex(), err) return nil diff --git a/rocketpool-cli/rocketpool-cli.go b/rocketpool-cli/rocketpool-cli.go index 1f89713ee..568761bd9 100644 --- a/rocketpool-cli/rocketpool-cli.go +++ b/rocketpool-cli/rocketpool-cli.go @@ -196,6 +196,7 @@ func main() { } if len(response.Alerts) > 0 { + fmt.Println() color.YellowPrintln("=== Alerts ===") for i, alert := range response.Alerts { fmt.Println(alert.ColorString()) From 0a0a624bd2cc4573bcad4aa9a825180b989d79a3 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Wed, 1 Apr 2026 14:03:05 -0300 Subject: [PATCH 22/24] Add response errors --- rocketpool/node/http.go | 30 +++++++++++++++++++++++++++++- rocketpool/node/routes/routes.go | 7 +++++++ shared/utils/api/http.go | 30 +++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/rocketpool/node/http.go b/rocketpool/node/http.go index 2ae0d3df8..f6a62831f 100644 --- a/rocketpool/node/http.go +++ b/rocketpool/node/http.go @@ -5,6 +5,7 @@ import ( "fmt" "log" "net/http" + "time" "github.com/urfave/cli/v3" @@ -17,6 +18,33 @@ type httpServer struct { mux *http.ServeMux } +// statusRecorder wraps http.ResponseWriter to capture the written status code. +type statusRecorder struct { + http.ResponseWriter + status int +} + +func (r *statusRecorder) WriteHeader(code int) { + r.status = code + r.ResponseWriter.WriteHeader(code) +} + +// Write implements the ResponseWriter interface so we don't lose the original +// Write behavior when wrapping. +func (r *statusRecorder) Write(b []byte) (int, error) { + return r.ResponseWriter.Write(b) +} + +// loggingMiddleware logs method, path, status code, and elapsed time for every request. +func loggingMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + rec := &statusRecorder{ResponseWriter: w, status: http.StatusOK} + next.ServeHTTP(rec, r) + log.Printf("%s %s %d %s", r.Method, r.URL.Path, rec.status, time.Since(start)) + }) +} + // startHTTP starts the node's HTTP API server and returns immediately. // The server runs in the background for the lifetime of the process. func startHTTP(ctx context.Context, c *cli.Command, cfg *config.RocketPoolConfig) { @@ -39,7 +67,7 @@ func startHTTP(ctx context.Context, c *cli.Command, cfg *config.RocketPoolConfig srv := &http.Server{ Addr: fmt.Sprintf("%s:%d", host, port), - Handler: mux, + Handler: loggingMiddleware(mux), } go func() { diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index 22f08281f..c4a9cb90b 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -18,6 +18,7 @@ import ( serviceroutes "github.com/rocket-pool/smartnode/rocketpool/api/service" upgraderoutes "github.com/rocket-pool/smartnode/rocketpool/api/upgrade" walletroutes "github.com/rocket-pool/smartnode/rocketpool/api/wallet" + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" ) // RegisterRoutes registers all HTTP API routes onto mux. @@ -41,4 +42,10 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { serviceroutes.RegisterRoutes(mux, c) upgraderoutes.RegisterRoutes(mux, c) walletroutes.RegisterRoutes(mux, c) + + // Catch-all: any path not matched by a specific route gets a JSON 404. + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + apiutils.WriteErrorResponse(w, &apiutils.NotFoundError{Path: r.URL.Path}) + }) + } diff --git a/shared/utils/api/http.go b/shared/utils/api/http.go index bd17926c9..6a3bc9a84 100644 --- a/shared/utils/api/http.go +++ b/shared/utils/api/http.go @@ -11,8 +11,22 @@ import ( "github.com/rocket-pool/smartnode/shared/types/api" ) +// BadRequestError signals that the caller supplied invalid input. +// WriteResponse maps it to HTTP 400 rather than 500. +type BadRequestError struct{ Err error } + +func (e *BadRequestError) Error() string { return e.Err.Error() } +func (e *BadRequestError) Unwrap() error { return e.Err } + +// NotFoundError signals that the requested resource or route does not exist. +// WriteResponse maps it to HTTP 404. +type NotFoundError struct{ Path string } + +func (e *NotFoundError) Error() string { return fmt.Sprintf("not found: %s", e.Path) } + // WriteResponse serialises response as JSON and writes it to w. // response must be a pointer to a struct with string fields named Status and Error. +// On error it writes 400 for BadRequestError and 500 for everything else. func WriteResponse(w http.ResponseWriter, response interface{}, responseError error) { r := reflect.ValueOf(response) if !(r.Kind() == reflect.Ptr && r.Type().Elem().Kind() == reflect.Struct) { @@ -48,8 +62,22 @@ func WriteResponse(w http.ResponseWriter, response interface{}, responseError er return } + statusCode := http.StatusOK + if ef.String() != "" { + var br *BadRequestError + var nf *NotFoundError + switch { + case errors.As(responseError, &br): + statusCode = http.StatusBadRequest + case errors.As(responseError, &nf): + statusCode = http.StatusNotFound + default: + statusCode = http.StatusInternalServerError + } + } + w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) + w.WriteHeader(statusCode) _, _ = w.Write(append(responseBytes, '\n')) } From cd85f7c0e8875eddba565932275a5dbe07a9b4d9 Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Wed, 1 Apr 2026 17:40:48 -0300 Subject: [PATCH 23/24] Revert "Remove the daemon-path flag" This reverts commit c72e6cc8c6adf4b885b5ec406ca49aee33bd11a0. --- README.md | 1 + rocketpool-cli/rocketpool-cli.go | 6 ++++++ shared/services/rocketpool/client.go | 13 +++++++------ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9426d9444..95553f5f4 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,7 @@ The following commands are available via the Smart Node client: - `rocketpool --allow-root, -r` - Allow rocketpool to be run as the root user - `rocketpool --config-path path, -c path` - Rocket Pool config asset path (default: "~/.rocketpool") +- `rocketpool --daemon-path path, -d path` - Interact with a Rocket Pool service daemon at a path on the host OS, running outside of docker - `rocketpool --maxFee value, -f value` - The max fee (including the priority fee) you want a transaction to cost, in gwei (default: 0) - `rocketpool --maxPrioFee value, -i value` - The max priority fee you want a transaction to use, in gwei (default: 0) - `rocketpool --gasLimit value, -l value` - [DEPRECATED] Desired gas limit (default: 0) diff --git a/rocketpool-cli/rocketpool-cli.go b/rocketpool-cli/rocketpool-cli.go index 568761bd9..e3d883697 100644 --- a/rocketpool-cli/rocketpool-cli.go +++ b/rocketpool-cli/rocketpool-cli.go @@ -62,6 +62,11 @@ func main() { Usage: "Rocket Pool config asset `path`", Value: "~/.rocketpool", }, + &cli.StringFlag{ + Name: "daemon-path", + Aliases: []string{"d"}, + Usage: "Interact with a Rocket Pool service daemon at a `path` on the host OS, running outside of docker", + }, &cli.Float64Flag{ Name: "maxFee", Aliases: []string{"f"}, @@ -148,6 +153,7 @@ func main() { Defaults := rocketpool.Globals{ ConfigPath: os.ExpandEnv(c.Root().String("config-path")), + DaemonPath: os.ExpandEnv(c.Root().String("daemon-path")), MaxFee: c.Root().Float64("maxFee"), MaxPrioFee: c.Root().Float64("maxPrioFee"), GasLimit: c.Root().Uint64("gasLimit"), diff --git a/shared/services/rocketpool/client.go b/shared/services/rocketpool/client.go index f06b359bc..51299916d 100644 --- a/shared/services/rocketpool/client.go +++ b/shared/services/rocketpool/client.go @@ -70,6 +70,7 @@ func SyncRatioToPercent(in float64) float64 { type Globals struct { ConfigPath string + DaemonPath string MaxFee float64 MaxPrioFee float64 GasLimit uint64 @@ -216,7 +217,7 @@ func (c *Client) LoadConfig() (*config.RocketPoolConfig, bool, error) { } // Config wasn't loaded, but there was no error- we should create one. - return config.NewRocketPoolConfig(c.ConfigPath(), false), true, nil + return config.NewRocketPoolConfig(c.ConfigPath(), c.globals.DaemonPath != ""), true, nil } // Load the backup config @@ -1027,6 +1028,11 @@ func (c *Client) checkIfCommandExists(command string) (bool, error) { // Build a docker compose command func (c *Client) compose(composeFiles []string, args string) (string, error) { + // Cancel if running in non-docker mode + if c.globals.DaemonPath != "" { + return "", errors.New("command unavailable in Native Mode (with '--daemon-path' option specified)") + } + // Get the expanded config path expandedConfigPath, err := homedir.Expand(c.ConfigPath()) if err != nil { @@ -1043,11 +1049,6 @@ func (c *Client) compose(composeFiles []string, args string) (string, error) { return "", fmt.Errorf("Settings file not found. Please run `rocketpool service config` to set up your Smart Node before starting it.") } - // Cancel if running in native mode - if cfg.IsNativeMode { - return "", errors.New("command unavailable in Native Mode") - } - // Check config if cfg.ExecutionClientMode.Value.(cfgtypes.Mode) == cfgtypes.Mode_Unknown { return "", fmt.Errorf("You haven't selected local or external mode for your Execution (ETH1) client.\nPlease run 'rocketpool service config' before running this command.") From bd5ecc79622ac81e54ce6c534125fb161364799b Mon Sep 17 00:00:00 2001 From: Fornax <23104993+0xfornax@users.noreply.github.com> Date: Wed, 1 Apr 2026 23:21:19 -0300 Subject: [PATCH 24/24] Add debug endpoint to fetch rewards events --- bindings/rewards/rewards.go | 144 ++++++++++++++++++++ rocketpool/api/debug/rewards-event.go | 61 +++++++++ rocketpool/api/debug/routes.go | 28 ++++ rocketpool/node/routes/routes.go | 2 + shared/services/rewards/execution-client.go | 4 +- shared/types/api/debug.go | 20 +++ 6 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 rocketpool/api/debug/rewards-event.go create mode 100644 rocketpool/api/debug/routes.go create mode 100644 shared/types/api/debug.go diff --git a/bindings/rewards/rewards.go b/bindings/rewards/rewards.go index 1e5264adb..051542e5c 100644 --- a/bindings/rewards/rewards.go +++ b/bindings/rewards/rewards.go @@ -818,6 +818,150 @@ func getMainnetIntervalRewardsEvent(rp *rocketpool.RocketPool, index uint64) (Re intervalEndTime = time.Unix(1746682539, 0) submissionTime = time.Unix(1746691523, 0) userETH.SetString("38934754761348367759", 10) + case 36: + treasuryRPL.SetString("22048941282103056576253", 10) + trustedNodeRPL.SetString("2004449207463914234114", 10) + nodeRPL.SetString("56124577808989598554500", 10) + executionBlock = big.NewInt(22636374) + consensusBlock = big.NewInt(11856479) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0x704c7c2f6faeb97b20535a9a325e9ba573ec066ee579853b3e94b175114a8fd7") + intervalStartTime = time.Unix(1746682539, 0) + intervalEndTime = time.Unix(1749101739, 0) + submissionTime = time.Unix(1749113279, 0) + nodeETH.SetString("50039863506253385959", 10) + userETH.SetString("57244908435972245571", 10) + case 37: + treasuryRPL.SetString("22131620846710572152925", 10) + trustedNodeRPL.SetString("2011965531519142922898", 10) + nodeRPL.SetString("56335034882536001840574", 10) + nodeETH.SetString("45418705066756834715", 10) + executionBlock = big.NewInt(22836652) + consensusBlock = big.NewInt(12058079) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0xf4db744c50762a7ae1b19ee26120a582207eb1c535614711aae4cc5c598e42cf") + intervalStartTime = time.Unix(1749101739, 0) + intervalEndTime = time.Unix(1751520939, 0) + submissionTime = time.Unix(1751532611, 0) + userETH.SetString("48318015461156177248", 10) + case 38: + treasuryRPL.SetString("22214610444816577609208", 10) + trustedNodeRPL.SetString("2019510040437870691659", 10) + nodeRPL.SetString("56546281132260379365673", 10) + nodeETH.SetString("40700127824685134045", 10) + executionBlock = big.NewInt(23037044) + consensusBlock = big.NewInt(12259679) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0xf7809e999791fb6c73712c7d281624020ba773dc144fdfbb41c86b2e3cbb42fd") + intervalStartTime = time.Unix(1751520939, 0) + intervalEndTime = time.Unix(1753940139, 0) + submissionTime = time.Unix(1753948367, 0) + userETH.SetString("40528725716465757725", 10) + case 39: + treasuryRPL.SetString("22297911238990936999935", 10) + trustedNodeRPL.SetString("2027082839908266999911", 10) + nodeRPL.SetString("56758319517431475996754", 10) + nodeETH.SetString("34921409718655333629", 10) + executionBlock = big.NewInt(23237567) + consensusBlock = big.NewInt(12461279) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0xec51162c8af79d86e4b8f6546ec0e1ec3b4172b12574893e938c4f5bdd408efe") + intervalStartTime = time.Unix(1753940139, 0) + intervalEndTime = time.Unix(1756359339, 0) + submissionTime = time.Unix(1756395407, 0) + userETH.SetString("31594532680318853963", 10) + case 40: + // {"status":"success","error":"","found":true,"index":"40","executionBlock":"23438005","consensusBlock":"12662879","merkleRoot":"0x2ad908aa47f988d09dd9884c8026e6213262e231bab0d5051eedb2bef6aefe1e","intervalsPassed":"1","treasuryRPL":"22381524396162942297937","trustedNodeRPL":["2034684036014812936091"],"nodeRPL":["56971153008414762209929"],"nodeETH":["24246940457789627532"],"userETH":"13888515305764133572","intervalStartTime":1756359339,"intervalEndTime":1758778539,"submissionTime":1758785783} + treasuryRPL.SetString("22381524396162942297937", 10) + trustedNodeRPL.SetString("2034684036014812936091", 10) + nodeRPL.SetString("56971153008414762209929", 10) + nodeETH.SetString("24246940457789627532", 10) + executionBlock = big.NewInt(23438005) + consensusBlock = big.NewInt(12662879) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0x2ad908aa47f988d09dd9884c8026e6213262e231bab0d5051eedb2bef6aefe1e") + intervalStartTime = time.Unix(1756359339, 0) + intervalEndTime = time.Unix(1758778539, 0) + submissionTime = time.Unix(1758785783, 0) + userETH.SetString("13888515305764133572", 10) + case 41: + treasuryRPL.SetString("22465451087637660464639", 10) + trustedNodeRPL.SetString("2042313735239787314880", 10) + nodeRPL.SetString("57184784586714044816063", 10) + nodeETH.SetString("43676270282606810107", 10) + executionBlock = big.NewInt(23638162) + consensusBlock = big.NewInt(12864479) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0xe8af8737484cfd3d3fd5106ef189333e92f9bbc2de0ac057f4c01c473b2ec958") + intervalStartTime = time.Unix(1758778539, 0) + intervalEndTime = time.Unix(1761197739, 0) + submissionTime = time.Unix(1761205211, 0) + userETH.SetString("47268078777290226308", 10) + case 42: + treasuryRPL.SetString("22549692489112341819332", 10) + trustedNodeRPL.SetString("2049972044464758347124", 10) + nodeRPL.SetString("57399217245013233718952", 10) + nodeETH.SetString("25631914712861974454", 10) + executionBlock = big.NewInt(23838215) + consensusBlock = big.NewInt(13066079) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0x9f8c89596b48d377279bf703444a2e0cd5e98ac4cc0f5c490324c394c1ba3ce8") + intervalStartTime = time.Unix(1761197739, 0) + intervalEndTime = time.Unix(1763616939, 0) + submissionTime = time.Unix(1763642831, 0) + userETH.SetString("17561894202841328207", 10) + case 43: + treasuryRPL.SetString("22634249780692889936981", 10) + trustedNodeRPL.SetString("2057659070972080903284", 10) + nodeRPL.SetString("57614453987218265291225", 10) + nodeETH.SetString("18947687367286040081", 10) + executionBlock = big.NewInt(24037441) + consensusBlock = big.NewInt(13267679) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0xa98c94badfa30d41fcde8a3c5ccdadadbe441e43883919567b2d45682e476ca3") + intervalStartTime = time.Unix(1763616939, 0) + intervalEndTime = time.Unix(1766036139, 0) + submissionTime = time.Unix(1766046599, 0) + userETH.SetString("8352566574518930988", 10) + case 44: + treasuryRPL.SetString("22719124146910393305039", 10) + trustedNodeRPL.SetString("2065374922446399391296", 10) + nodeRPL.SetString("57830497828499182955594", 10) + nodeETH.SetString("15367476931278801422", 10) + executionBlock = big.NewInt(24238059) + consensusBlock = big.NewInt(13469279) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0x72ed38107b2b6c1a0469800af741c04adf5563aebe5a0ae5d77fb9b2354c64a5") + intervalStartTime = time.Unix(1766036139, 0) + intervalEndTime = time.Unix(1768455339, 0) + submissionTime = time.Unix(1768461851, 0) + userETH.SetString("4223474559072201135", 10) + case 45: + treasuryRPL.SetString("22804316776737718971210", 10) + trustedNodeRPL.SetString("2073119706976156270036", 10) + nodeRPL.SetString("58047351795332375560374", 10) + nodeETH.SetString("28550894583322805236", 10) + executionBlock = big.NewInt(24438645) + consensusBlock = big.NewInt(13670879) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0x97dc8f589c86c3650a96568ab05c08a9e160aec7eb405e35ec2e62c6e1af559c") + intervalStartTime = time.Unix(1768455339, 0) + intervalEndTime = time.Unix(1770874539, 0) + submissionTime = time.Unix(1770894827, 0) + userETH.SetString("22178758316567204991", 10) + case 46: + treasuryRPL.SetString("22889828863606168413868", 10) + trustedNodeRPL.SetString("2080893533055106219373", 10) + nodeRPL.SetString("58265018925542974141956", 10) + nodeETH.SetString("19997007660595265346", 10) + executionBlock = big.NewInt(24639334) + consensusBlock = big.NewInt(13872479) + intervalsPassed = big.NewInt(1) + merkleRoot = common.HexToHash("0x8cb45bcefd498b8788e6291c4dc086694c85b495fb60e9d5b047e7b921929d48") + intervalStartTime = time.Unix(1770874539, 0) + intervalEndTime = time.Unix(1773293739, 0) + submissionTime = time.Unix(1773299819, 0) + userETH.SetString("12369109587853762785", 10) default: return RewardsEvent{}, false, nil } diff --git a/rocketpool/api/debug/rewards-event.go b/rocketpool/api/debug/rewards-event.go new file mode 100644 index 000000000..e059f3222 --- /dev/null +++ b/rocketpool/api/debug/rewards-event.go @@ -0,0 +1,61 @@ +package debug + +import ( + "github.com/urfave/cli/v3" + + "github.com/rocket-pool/smartnode/shared/services" + rprewards "github.com/rocket-pool/smartnode/shared/services/rewards" + "github.com/rocket-pool/smartnode/shared/types/api" +) + +func getRewardsEvent(c *cli.Command, interval uint64) (*api.RewardsEventResponse, error) { + if err := services.RequireRocketStorage(c); err != nil { + return nil, err + } + rp, err := services.GetRocketPool(c) + if err != nil { + return nil, err + } + cfg, err := services.GetConfig(c) + if err != nil { + return nil, err + } + + previousRewardsPoolAddresses := cfg.Smartnode.GetPreviousRewardsPoolAddresses() + rewardsClient := rprewards.NewRewardsExecutionClient(rp) + + event, err := rewardsClient.GetRewardSnapshotEvent(previousRewardsPoolAddresses, interval, nil) + if err != nil { + return nil, err + } + + response := api.RewardsEventResponse{ + Found: true, + } + + response.Index = event.Index.String() + response.ExecutionBlock = event.ExecutionBlock.String() + response.ConsensusBlock = event.ConsensusBlock.String() + response.MerkleRoot = event.MerkleRoot.Hex() + response.IntervalsPassed = event.IntervalsPassed.String() + response.TreasuryRPL = event.TreasuryRPL.String() + response.UserETH = event.UserETH.String() + response.IntervalStartTime = event.IntervalStartTime.Unix() + response.IntervalEndTime = event.IntervalEndTime.Unix() + response.SubmissionTime = event.SubmissionTime.Unix() + + response.TrustedNodeRPL = make([]string, len(event.TrustedNodeRPL)) + for i, v := range event.TrustedNodeRPL { + response.TrustedNodeRPL[i] = v.String() + } + response.NodeRPL = make([]string, len(event.NodeRPL)) + for i, v := range event.NodeRPL { + response.NodeRPL[i] = v.String() + } + response.NodeETH = make([]string, len(event.NodeETH)) + for i, v := range event.NodeETH { + response.NodeETH[i] = v.String() + } + + return &response, nil +} diff --git a/rocketpool/api/debug/routes.go b/rocketpool/api/debug/routes.go new file mode 100644 index 000000000..b97c8e761 --- /dev/null +++ b/rocketpool/api/debug/routes.go @@ -0,0 +1,28 @@ +package debug + +import ( + "fmt" + "net/http" + "strconv" + + "github.com/urfave/cli/v3" + + apiutils "github.com/rocket-pool/smartnode/shared/utils/api" +) + +func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { + mux.HandleFunc("/api/debug/rewards-event", func(w http.ResponseWriter, r *http.Request) { + raw := r.URL.Query().Get("interval") + if raw == "" { + apiutils.WriteErrorResponse(w, &apiutils.BadRequestError{Err: fmt.Errorf("missing required query parameter: interval")}) + return + } + interval, err := strconv.ParseUint(raw, 10, 64) + if err != nil { + apiutils.WriteErrorResponse(w, &apiutils.BadRequestError{Err: fmt.Errorf("invalid interval: %w", err)}) + return + } + resp, err := getRewardsEvent(c, interval) + apiutils.WriteResponse(w, resp, err) + }) +} diff --git a/rocketpool/node/routes/routes.go b/rocketpool/node/routes/routes.go index c4a9cb90b..fdbb6940a 100644 --- a/rocketpool/node/routes/routes.go +++ b/rocketpool/node/routes/routes.go @@ -7,6 +7,7 @@ import ( apiroutes "github.com/rocket-pool/smartnode/rocketpool/api" auctionroutes "github.com/rocket-pool/smartnode/rocketpool/api/auction" + debugroutes "github.com/rocket-pool/smartnode/rocketpool/api/debug" megapoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/megapool" minipoolroutes "github.com/rocket-pool/smartnode/rocketpool/api/minipool" networkroutes "github.com/rocket-pool/smartnode/rocketpool/api/network" @@ -31,6 +32,7 @@ func RegisterRoutes(mux *http.ServeMux, c *cli.Command) { apiroutes.RegisterVersionRoute(mux) apiroutes.RegisterWaitRoute(mux, c) auctionroutes.RegisterRoutes(mux, c) + debugroutes.RegisterRoutes(mux, c) megapoolroutes.RegisterRoutes(mux, c) minipoolroutes.RegisterRoutes(mux, c) networkroutes.RegisterRoutes(mux, c) diff --git a/shared/services/rewards/execution-client.go b/shared/services/rewards/execution-client.go index 081ef50de..a494b71f6 100644 --- a/shared/services/rewards/execution-client.go +++ b/shared/services/rewards/execution-client.go @@ -65,8 +65,8 @@ func (client *defaultRewardsExecutionClient) GetRewardsEvent(index uint64, rocke TrustedNodeRPL: eventHouston.TrustedNodeRPL, SubmissionTime: eventHouston.SubmissionTime, NodeRPL: eventHouston.NodeRPL, - NodeETH: rewardsEvent.NodeETH, - UserETH: rewardsEvent.UserETH, + NodeETH: eventHouston.NodeETH, + UserETH: eventHouston.UserETH, } return found, event, nil diff --git a/shared/types/api/debug.go b/shared/types/api/debug.go new file mode 100644 index 000000000..a38621b9d --- /dev/null +++ b/shared/types/api/debug.go @@ -0,0 +1,20 @@ +package api + +type RewardsEventResponse struct { + Status string `json:"status"` + Error string `json:"error"` + Found bool `json:"found"` + Index string `json:"index"` + ExecutionBlock string `json:"executionBlock"` + ConsensusBlock string `json:"consensusBlock"` + MerkleRoot string `json:"merkleRoot"` + IntervalsPassed string `json:"intervalsPassed"` + TreasuryRPL string `json:"treasuryRPL"` + TrustedNodeRPL []string `json:"trustedNodeRPL"` + NodeRPL []string `json:"nodeRPL"` + NodeETH []string `json:"nodeETH"` + UserETH string `json:"userETH"` + IntervalStartTime int64 `json:"intervalStartTime"` + IntervalEndTime int64 `json:"intervalEndTime"` + SubmissionTime int64 `json:"submissionTime"` +}