package jsonrpc import ( "context" "encoding/json" "errors" "fmt" "net/url" ) // Client json rpc client type Client struct { // URL is remote url, // example // http://username:password@192.168.1.3:1001/jsonrpc // ws://192.168.0.1:9121/ URL string Transport Transport } type request struct { Version string `json:"jsonrpc"` Method string `json:"method"` Params interface{} `json:"params"` ID uint64 `json:"id"` } type response struct { Version string `json:"jsonrpc"` Result json.RawMessage `json:"result"` Error *Error `json:"error"` ID uint64 `json:"id"` Method string `json:"method"` Params json.RawMessage `json:"params"` } // Error rpc error type Error struct { Code int `json:"code"` Message string `json:"message"` Data json.RawMessage `json:"data"` } func (e *Error) Error() string { return fmt.Sprintf("code: %d, message: %s, data: %s", e.Code, e.Message, e.Data) } // NewClient create a new jsonrpc client func NewClient(uri string) (*Client, error) { u, err := url.Parse(uri) if err != nil { return nil, err } t := "" switch u.Scheme { case "http", "https": t = "http" case "ws", "wss": t = "ws" default: return nil, fmt.Errorf("not supported %s", u.Scheme) } if t == "http" { tr, _ := NewHTTPTransport(uri, nil) return &Client{Transport: tr, URL: uri}, nil } if t == "ws" { tr, _ := NewWebsocketTransport(context.Background(), uri) return &Client{Transport: tr, URL: uri}, nil } return nil, errors.New("not supported") } // Call invoke a method with args and return reply func (c *Client) Call(method string, args interface{}, reply interface{}) error { return c.Transport.Call(method, args, reply) } // Subscribe subscribe for change func (c *Client) Subscribe(method, notifyMethod string, args interface{}, reply interface{}) (chan json.RawMessage, chan *Error, error) { return c.Transport.Subscribe(method, notifyMethod, args, reply) }