diff --git a/pkg/httpclient/httpclient.go b/pkg/httpclient/httpclient.go index 407b214..f986f71 100644 --- a/pkg/httpclient/httpclient.go +++ b/pkg/httpclient/httpclient.go @@ -171,7 +171,7 @@ func (c *HTTPClient) NewRequest(service rpcinterface.ServiceType, rpcEndpoint rp } // Do sends an RPC request and returns the RPC response. -func (c *HTTPClient) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { +func (c *HTTPClient) Do(req *rpcinterface.Request, v rpcinterface.IResponse) (*http.Response, error) { client, err := c.httpClientForService(req.Service) if err != nil { return nil, err diff --git a/pkg/publichttpclient/httpclient.go b/pkg/publichttpclient/httpclient.go index 7ca935e..cbea06f 100644 --- a/pkg/publichttpclient/httpclient.go +++ b/pkg/publichttpclient/httpclient.go @@ -132,7 +132,7 @@ func (c *HTTPClient) NewRequest(service rpcinterface.ServiceType, rpcEndpoint rp } // Do sends an RPC request and returns the RPC response. -func (c *HTTPClient) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { +func (c *HTTPClient) Do(req *rpcinterface.Request, v rpcinterface.IResponse) (*http.Response, error) { client, err := c.httpClientForService(req.Service) if err != nil { return nil, err diff --git a/pkg/rpc/client.go b/pkg/rpc/client.go index d4e2280..b33025c 100644 --- a/pkg/rpc/client.go +++ b/pkg/rpc/client.go @@ -1,7 +1,9 @@ package rpc import ( + "log/slog" "net/http" + "net/url" "github.com/google/uuid" @@ -87,8 +89,26 @@ func (c *Client) NewRequest(service rpcinterface.ServiceType, rpcEndpoint rpcint } // Do is a helper that wraps the activeClient's Do method -func (c *Client) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return c.activeClient.Do(req, v) +func (c *Client) Do(req *rpcinterface.Request, v rpcinterface.IResponse) (*http.Response, error) { + resp, err := c.activeClient.Do(req, v) + if err != nil { + return resp, err + } + if !v.IsSuccessful() { + return resp, &rpcinterface.ChiaRPCError{Message: v.GetRPCError()} + } + return resp, nil +} + +// Do Helper to create and send a new request for a given service and retain the proper types +func Do[R rpcinterface.IResponse](service rpcinterface.Service, endpoint rpcinterface.Endpoint, opts any, v R) (R, *http.Response, error) { + req, err := service.NewRequest(endpoint, opts) + if err != nil { + return v, nil, err + } + + resp, err := service.GetClient().Do(req, v) + return v, resp, err } // Close calls the close method on the active client @@ -98,6 +118,16 @@ func (c *Client) Close() error { // The following has a bunch of methods that are currently only used for the websocket implementation +// SetBaseURL satisfies the Client interface +func (c *Client) SetBaseURL(url *url.URL) error { + return c.activeClient.SetBaseURL(url) +} + +// SetLogHandler satisfies the client interface +func (c *Client) SetLogHandler(handler slog.Handler) { + c.activeClient.SetLogHandler(handler) +} + // SubscribeSelf subscribes to responses to requests from this service // This is currently only useful for websocket mode func (c *Client) SubscribeSelf() error { diff --git a/pkg/rpc/crawler.go b/pkg/rpc/crawler.go index 5862b9d..b5f8587 100644 --- a/pkg/rpc/crawler.go +++ b/pkg/rpc/crawler.go @@ -19,64 +19,30 @@ func (s *CrawlerService) NewRequest(rpcEndpoint rpcinterface.Endpoint, opt inter return s.client.NewRequest(rpcinterface.ServiceCrawler, rpcEndpoint, opt) } -// Do is just a shortcut to the client's Do method -func (s *CrawlerService) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return s.client.Do(req, v) +// GetClient returns the active client for the service +func (s *CrawlerService) GetClient() rpcinterface.Client { + return s.client } // GetNetworkInfo gets the network name and prefix from the full node func (s *CrawlerService) GetNetworkInfo(opts *GetNetworkInfoOptions) (*GetNetworkInfoResponse, *http.Response, error) { - request, err := s.NewRequest("get_network_info", opts) - if err != nil { - return nil, nil, err - } - - r := &GetNetworkInfoResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_network_info", opts, &GetNetworkInfoResponse{}) } // GetVersion returns the application version for the service func (s *CrawlerService) GetVersion(opts *GetVersionOptions) (*GetVersionResponse, *http.Response, error) { - request, err := s.NewRequest("get_version", opts) - if err != nil { - return nil, nil, err - } - - r := &GetVersionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_version", opts, &GetVersionResponse{}) } // GetPeerCountsResponse Response for get_get_peer_counts on crawler type GetPeerCountsResponse struct { - Response + rpcinterface.Response PeerCounts mo.Option[types.CrawlerPeerCounts] `json:"peer_counts"` } // GetPeerCounts crawler rpc -> get_peer_counts func (s *CrawlerService) GetPeerCounts() (*GetPeerCountsResponse, *http.Response, error) { - request, err := s.NewRequest("get_peer_counts", nil) - if err != nil { - return nil, nil, err - } - - r := &GetPeerCountsResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_peer_counts", nil, &GetPeerCountsResponse{}) } // GetIPsAfterTimestampOptions Options for the get_ips_after_timestamp RPC call @@ -88,23 +54,12 @@ type GetIPsAfterTimestampOptions struct { // GetIPsAfterTimestampResponse Response for get_ips_after_timestamp type GetIPsAfterTimestampResponse struct { - Response + rpcinterface.Response IPs mo.Option[[]string] `json:"ips"` Total mo.Option[int] `json:"total"` } // GetIPsAfterTimestamp Returns IP addresses seen by the network after a particular timestamp func (s *CrawlerService) GetIPsAfterTimestamp(opts *GetIPsAfterTimestampOptions) (*GetIPsAfterTimestampResponse, *http.Response, error) { - request, err := s.NewRequest("get_ips_after_timestamp", opts) - if err != nil { - return nil, nil, err - } - - r := &GetIPsAfterTimestampResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_ips_after_timestamp", opts, &GetIPsAfterTimestampResponse{}) } diff --git a/pkg/rpc/daemon.go b/pkg/rpc/daemon.go index 7d58d8f..62527c1 100644 --- a/pkg/rpc/daemon.go +++ b/pkg/rpc/daemon.go @@ -17,42 +17,19 @@ func (s *DaemonService) NewRequest(rpcEndpoint rpcinterface.Endpoint, opt interf return s.client.NewRequest(rpcinterface.ServiceDaemon, rpcEndpoint, opt) } -// Do is just a shortcut to the client's Do method -func (s *DaemonService) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return s.client.Do(req, v) +// GetClient returns the active client for the service +func (s *DaemonService) GetClient() rpcinterface.Client { + return s.client } // GetNetworkInfo gets the network name and prefix from the full node func (s *DaemonService) GetNetworkInfo(opts *GetNetworkInfoOptions) (*GetNetworkInfoResponse, *http.Response, error) { - request, err := s.NewRequest("get_network_info", opts) - if err != nil { - return nil, nil, err - } - - r := &GetNetworkInfoResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_network_info", opts, &GetNetworkInfoResponse{}) } // GetVersion returns the application version for the service func (s *DaemonService) GetVersion(opts *GetVersionOptions) (*GetVersionResponse, *http.Response, error) { - request, err := s.NewRequest("get_version", opts) - if err != nil { - return nil, nil, err - } - - r := &GetVersionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_version", opts, &GetVersionResponse{}) } // GetKeysOptions configures how keys are returned in get_keys @@ -62,25 +39,13 @@ type GetKeysOptions struct { // GetKeysResponse response from get_keys RPC call type GetKeysResponse struct { - Response + rpcinterface.Response Keys []types.KeyData `json:"keys"` } // GetKeys returns key information func (s *DaemonService) GetKeys(opts *GetKeysOptions) (*GetKeysResponse, *http.Response, error) { - request, err := s.NewRequest("get_keys", opts) - if err != nil { - return nil, nil, err - } - - r := &GetKeysResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_keys", opts, &GetKeysResponse{}) } // StartServiceOptions start service options @@ -90,25 +55,13 @@ type StartServiceOptions struct { // StartServiceResponse start service response type StartServiceResponse struct { - Response + rpcinterface.Response Service ServiceFullName `json:"service"` } // StartService starts the given service func (s *DaemonService) StartService(opts *StartServiceOptions) (*StartServiceResponse, *http.Response, error) { - request, err := s.NewRequest("start_service", opts) - if err != nil { - return nil, nil, err - } - - r := &StartServiceResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "start_service", opts, &StartServiceResponse{}) } // StopServiceOptions start service options @@ -118,25 +71,13 @@ type StopServiceOptions struct { // StopServiceResponse stop service response type StopServiceResponse struct { - Response + rpcinterface.Response Service ServiceFullName `json:"service"` } // StopService stops the given service func (s *DaemonService) StopService(opts *StopServiceOptions) (*StopServiceResponse, *http.Response, error) { - request, err := s.NewRequest("stop_service", opts) - if err != nil { - return nil, nil, err - } - - r := &StopServiceResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "stop_service", opts, &StopServiceResponse{}) } // IsRunningOptions is service running options @@ -146,72 +87,36 @@ type IsRunningOptions struct { // IsRunningResponse is service running response type IsRunningResponse struct { - Response + rpcinterface.Response ServiceName ServiceFullName `json:"service_name"` IsRunning bool `json:"is_running"` } // IsRunning returns whether a service is running func (s *DaemonService) IsRunning(opts *IsRunningOptions) (*IsRunningResponse, *http.Response, error) { - request, err := s.NewRequest("is_running", opts) - if err != nil { - return nil, nil, err - } - - r := &IsRunningResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "is_running", opts, &IsRunningResponse{}) } // RunningServicesResponse is service running response type RunningServicesResponse struct { - Response + rpcinterface.Response RunningServices []ServiceFullName `json:"running_services"` } // RunningServices returns all running services func (s *DaemonService) RunningServices() (*RunningServicesResponse, *http.Response, error) { - request, err := s.NewRequest("running_services", nil) - if err != nil { - return nil, nil, err - } - - r := &RunningServicesResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "running_services", nil, &RunningServicesResponse{}) } // ExitResponse shows information about the services that were stopped type ExitResponse struct { - Response + rpcinterface.Response ServicesStopped []ServiceFullName `json:"services_stopped"` } // Exit tells the daemon to exit func (s *DaemonService) Exit() (*ExitResponse, *http.Response, error) { - request, err := s.NewRequest("exit", nil) - if err != nil { - return nil, nil, err - } - - r := &ExitResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "exit", nil, &ExitResponse{}) } // DaemonDeleteAllKeysOpts options for delete all keys request @@ -219,22 +124,10 @@ type DaemonDeleteAllKeysOpts struct{} // DaemonDeleteAllKeysResponse response when deleting all keys type DaemonDeleteAllKeysResponse struct { - Response + rpcinterface.Response } // DeleteAllKeys deletes all keys from the keychain func (s *DaemonService) DeleteAllKeys(opts *DaemonDeleteAllKeysOpts) (*DaemonDeleteAllKeysResponse, *http.Response, error) { - request, err := s.NewRequest("delete_all_keys", opts) - if err != nil { - return nil, nil, err - } - - r := &DaemonDeleteAllKeysResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "delete_all_keys", opts, &DaemonDeleteAllKeysResponse{}) } diff --git a/pkg/rpc/datalayer.go b/pkg/rpc/datalayer.go index fe57c8b..0e6b785 100644 --- a/pkg/rpc/datalayer.go +++ b/pkg/rpc/datalayer.go @@ -17,25 +17,14 @@ func (s *DataLayerService) NewRequest(rpcEndpoint rpcinterface.Endpoint, opt int return s.client.NewRequest(rpcinterface.ServiceDataLayer, rpcEndpoint, opt) } -// Do is just a shortcut to the client's Do method -func (s *DataLayerService) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return s.client.Do(req, v) +// GetClient returns the active client for the service +func (s *DataLayerService) GetClient() rpcinterface.Client { + return s.client } // GetVersion returns the application version for the service func (s *DataLayerService) GetVersion(opts *GetVersionOptions) (*GetVersionResponse, *http.Response, error) { - request, err := s.NewRequest("get_version", opts) - if err != nil { - return nil, nil, err - } - - r := &GetVersionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_version", opts, &GetVersionResponse{}) } // DatalayerGetSubscriptionsOptions options for get_subscriptions @@ -43,7 +32,7 @@ type DatalayerGetSubscriptionsOptions struct{} // DatalayerGetSubscriptionsResponse response for get_subscriptions type DatalayerGetSubscriptionsResponse struct { - Response + rpcinterface.Response StoreIDs []string `json:"store_ids"` } @@ -55,19 +44,7 @@ func (s *DataLayerService) GetSubscriptions(opts *DatalayerGetSubscriptionsOptio // Subscriptions calls the subscriptions endpoint to list all subscriptions func (s *DataLayerService) Subscriptions(opts *DatalayerGetSubscriptionsOptions) (*DatalayerGetSubscriptionsResponse, *http.Response, error) { - request, err := s.NewRequest("subscriptions", opts) - if err != nil { - return nil, nil, err - } - - r := &DatalayerGetSubscriptionsResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "subscriptions", opts, &DatalayerGetSubscriptionsResponse{}) } // DatalayerGetOwnedStoresOptions Options for get_owned_stores @@ -75,25 +52,13 @@ type DatalayerGetOwnedStoresOptions struct{} // DatalayerGetOwnedStoresResponse Response for get_owned_stores type DatalayerGetOwnedStoresResponse struct { - Response + rpcinterface.Response StoreIDs []string `json:"store_ids"` } // GetOwnedStores RPC endpoint get_owned_stores func (s *DataLayerService) GetOwnedStores(opts *DatalayerGetOwnedStoresOptions) (*DatalayerGetOwnedStoresResponse, *http.Response, error) { - request, err := s.NewRequest("get_owned_stores", opts) - if err != nil { - return nil, nil, err - } - - r := &DatalayerGetOwnedStoresResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_owned_stores", opts, &DatalayerGetOwnedStoresResponse{}) } // DatalayerGetMirrorsOptions Options for get_mirrors @@ -103,25 +68,13 @@ type DatalayerGetMirrorsOptions struct { // DatalayerGetMirrorsResponse Response from the get_mirrors RPC type DatalayerGetMirrorsResponse struct { - Response + rpcinterface.Response Mirrors []types.DatalayerMirror `json:"mirrors"` } // GetMirrors lists the mirrors for the given datalayer store func (s *DataLayerService) GetMirrors(opts *DatalayerGetMirrorsOptions) (*DatalayerGetMirrorsResponse, *http.Response, error) { - request, err := s.NewRequest("get_mirrors", opts) - if err != nil { - return nil, nil, err - } - - r := &DatalayerGetMirrorsResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_mirrors", opts, &DatalayerGetMirrorsResponse{}) } // DatalayerDeleteMirrorOptions options for delete_mirror RPC call @@ -132,24 +85,12 @@ type DatalayerDeleteMirrorOptions struct { // DatalayerDeleteMirrorResponse response data for delete_mirror type DatalayerDeleteMirrorResponse struct { - Response + rpcinterface.Response } // DeleteMirror deletes a datalayer mirror func (s *DataLayerService) DeleteMirror(opts *DatalayerDeleteMirrorOptions) (*DatalayerDeleteMirrorResponse, *http.Response, error) { - request, err := s.NewRequest("delete_mirror", opts) - if err != nil { - return nil, nil, err - } - - r := &DatalayerDeleteMirrorResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "delete_mirror", opts, &DatalayerDeleteMirrorResponse{}) } // DatalayerAddMirrorOptions options for delete_mirror RPC call @@ -162,24 +103,12 @@ type DatalayerAddMirrorOptions struct { // DatalayerAddMirrorResponse response data for add_mirror type DatalayerAddMirrorResponse struct { - Response + rpcinterface.Response } // AddMirror deletes a datalayer mirror func (s *DataLayerService) AddMirror(opts *DatalayerAddMirrorOptions) (*DatalayerAddMirrorResponse, *http.Response, error) { - request, err := s.NewRequest("add_mirror", opts) - if err != nil { - return nil, nil, err - } - - r := &DatalayerAddMirrorResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "add_mirror", opts, &DatalayerAddMirrorResponse{}) } // DatalayerSubscribeOptions options for subscribe @@ -190,24 +119,12 @@ type DatalayerSubscribeOptions struct { // DatalayerSubscribeResponse Response from subscribe. Always empty aside from standard fields type DatalayerSubscribeResponse struct { - Response + rpcinterface.Response } // Subscribe deletes a datalayer mirror func (s *DataLayerService) Subscribe(opts *DatalayerSubscribeOptions) (*DatalayerSubscribeResponse, *http.Response, error) { - request, err := s.NewRequest("subscribe", opts) - if err != nil { - return nil, nil, err - } - - r := &DatalayerSubscribeResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "subscribe", opts, &DatalayerSubscribeResponse{}) } // DatalayerUnsubscribeOptions options for unsubscribing to a datastore @@ -218,22 +135,10 @@ type DatalayerUnsubscribeOptions struct { // DatalayerUnsubscribeResponse response data for unsubscribe type DatalayerUnsubscribeResponse struct { - Response + rpcinterface.Response } // Unsubscribe deletes a datalayer mirror func (s *DataLayerService) Unsubscribe(opts *DatalayerUnsubscribeOptions) (*DatalayerUnsubscribeResponse, *http.Response, error) { - request, err := s.NewRequest("unsubscribe", opts) - if err != nil { - return nil, nil, err - } - - r := &DatalayerUnsubscribeResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "unsubscribe", opts, &DatalayerUnsubscribeResponse{}) } diff --git a/pkg/rpc/farmer.go b/pkg/rpc/farmer.go index 04b85d4..06e5a32 100644 --- a/pkg/rpc/farmer.go +++ b/pkg/rpc/farmer.go @@ -20,58 +20,24 @@ func (s *FarmerService) NewRequest(rpcEndpoint rpcinterface.Endpoint, opt interf return s.client.NewRequest(rpcinterface.ServiceFarmer, rpcEndpoint, opt) } -// Do is just a shortcut to the client's Do method -func (s *FarmerService) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return s.client.Do(req, v) +// GetClient returns the active client for the service +func (s *FarmerService) GetClient() rpcinterface.Client { + return s.client } // GetConnections returns connections func (s *FarmerService) GetConnections(opts *GetConnectionsOptions) (*GetConnectionsResponse, *http.Response, error) { - request, err := s.NewRequest("get_connections", opts) - if err != nil { - return nil, nil, err - } - - c := &GetConnectionsResponse{} - resp, err := s.Do(request, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return Do(s, "get_connections", opts, &GetConnectionsResponse{}) } // GetNetworkInfo gets the network name and prefix from the farmer func (s *FarmerService) GetNetworkInfo(opts *GetNetworkInfoOptions) (*GetNetworkInfoResponse, *http.Response, error) { - request, err := s.NewRequest("get_network_info", opts) - if err != nil { - return nil, nil, err - } - - r := &GetNetworkInfoResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_network_info", opts, &GetNetworkInfoResponse{}) } // GetVersion returns the application version for the service func (s *FarmerService) GetVersion(opts *GetVersionOptions) (*GetVersionResponse, *http.Response, error) { - request, err := s.NewRequest("get_version", opts) - if err != nil { - return nil, nil, err - } - - r := &GetVersionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_version", opts, &GetVersionResponse{}) } // FarmerGetHarvestersOptions optoins for get_harvesters endpoint. Currently, accepts no options @@ -101,22 +67,11 @@ type FarmerHarvester struct { // FarmerGetHarvestersResponse get_harvesters response format type FarmerGetHarvestersResponse struct { - Response + rpcinterface.Response Harvesters []FarmerHarvester `json:"harvesters"` } // GetHarvesters returns all harvester details for the farmer func (s *FarmerService) GetHarvesters(opts *FarmerGetHarvestersOptions) (*FarmerGetHarvestersResponse, *http.Response, error) { - request, err := s.NewRequest("get_harvesters", opts) - if err != nil { - return nil, nil, err - } - - c := &FarmerGetHarvestersResponse{} - resp, err := s.Do(request, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return Do(s, "get_harvesters", opts, &FarmerGetHarvestersResponse{}) } diff --git a/pkg/rpc/fullnode.go b/pkg/rpc/fullnode.go index 9ee69fd..2642b0b 100644 --- a/pkg/rpc/fullnode.go +++ b/pkg/rpc/fullnode.go @@ -19,9 +19,9 @@ func (s *FullNodeService) NewRequest(rpcEndpoint rpcinterface.Endpoint, opt inte return s.client.NewRequest(rpcinterface.ServiceFullNode, rpcEndpoint, opt) } -// Do is just a shortcut to the client's Do method -func (s *FullNodeService) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return s.client.Do(req, v) +// GetClient returns the active client for the service +func (s *FullNodeService) GetClient() rpcinterface.Client { + return s.client } // GetConnectionsOptions options to filter get_connections @@ -31,79 +31,34 @@ type GetConnectionsOptions struct { // GetConnectionsResponse get_connections response format type GetConnectionsResponse struct { - Response + rpcinterface.Response Connections mo.Option[[]types.Connection] `json:"connections"` } // GetConnections returns connections func (s *FullNodeService) GetConnections(opts *GetConnectionsOptions) (*GetConnectionsResponse, *http.Response, error) { - request, err := s.NewRequest("get_connections", opts) - if err != nil { - return nil, nil, err - } - - c := &GetConnectionsResponse{} - resp, err := s.Do(request, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return Do(s, "get_connections", opts, &GetConnectionsResponse{}) } // GetNetworkInfo gets the network name and prefix from the full node func (s *FullNodeService) GetNetworkInfo(opts *GetNetworkInfoOptions) (*GetNetworkInfoResponse, *http.Response, error) { - request, err := s.NewRequest("get_network_info", opts) - if err != nil { - return nil, nil, err - } - - r := &GetNetworkInfoResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_network_info", opts, &GetNetworkInfoResponse{}) } // GetBlockchainStateResponse is the blockchain state RPC response type GetBlockchainStateResponse struct { - Response + rpcinterface.Response BlockchainState mo.Option[types.BlockchainState] `json:"blockchain_state,omitempty"` } // GetVersion returns the application version for the service func (s *FullNodeService) GetVersion(opts *GetVersionOptions) (*GetVersionResponse, *http.Response, error) { - request, err := s.NewRequest("get_version", opts) - if err != nil { - return nil, nil, err - } - - r := &GetVersionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_version", opts, &GetVersionResponse{}) } // GetBlockchainState returns blockchain state func (s *FullNodeService) GetBlockchainState() (*GetBlockchainStateResponse, *http.Response, error) { - request, err := s.NewRequest("get_blockchain_state", nil) - if err != nil { - return nil, nil, err - } - - r := &GetBlockchainStateResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_blockchain_state", nil, &GetBlockchainStateResponse{}) } // GetBlockOptions options for get_block rpc call @@ -113,24 +68,13 @@ type GetBlockOptions struct { // GetBlockResponse response for get_block rpc call type GetBlockResponse struct { - Response + rpcinterface.Response Block mo.Option[types.FullBlock] `json:"block"` } // GetBlock full_node->get_block RPC method func (s *FullNodeService) GetBlock(opts *GetBlockOptions) (*GetBlockResponse, *http.Response, error) { - request, err := s.NewRequest("get_block", opts) - if err != nil { - return nil, nil, err - } - - r := &GetBlockResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_block", opts, &GetBlockResponse{}) } // GetBlocksOptions options for get_blocks rpc call @@ -145,47 +89,24 @@ type GetBlocksOptions struct { // GetBlocksResponse response for get_blocks rpc call type GetBlocksResponse struct { - Response + rpcinterface.Response Blocks mo.Option[[]types.FullBlock] `json:"blocks"` } // GetBlocks full_node->get_blocks RPC method func (s *FullNodeService) GetBlocks(opts *GetBlocksOptions) (*GetBlocksResponse, *http.Response, error) { - request, err := s.NewRequest("get_blocks", opts) - if err != nil { - return nil, nil, err - } - - r := &GetBlocksResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_blocks", opts, &GetBlocksResponse{}) } // GetBlockCountMetricsResponse response for get_block_count_metrics rpc call type GetBlockCountMetricsResponse struct { - Response + rpcinterface.Response Metrics mo.Option[types.BlockCountMetrics] `json:"metrics"` } // GetBlockCountMetrics gets metrics about blocks func (s *FullNodeService) GetBlockCountMetrics() (*GetBlockCountMetricsResponse, *http.Response, error) { - request, err := s.NewRequest("get_block_count_metrics", nil) - if err != nil { - return nil, nil, err - } - - r := &GetBlockCountMetricsResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_block_count_metrics", nil, &GetBlockCountMetricsResponse{}) } // GetBlockByHeightOptions options for get_block_record_by_height and get_block rpc call @@ -195,25 +116,13 @@ type GetBlockByHeightOptions struct { // GetBlockRecordResponse response from get_block_record_by_height type GetBlockRecordResponse struct { - Response + rpcinterface.Response BlockRecord mo.Option[types.BlockRecord] `json:"block_record"` } // GetBlockRecordByHeight full_node->get_block_record_by_height RPC method func (s *FullNodeService) GetBlockRecordByHeight(opts *GetBlockByHeightOptions) (*GetBlockRecordResponse, *http.Response, error) { - // Get Block Record - request, err := s.NewRequest("get_block_record_by_height", opts) - if err != nil { - return nil, nil, err - } - - record := &GetBlockRecordResponse{} - resp, err := s.Do(request, record) - if err != nil { - return nil, resp, err - } - - return record, resp, nil + return Do(s, "get_block_record_by_height", opts, &GetBlockRecordResponse{}) } // GetBlockByHeight helper function to get a full block by height, calls full_node->get_block_record_by_height RPC method then full_node->get_block RPC method @@ -224,21 +133,7 @@ func (s *FullNodeService) GetBlockByHeight(opts *GetBlockByHeightOptions) (*GetB return nil, resp, err } - request, err := s.NewRequest("get_block", GetBlockOptions{ - HeaderHash: record.BlockRecord.OrEmpty().HeaderHash, - }) - if err != nil { - return nil, nil, err - } - - // Get Full Block - block := &GetBlockResponse{} - resp, err = s.Do(request, block) - if err != nil { - return nil, resp, err - } - - return block, resp, nil + return Do(s, "get_block", GetBlockOptions{HeaderHash: record.BlockRecord.OrEmpty().HeaderHash}, &GetBlockResponse{}) } // GetAdditionsAndRemovalsOptions options for get_additions_and_removals @@ -248,26 +143,14 @@ type GetAdditionsAndRemovalsOptions struct { // GetAdditionsAndRemovalsResponse response for get_additions_and_removals type GetAdditionsAndRemovalsResponse struct { - Response + rpcinterface.Response Additions []types.CoinRecord `json:"additions"` Removals []types.CoinRecord `json:"removals"` } // GetAdditionsAndRemovals Gets additions and removals for a particular block hash func (s *FullNodeService) GetAdditionsAndRemovals(opts *GetAdditionsAndRemovalsOptions) (*GetAdditionsAndRemovalsResponse, *http.Response, error) { - request, err := s.NewRequest("get_additions_and_removals", opts) - if err != nil { - return nil, nil, err - } - - r := &GetAdditionsAndRemovalsResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_additions_and_removals", opts, &GetAdditionsAndRemovalsResponse{}) } // GetCoinRecordsByPuzzleHashOptions request options for /get_coin_records_by_puzzle_hash @@ -280,25 +163,13 @@ type GetCoinRecordsByPuzzleHashOptions struct { // GetCoinRecordsByPuzzleHashResponse Response for /get_coin_records_by_puzzle_hash type GetCoinRecordsByPuzzleHashResponse struct { - Response + rpcinterface.Response CoinRecords []types.CoinRecord `json:"coin_records"` } // GetCoinRecordsByPuzzleHash returns coin records for a specified puzzle hash func (s *FullNodeService) GetCoinRecordsByPuzzleHash(opts *GetCoinRecordsByPuzzleHashOptions) (*GetCoinRecordsByPuzzleHashResponse, *http.Response, error) { - request, err := s.NewRequest("get_coin_records_by_puzzle_hash", opts) - if err != nil { - return nil, nil, err - } - - r := &GetCoinRecordsByPuzzleHashResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_coin_records_by_puzzle_hash", opts, &GetCoinRecordsByPuzzleHashResponse{}) } // GetCoinRecordsByPuzzleHashesOptions request options for /get_coin_records_by_puzzle_hash @@ -311,25 +182,13 @@ type GetCoinRecordsByPuzzleHashesOptions struct { // GetCoinRecordsByPuzzleHashesResponse Response for /get_coin_records_by_puzzle_hashes type GetCoinRecordsByPuzzleHashesResponse struct { - Response + rpcinterface.Response CoinRecords []types.CoinRecord `json:"coin_records"` } // GetCoinRecordsByPuzzleHashes returns coin records for a specified list of puzzle hashes func (s *FullNodeService) GetCoinRecordsByPuzzleHashes(opts *GetCoinRecordsByPuzzleHashesOptions) (*GetCoinRecordsByPuzzleHashesResponse, *http.Response, error) { - request, err := s.NewRequest("get_coin_records_by_puzzle_hashes", opts) - if err != nil { - return nil, nil, err - } - - r := &GetCoinRecordsByPuzzleHashesResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_coin_records_by_puzzle_hashes", opts, &GetCoinRecordsByPuzzleHashesResponse{}) } // GetCoinRecordByNameOptions request options for /get_coin_record_by_name @@ -339,25 +198,13 @@ type GetCoinRecordByNameOptions struct { // GetCoinRecordByNameResponse response from get_coin_record_by_name endpoint type GetCoinRecordByNameResponse struct { - Response + rpcinterface.Response CoinRecord mo.Option[types.CoinRecord] `json:"coin_record"` } // GetCoinRecordByName request to get_coin_record_by_name endpoint func (s *FullNodeService) GetCoinRecordByName(opts *GetCoinRecordByNameOptions) (*GetCoinRecordByNameResponse, *http.Response, error) { - request, err := s.NewRequest("get_coin_record_by_name", opts) - if err != nil { - return nil, nil, err - } - - r := &GetCoinRecordByNameResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_coin_record_by_name", opts, &GetCoinRecordByNameResponse{}) } // GetCoinRecordsByHintOptions options for get_coin_records_by_hint @@ -370,25 +217,13 @@ type GetCoinRecordsByHintOptions struct { // GetCoinRecordsByHintResponse Response for /get_coin_records_by_hint type GetCoinRecordsByHintResponse struct { - Response + rpcinterface.Response CoinRecords []types.CoinRecord `json:"coin_records"` } // GetCoinRecordsByHint returns coin records for a specified puzzle hash func (s *FullNodeService) GetCoinRecordsByHint(opts *GetCoinRecordsByHintOptions) (*GetCoinRecordsByHintResponse, *http.Response, error) { - request, err := s.NewRequest("get_coin_records_by_hint", opts) - if err != nil { - return nil, nil, err - } - - r := &GetCoinRecordsByHintResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_coin_records_by_hint", opts, &GetCoinRecordsByHintResponse{}) } // FullNodePushTXOptions options for pushing tx to full node mempool @@ -398,41 +233,13 @@ type FullNodePushTXOptions struct { // FullNodePushTXResponse Response from full node push_tx type FullNodePushTXResponse struct { - Response + rpcinterface.Response Status mo.Option[string] `json:"status"` } // PushTX pushes a transaction to the full node func (s *FullNodeService) PushTX(opts *FullNodePushTXOptions) (*FullNodePushTXResponse, *http.Response, error) { - request, err := s.NewRequest("push_tx", opts) - if err != nil { - return nil, nil, err - } - - r := &FullNodePushTXResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil -} - -// GetPuzzleAndSolution full_node-> get_puzzle_and_solution RPC method -func (s *FullNodeService) GetPuzzleAndSolution(opts *GetPuzzleAndSolutionOptions) (*GetPuzzleAndSolutionResponse, *http.Response, error) { - request, err := s.NewRequest("get_puzzle_and_solution", opts) - if err != nil { - return nil, nil, err - } - - record := &GetPuzzleAndSolutionResponse{} - resp, err := s.Do(request, record) - if err != nil { - return nil, resp, err - } - - return record, resp, nil + return Do(s, "push_tx", opts, &FullNodePushTXResponse{}) } // GetFeeEstimateOptions inputs to get a fee estimate @@ -446,7 +253,7 @@ type GetFeeEstimateOptions struct { // GetFeeEstimateResponse response for get_fee_estimate type GetFeeEstimateResponse struct { - Response + rpcinterface.Response Estimates mo.Option[[]float64] `json:"estimates"` TargetTimes mo.Option[[]uint64] `json:"target_times"` CurrentFeeRate mo.Option[float64] `json:"current_fee_rate"` @@ -460,19 +267,7 @@ type GetFeeEstimateResponse struct { // GetFeeEstimate endpoint func (s *FullNodeService) GetFeeEstimate(opts *GetFeeEstimateOptions) (*GetFeeEstimateResponse, *http.Response, error) { - request, err := s.NewRequest("get_fee_estimate", opts) - if err != nil { - return nil, nil, err - } - - r := &GetFeeEstimateResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_fee_estimate", opts, &GetFeeEstimateResponse{}) } // GetPuzzleAndSolutionOptions options for get_puzzle_and_solution rpc call @@ -483,6 +278,11 @@ type GetPuzzleAndSolutionOptions struct { // GetPuzzleAndSolutionResponse response from get_puzzle_and_solution type GetPuzzleAndSolutionResponse struct { - Response + rpcinterface.Response CoinSolution mo.Option[types.CoinSpend] `json:"coin_solution"` } + +// GetPuzzleAndSolution full_node-> get_puzzle_and_solution RPC method +func (s *FullNodeService) GetPuzzleAndSolution(opts *GetPuzzleAndSolutionOptions) (*GetPuzzleAndSolutionResponse, *http.Response, error) { + return Do(s, "get_puzzle_and_solution", opts, &GetPuzzleAndSolutionResponse{}) +} diff --git a/pkg/rpc/harvester.go b/pkg/rpc/harvester.go index 80b14b2..4b1c38c 100644 --- a/pkg/rpc/harvester.go +++ b/pkg/rpc/harvester.go @@ -19,63 +19,29 @@ func (s *HarvesterService) NewRequest(rpcEndpoint rpcinterface.Endpoint, opt int return s.client.NewRequest(rpcinterface.ServiceHarvester, rpcEndpoint, opt) } -// Do is just a shortcut to the client's Do method -func (s *HarvesterService) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return s.client.Do(req, v) +// GetClient returns the active client for the service +func (s *HarvesterService) GetClient() rpcinterface.Client { + return s.client } // GetConnections returns connections func (s *HarvesterService) GetConnections(opts *GetConnectionsOptions) (*GetConnectionsResponse, *http.Response, error) { - request, err := s.NewRequest("get_connections", opts) - if err != nil { - return nil, nil, err - } - - c := &GetConnectionsResponse{} - resp, err := s.Do(request, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return Do(s, "get_connections", opts, &GetConnectionsResponse{}) } // GetNetworkInfo gets the network name and prefix from the harvester func (s *HarvesterService) GetNetworkInfo(opts *GetNetworkInfoOptions) (*GetNetworkInfoResponse, *http.Response, error) { - request, err := s.NewRequest("get_network_info", opts) - if err != nil { - return nil, nil, err - } - - r := &GetNetworkInfoResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_network_info", opts, &GetNetworkInfoResponse{}) } // GetVersion returns the application version for the service func (s *HarvesterService) GetVersion(opts *GetVersionOptions) (*GetVersionResponse, *http.Response, error) { - request, err := s.NewRequest("get_version", opts) - if err != nil { - return nil, nil, err - } - - r := &GetVersionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_version", opts, &GetVersionResponse{}) } // HarvesterGetPlotsResponse get_plots response format type HarvesterGetPlotsResponse struct { - Response + rpcinterface.Response Plots mo.Option[[]protocols.Plot] `json:"plots"` FailedToOpenFilenames mo.Option[[]string] `json:"failed_to_open_filenames"` NotFoundFilenames mo.Option[[]string] `json:"not_found_filenames"` @@ -83,16 +49,5 @@ type HarvesterGetPlotsResponse struct { // GetPlots returns connections func (s *HarvesterService) GetPlots() (*HarvesterGetPlotsResponse, *http.Response, error) { - request, err := s.NewRequest("get_plots", nil) - if err != nil { - return nil, nil, err - } - - p := &HarvesterGetPlotsResponse{} - resp, err := s.Do(request, p) - if err != nil { - return nil, resp, err - } - - return p, resp, nil + return Do(s, "get_plots", nil, &HarvesterGetPlotsResponse{}) } diff --git a/pkg/rpc/response.go b/pkg/rpc/response.go deleted file mode 100644 index ad5bec4..0000000 --- a/pkg/rpc/response.go +++ /dev/null @@ -1,11 +0,0 @@ -package rpc - -import ( - "github.com/samber/mo" -) - -// Response is the base response elements that may be in any response from an RPC server in Chia -type Response struct { - Success bool `json:"success"` - Error mo.Option[string] `json:"error,omitempty"` -} diff --git a/pkg/rpc/shared.go b/pkg/rpc/shared.go index d168c17..e4c34ff 100644 --- a/pkg/rpc/shared.go +++ b/pkg/rpc/shared.go @@ -2,6 +2,8 @@ package rpc import ( "github.com/samber/mo" + + "github.com/chia-network/go-chia-libs/pkg/rpcinterface" ) // GetNetworkInfoOptions options for the get_network_info rpc calls @@ -9,7 +11,7 @@ type GetNetworkInfoOptions struct{} // GetNetworkInfoResponse common get_network_info response from all RPC services type GetNetworkInfoResponse struct { - Response + rpcinterface.Response NetworkName mo.Option[string] `json:"network_name"` NetworkPrefix mo.Option[string] `json:"network_prefix"` } @@ -19,7 +21,7 @@ type GetVersionOptions struct{} // GetVersionResponse is the response of get_version from all RPC services type GetVersionResponse struct { - Response + rpcinterface.Response Version string `json:"version"` } diff --git a/pkg/rpc/timelord.go b/pkg/rpc/timelord.go index f102e3b..3b7e4bd 100644 --- a/pkg/rpc/timelord.go +++ b/pkg/rpc/timelord.go @@ -16,56 +16,22 @@ func (s *TimelordService) NewRequest(rpcEndpoint rpcinterface.Endpoint, opt inte return s.client.NewRequest(rpcinterface.ServiceTimelord, rpcEndpoint, opt) } -// Do is just a shortcut to the client's Do method -func (s *TimelordService) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return s.client.Do(req, v) +// GetClient returns the active client for the service +func (s *TimelordService) GetClient() rpcinterface.Client { + return s.client } // GetConnections returns connections func (s *TimelordService) GetConnections(opts *GetConnectionsOptions) (*GetConnectionsResponse, *http.Response, error) { - request, err := s.NewRequest("get_connections", opts) - if err != nil { - return nil, nil, err - } - - c := &GetConnectionsResponse{} - resp, err := s.Do(request, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return Do(s, "get_connections", opts, &GetConnectionsResponse{}) } // GetNetworkInfo gets the network name and prefix from the full node func (s *TimelordService) GetNetworkInfo(opts *GetNetworkInfoOptions) (*GetNetworkInfoResponse, *http.Response, error) { - request, err := s.NewRequest("get_network_info", opts) - if err != nil { - return nil, nil, err - } - - r := &GetNetworkInfoResponse{} - - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_network_info", opts, &GetNetworkInfoResponse{}) } // GetVersion returns the application version for the service func (s *TimelordService) GetVersion(opts *GetVersionOptions) (*GetVersionResponse, *http.Response, error) { - request, err := s.NewRequest("get_version", opts) - if err != nil { - return nil, nil, err - } - - r := &GetVersionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_version", opts, &GetVersionResponse{}) } diff --git a/pkg/rpc/wallet.go b/pkg/rpc/wallet.go index b266eb7..06e2046 100644 --- a/pkg/rpc/wallet.go +++ b/pkg/rpc/wallet.go @@ -19,101 +19,46 @@ func (s *WalletService) NewRequest(rpcEndpoint rpcinterface.Endpoint, opt interf return s.client.NewRequest(rpcinterface.ServiceWallet, rpcEndpoint, opt) } -// Do is just a shortcut to the client's Do method -func (s *WalletService) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { - return s.client.Do(req, v) +// GetClient returns the active client for the service +func (s *WalletService) GetClient() rpcinterface.Client { + return s.client } // GetConnections returns connections func (s *WalletService) GetConnections(opts *GetConnectionsOptions) (*GetConnectionsResponse, *http.Response, error) { - request, err := s.NewRequest("get_connections", opts) - if err != nil { - return nil, nil, err - } - - c := &GetConnectionsResponse{} - resp, err := s.Do(request, c) - if err != nil { - return nil, resp, err - } - - return c, resp, nil + return Do(s, "get_connections", opts, &GetConnectionsResponse{}) } // GetNetworkInfo wallet rpc -> get_network_info func (s *WalletService) GetNetworkInfo(opts *GetNetworkInfoOptions) (*GetNetworkInfoResponse, *http.Response, error) { - request, err := s.NewRequest("get_network_info", nil) - if err != nil { - return nil, nil, err - } - - r := &GetNetworkInfoResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_network_info", opts, &GetNetworkInfoResponse{}) } // GetVersion returns the application version for the service func (s *WalletService) GetVersion(opts *GetVersionOptions) (*GetVersionResponse, *http.Response, error) { - request, err := s.NewRequest("get_version", opts) - if err != nil { - return nil, nil, err - } - - r := &GetVersionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_version", opts, &GetVersionResponse{}) } // GetPublicKeysResponse response from get_public_keys type GetPublicKeysResponse struct { - Response + rpcinterface.Response PublicKeyFingerprints mo.Option[[]int] `json:"public_key_fingerprints"` } // GetPublicKeys endpoint func (s *WalletService) GetPublicKeys() (*GetPublicKeysResponse, *http.Response, error) { - request, err := s.NewRequest("get_public_keys", nil) - if err != nil { - return nil, nil, err - } - - r := &GetPublicKeysResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_public_keys", nil, &GetPublicKeysResponse{}) } // GenerateMnemonicResponse Random new 24 words response type GenerateMnemonicResponse struct { - Response + rpcinterface.Response Mnemonic mo.Option[[]string] `json:"mnemonic"` } // GenerateMnemonic Endpoint for generating a new random 24 words func (s *WalletService) GenerateMnemonic() (*GenerateMnemonicResponse, *http.Response, error) { - request, err := s.NewRequest("generate_mnemonic", nil) - if err != nil { - return nil, nil, err - } - - r := &GenerateMnemonicResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "generate_mnemonic", nil, &GenerateMnemonicResponse{}) } // AddKeyOptions options for the add_key endpoint @@ -123,46 +68,24 @@ type AddKeyOptions struct { // AddKeyResponse response from the add_key endpoint type AddKeyResponse struct { - Response + rpcinterface.Response Word mo.Option[string] `json:"word,omitempty"` // This is part of a unique error response Fingerprint mo.Option[int] `json:"fingerprint,omitempty"` } // AddKey Adds a new key from 24 words to the keychain -func (s *WalletService) AddKey(options *AddKeyOptions) (*AddKeyResponse, *http.Response, error) { - request, err := s.NewRequest("add_key", options) - if err != nil { - return nil, nil, err - } - - r := &AddKeyResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil +func (s *WalletService) AddKey(opts *AddKeyOptions) (*AddKeyResponse, *http.Response, error) { + return Do(s, "add_key", opts, &AddKeyResponse{}) } // DeleteAllKeysResponse Delete keys response type DeleteAllKeysResponse struct { - Response + rpcinterface.Response } // DeleteAllKeys deletes all keys from the keychain func (s *WalletService) DeleteAllKeys() (*DeleteAllKeysResponse, *http.Response, error) { - request, err := s.NewRequest("delete_all_keys", nil) - if err != nil { - return nil, nil, err - } - - r := &DeleteAllKeysResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "delete_all_keys", nil, &DeleteAllKeysResponse{}) } // GetNextAddressOptions options for get_next_address endpoint @@ -173,30 +96,19 @@ type GetNextAddressOptions struct { // GetNextAddressResponse response from get next address type GetNextAddressResponse struct { - Response + rpcinterface.Response WalletID mo.Option[uint32] `json:"wallet_id"` Address mo.Option[string] `json:"address"` } // GetNextAddress returns the current address for the wallet. If NewAddress is true, it moves to the next address before responding -func (s *WalletService) GetNextAddress(options *GetNextAddressOptions) (*GetNextAddressResponse, *http.Response, error) { - request, err := s.NewRequest("get_next_address", options) - if err != nil { - return nil, nil, err - } - - r := &GetNextAddressResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil +func (s *WalletService) GetNextAddress(opts *GetNextAddressOptions) (*GetNextAddressResponse, *http.Response, error) { + return Do(s, "get_next_address", opts, &GetNextAddressResponse{}) } // GetWalletSyncStatusResponse Response for get_sync_status on wallet type GetWalletSyncStatusResponse struct { - Response + rpcinterface.Response GenesisInitialized mo.Option[bool] `json:"genesis_initialized"` Synced mo.Option[bool] `json:"synced"` Syncing mo.Option[bool] `json:"syncing"` @@ -204,40 +116,18 @@ type GetWalletSyncStatusResponse struct { // GetSyncStatus wallet rpc -> get_sync_status func (s *WalletService) GetSyncStatus() (*GetWalletSyncStatusResponse, *http.Response, error) { - request, err := s.NewRequest("get_sync_status", nil) - if err != nil { - return nil, nil, err - } - - r := &GetWalletSyncStatusResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_sync_status", nil, &GetWalletSyncStatusResponse{}) } // GetWalletHeightInfoResponse response for get_height_info on wallet type GetWalletHeightInfoResponse struct { - Response + rpcinterface.Response Height mo.Option[uint32] `json:"height"` } // GetHeightInfo wallet rpc -> get_height_info func (s *WalletService) GetHeightInfo() (*GetWalletHeightInfoResponse, *http.Response, error) { - request, err := s.NewRequest("get_height_info", nil) - if err != nil { - return nil, nil, err - } - - r := &GetWalletHeightInfoResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_height_info", nil, &GetWalletHeightInfoResponse{}) } // GetWalletsOptions wallet rpc -> get_wallets @@ -247,25 +137,14 @@ type GetWalletsOptions struct { // GetWalletsResponse wallet rpc -> get_wallets type GetWalletsResponse struct { - Response + rpcinterface.Response Fingerprint mo.Option[int] `json:"fingerprint"` Wallets mo.Option[[]types.WalletInfo] `json:"wallets"` } // GetWallets wallet rpc -> get_wallets func (s *WalletService) GetWallets(opts *GetWalletsOptions) (*GetWalletsResponse, *http.Response, error) { - request, err := s.NewRequest("get_wallets", opts) - if err != nil { - return nil, nil, err - } - - r := &GetWalletsResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_wallets", opts, &GetWalletsResponse{}) } // GetWalletBalanceOptions request options for get_wallet_balance @@ -275,24 +154,13 @@ type GetWalletBalanceOptions struct { // GetWalletBalanceResponse is the wallet balance RPC response type GetWalletBalanceResponse struct { - Response + rpcinterface.Response Balance mo.Option[types.WalletBalance] `json:"wallet_balance"` } // GetWalletBalance returns wallet balance func (s *WalletService) GetWalletBalance(opts *GetWalletBalanceOptions) (*GetWalletBalanceResponse, *http.Response, error) { - request, err := s.NewRequest("get_wallet_balance", opts) - if err != nil { - return nil, nil, err - } - - r := &GetWalletBalanceResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_wallet_balance", opts, &GetWalletBalanceResponse{}) } // GetWalletTransactionCountOptions options for get transaction count @@ -302,25 +170,14 @@ type GetWalletTransactionCountOptions struct { // GetWalletTransactionCountResponse response for get_transaction_count type GetWalletTransactionCountResponse struct { - Response + rpcinterface.Response WalletID mo.Option[uint32] `json:"wallet_id"` Count mo.Option[int] `json:"count"` } // GetTransactionCount returns the total count of transactions for the specific wallet ID func (s *WalletService) GetTransactionCount(opts *GetWalletTransactionCountOptions) (*GetWalletTransactionCountResponse, *http.Response, error) { - request, err := s.NewRequest("get_transaction_count", opts) - if err != nil { - return nil, nil, err - } - - r := &GetWalletTransactionCountResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_transaction_count", opts, &GetWalletTransactionCountResponse{}) } // GetWalletTransactionsOptions options for get wallet transactions @@ -333,25 +190,14 @@ type GetWalletTransactionsOptions struct { // GetWalletTransactionsResponse response for get_wallet_transactions type GetWalletTransactionsResponse struct { - Response + rpcinterface.Response WalletID mo.Option[uint32] `json:"wallet_id"` Transactions mo.Option[[]types.TransactionRecord] `json:"transactions"` } // GetTransactions wallet rpc -> get_transactions func (s *WalletService) GetTransactions(opts *GetWalletTransactionsOptions) (*GetWalletTransactionsResponse, *http.Response, error) { - request, err := s.NewRequest("get_transactions", opts) - if err != nil { - return nil, nil, err - } - - r := &GetWalletTransactionsResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_transactions", opts, &GetWalletTransactionsResponse{}) } // GetWalletTransactionOptions options for getting a single wallet transaction @@ -362,25 +208,14 @@ type GetWalletTransactionOptions struct { // GetWalletTransactionResponse response for get_wallet_transactions type GetWalletTransactionResponse struct { - Response + rpcinterface.Response Transaction mo.Option[types.TransactionRecord] `json:"transaction"` TransactionID mo.Option[string] `json:"transaction_id"` } // GetTransaction returns a single transaction record func (s *WalletService) GetTransaction(opts *GetWalletTransactionOptions) (*GetWalletTransactionResponse, *http.Response, error) { - request, err := s.NewRequest("get_transaction", opts) - if err != nil { - return nil, nil, err - } - - r := &GetWalletTransactionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_transaction", opts, &GetWalletTransactionResponse{}) } // SendTransactionOptions represents the options for send_transaction @@ -395,25 +230,14 @@ type SendTransactionOptions struct { // SendTransactionResponse represents the response from send_transaction type SendTransactionResponse struct { - Response + rpcinterface.Response TransactionID mo.Option[string] `json:"transaction_id"` Transaction mo.Option[types.TransactionRecord] `json:"transaction"` } // SendTransaction sends a transaction func (s *WalletService) SendTransaction(opts *SendTransactionOptions) (*SendTransactionResponse, *http.Response, error) { - request, err := s.NewRequest("send_transaction", opts) - if err != nil { - return nil, nil, err - } - - r := &SendTransactionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "send_transaction", opts, &SendTransactionResponse{}) } // CatSpendOptions represents the options for cat_spend @@ -426,25 +250,14 @@ type CatSpendOptions struct { // CatSpendResponse represents the response from cat_spend type CatSpendResponse struct { - Response + rpcinterface.Response TransactionID mo.Option[string] `json:"transaction_id"` Transaction mo.Option[types.TransactionRecord] `json:"transaction"` } // CatSpend sends a transaction func (s *WalletService) CatSpend(opts *CatSpendOptions) (*CatSpendResponse, *http.Response, error) { - request, err := s.NewRequest("cat_spend", opts) - if err != nil { - return nil, nil, err - } - - r := &CatSpendResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "cat_spend", opts, &CatSpendResponse{}) } // MintNFTOptions represents the options for nft_get_info @@ -467,25 +280,14 @@ type MintNFTOptions struct { // MintNFTResponse represents the response from nft_get_info type MintNFTResponse struct { - Response + rpcinterface.Response SpendBundle mo.Option[types.SpendBundle] `json:"spend_bundle"` WalletID mo.Option[uint32] `json:"wallet_id"` } // MintNFT Mint a new NFT func (s *WalletService) MintNFT(opts *MintNFTOptions) (*MintNFTResponse, *http.Response, error) { - request, err := s.NewRequest("nft_mint_nft", opts) - if err != nil { - return nil, nil, err - } - - r := &MintNFTResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "nft_mint_nft", opts, &MintNFTResponse{}) } // GetNFTsOptions represents the options for nft_get_nfts @@ -497,25 +299,14 @@ type GetNFTsOptions struct { // GetNFTsResponse represents the response from nft_get_nfts type GetNFTsResponse struct { - Response + rpcinterface.Response WalletID mo.Option[uint32] `json:"wallet_id"` NFTList mo.Option[[]types.NFTInfo] `json:"nft_list"` } // GetNFTs Show all NFTs in a given wallet func (s *WalletService) GetNFTs(opts *GetNFTsOptions) (*GetNFTsResponse, *http.Response, error) { - request, err := s.NewRequest("nft_get_nfts", opts) - if err != nil { - return nil, nil, err - } - - r := &GetNFTsResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "nft_get_nfts", opts, &GetNFTsResponse{}) } // TransferNFTOptions represents the options for nft_get_info @@ -528,25 +319,14 @@ type TransferNFTOptions struct { // TransferNFTResponse represents the response from nft_get_info type TransferNFTResponse struct { - Response + rpcinterface.Response SpendBundle mo.Option[types.SpendBundle] `json:"spend_bundle"` WalletID mo.Option[uint32] `json:"wallet_id"` } // TransferNFT Get info about an NFT func (s *WalletService) TransferNFT(opts *TransferNFTOptions) (*TransferNFTResponse, *http.Response, error) { - request, err := s.NewRequest("nft_transfer_nft", opts) - if err != nil { - return nil, nil, err - } - - r := &TransferNFTResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "nft_transfer_nft", opts, &TransferNFTResponse{}) } // GetNFTInfoOptions represents the options for nft_get_info @@ -557,24 +337,13 @@ type GetNFTInfoOptions struct { // GetNFTInfoResponse represents the response from nft_get_info type GetNFTInfoResponse struct { - Response + rpcinterface.Response NFTInfo mo.Option[types.NFTInfo] `json:"nft_info"` } // GetNFTInfo Get info about an NFT func (s *WalletService) GetNFTInfo(opts *GetNFTInfoOptions) (*GetNFTInfoResponse, *http.Response, error) { - request, err := s.NewRequest("nft_get_info", opts) - if err != nil { - return nil, nil, err - } - - r := &GetNFTInfoResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "nft_get_info", opts, &GetNFTInfoResponse{}) } // NFTAddURIOptions represents the options for nft_add_uri @@ -588,25 +357,14 @@ type NFTAddURIOptions struct { // NFTAddURIResponse represents the response from nft_add_uri type NFTAddURIResponse struct { - Response + rpcinterface.Response SpendBundle mo.Option[types.SpendBundle] `json:"spend_bundle"` WalletID mo.Option[uint32] `json:"wallet_id"` } // NFTAddURI Get info about an NFT func (s *WalletService) NFTAddURI(opts *NFTAddURIOptions) (*NFTAddURIResponse, *http.Response, error) { - request, err := s.NewRequest("nft_add_uri", opts) - if err != nil { - return nil, nil, err - } - - r := &NFTAddURIResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "nft_add_uri", opts, &NFTAddURIResponse{}) } // NFTGetByDidOptions represents the options for nft_get_by_did @@ -616,24 +374,13 @@ type NFTGetByDidOptions struct { // NFTGetByDidResponse represents the response from nft_get_by_did type NFTGetByDidResponse struct { - Response + rpcinterface.Response WalletID mo.Option[uint32] `json:"wallet_id"` } // NFTGetByDid Get wallet ID by DID func (s *WalletService) NFTGetByDid(opts *NFTGetByDidOptions) (*NFTGetByDidResponse, *http.Response, error) { - request, err := s.NewRequest("nft_get_by_did", opts) - if err != nil { - return nil, nil, err - } - - r := &NFTGetByDidResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "nft_get_by_did", opts, &NFTGetByDidResponse{}) } // GetSpendableCoinsOptions Options for get_spendable_coins @@ -646,7 +393,7 @@ type GetSpendableCoinsOptions struct { // GetSpendableCoinsResponse response from get_spendable_coins type GetSpendableCoinsResponse struct { - Response + rpcinterface.Response ConfirmedRecords mo.Option[[]types.CoinRecord] `json:"confirmed_records"` UnconfirmedRemovals mo.Option[[]types.CoinRecord] `json:"unconfirmed_removals"` UnconfirmedAdditions mo.Option[[]types.CoinRecord] `json:"unconfirmed_additions"` @@ -654,18 +401,7 @@ type GetSpendableCoinsResponse struct { // GetSpendableCoins returns information about the coins in the wallet func (s *WalletService) GetSpendableCoins(opts *GetSpendableCoinsOptions) (*GetSpendableCoinsResponse, *http.Response, error) { - request, err := s.NewRequest("get_spendable_coins", opts) - if err != nil { - return nil, nil, err - } - - r := &GetSpendableCoinsResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "get_spendable_coins", opts, &GetSpendableCoinsResponse{}) } // CreateSignedTransactionOptions Options for create_signed_transaction endpoint @@ -682,30 +418,19 @@ type CreateSignedTransactionOptions struct { // CreateSignedTransactionResponse Response from create_signed_transaction type CreateSignedTransactionResponse struct { - Response + rpcinterface.Response SignedTXs mo.Option[[]types.TransactionRecord] `json:"signed_txs"` SignedTX mo.Option[types.TransactionRecord] `json:"signed_tx"` } // CreateSignedTransaction generates a signed transaction based on the specified options func (s *WalletService) CreateSignedTransaction(opts *CreateSignedTransactionOptions) (*CreateSignedTransactionResponse, *http.Response, error) { - request, err := s.NewRequest("create_signed_transaction", opts) - if err != nil { - return nil, nil, err - } - - r := &CreateSignedTransactionResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "create_signed_transaction", opts, &CreateSignedTransactionResponse{}) } // SendTransactionMultiResponse Response from send_transaction_multi type SendTransactionMultiResponse struct { - Response + rpcinterface.Response Transaction mo.Option[types.TransactionRecord] `json:"transaction"` TransactionID mo.Option[string] `json:"transaction_id"` } @@ -713,16 +438,5 @@ type SendTransactionMultiResponse struct { // SendTransactionMulti allows sending a more detailed transaction with multiple inputs/outputs. // Options are the same as create signed transaction since this is ultimately just a wrapper around that in Chia func (s *WalletService) SendTransactionMulti(opts *CreateSignedTransactionOptions) (*SendTransactionMultiResponse, *http.Response, error) { - request, err := s.NewRequest("send_transaction_multi", opts) - if err != nil { - return nil, nil, err - } - - r := &SendTransactionMultiResponse{} - resp, err := s.Do(request, r) - if err != nil { - return nil, resp, err - } - - return r, resp, nil + return Do(s, "send_transaction_multi", opts, &SendTransactionMultiResponse{}) } diff --git a/pkg/rpc/wallet_test.go b/pkg/rpc/wallet_test.go index 9fa2467..15442ba 100644 --- a/pkg/rpc/wallet_test.go +++ b/pkg/rpc/wallet_test.go @@ -5,9 +5,11 @@ import ( "net/http" "testing" - "github.com/chia-network/go-chia-libs/pkg/types" "github.com/samber/mo" "github.com/stretchr/testify/require" + + "github.com/chia-network/go-chia-libs/pkg/rpcinterface" + "github.com/chia-network/go-chia-libs/pkg/types" ) func TestGetNFTs(t *testing.T) { @@ -24,7 +26,7 @@ func TestGetNFTs(t *testing.T) { }) want := GetNFTsResponse{ - Response: Response{ + Response: rpcinterface.Response{ Success: true, }, WalletID: mo.Some[uint32](4), @@ -78,7 +80,7 @@ func TestNFTGetByDid(t *testing.T) { }) want := NFTGetByDidResponse{ - Response: Response{ + Response: rpcinterface.Response{ Success: true, }, WalletID: mo.Some[uint32](4), diff --git a/pkg/rpcinterface/client.go b/pkg/rpcinterface/client.go index 6453dd4..85ceac0 100644 --- a/pkg/rpcinterface/client.go +++ b/pkg/rpcinterface/client.go @@ -12,7 +12,7 @@ import ( // HTTP (standard RPC) and websockets are the two supported now type Client interface { NewRequest(service ServiceType, rpcEndpoint Endpoint, opt interface{}) (*Request, error) - Do(req *Request, v interface{}) (*http.Response, error) + Do(req *Request, v IResponse) (*http.Response, error) Close() error SetBaseURL(url *url.URL) error diff --git a/pkg/rpcinterface/response.go b/pkg/rpcinterface/response.go new file mode 100644 index 0000000..80c86f2 --- /dev/null +++ b/pkg/rpcinterface/response.go @@ -0,0 +1,37 @@ +package rpcinterface + +import ( + "github.com/samber/mo" +) + +// IResponse is the interface that must be satisfied by return types so we can properly wrap RPC errors +type IResponse interface { + IsSuccessful() bool + GetRPCError() string +} + +// Response is the base response elements that may be in any response from an RPC server in Chia +type Response struct { + Success bool `json:"success"` + Error mo.Option[string] `json:"error,omitempty"` +} + +// IsSuccessful returns whether the RPC request has success: true +func (r *Response) IsSuccessful() bool { + return r.Success +} + +// GetRPCError returns the error if present or an empty string +func (r *Response) GetRPCError() string { + return r.Error.OrEmpty() +} + +// ChiaRPCError is the specific error returned when the RPC request succeeds, but returns success: false and an error +type ChiaRPCError struct { + Message string +} + +// Error satisfies the error interface +func (e *ChiaRPCError) Error() string { + return e.Message +} diff --git a/pkg/rpcinterface/service.go b/pkg/rpcinterface/service.go new file mode 100644 index 0000000..4513739 --- /dev/null +++ b/pkg/rpcinterface/service.go @@ -0,0 +1,7 @@ +package rpcinterface + +// Service defines the interface for a service +type Service interface { + NewRequest(rpcEndpoint Endpoint, opt interface{}) (*Request, error) + GetClient() Client +} diff --git a/pkg/websocketclient/websocketclient.go b/pkg/websocketclient/websocketclient.go index 38360be..085fe29 100644 --- a/pkg/websocketclient/websocketclient.go +++ b/pkg/websocketclient/websocketclient.go @@ -137,7 +137,7 @@ func (c *WebsocketClient) NewRequest(service rpcinterface.ServiceType, rpcEndpoi // Do sends an RPC request via the websocket // *http.Response is always nil in this return in async mode // call SetSyncMode() to ensure the calls return the data in a synchronous fashion -func (c *WebsocketClient) Do(req *rpcinterface.Request, v interface{}) (*http.Response, error) { +func (c *WebsocketClient) Do(req *rpcinterface.Request, v rpcinterface.IResponse) (*http.Response, error) { err := c.ensureConnection() if err != nil { return nil, fmt.Errorf("error ensuring connection: %w", err)