Browse Source

rpc: simplify the JSON-RPC client Caller interface (#7549)

* Update Caller interface and its documentation.
* Rework MapToRequest as ParamsToRequest.

The old interface returned the result as well as populating it.  Nothing was
using this, so drop the duplicated value from the return signature. Clarify the
documentation on the Caller type.

Rework the MapToRequest helper to take an arbitrary value instead of only a
map. This is groundwork for getting rid of the custom marshaling code. For now,
however, the implementation preserves the existing behaviour for the map, until
we can replace those.
pull/7552/head
M. J. Fromberger 3 years ago
committed by GitHub
parent
commit
6291d22f46
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 112 deletions
  1. +30
    -61
      rpc/client/http/http.go
  2. +6
    -12
      rpc/jsonrpc/client/decode.go
  3. +19
    -23
      rpc/jsonrpc/client/http_json_client.go
  4. +1
    -1
      rpc/jsonrpc/client/ws_client.go
  5. +4
    -4
      rpc/jsonrpc/jsonrpc_test.go
  6. +1
    -1
      rpc/jsonrpc/server/ws_handler_test.go
  7. +19
    -9
      rpc/jsonrpc/types/types.go
  8. +1
    -1
      rpc/test/helpers.go

+ 30
- 61
rpc/client/http/http.go View File

@ -203,21 +203,17 @@ func (b *BatchHTTP) Count() int {
func (c *baseRPCClient) Status(ctx context.Context) (*coretypes.ResultStatus, error) { func (c *baseRPCClient) Status(ctx context.Context) (*coretypes.ResultStatus, error) {
result := new(coretypes.ResultStatus) result := new(coretypes.ResultStatus)
_, err := c.caller.Call(ctx, "status", map[string]interface{}{}, result)
if err != nil {
if err := c.caller.Call(ctx, "status", map[string]interface{}{}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
} }
func (c *baseRPCClient) ABCIInfo(ctx context.Context) (*coretypes.ResultABCIInfo, error) { func (c *baseRPCClient) ABCIInfo(ctx context.Context) (*coretypes.ResultABCIInfo, error) {
result := new(coretypes.ResultABCIInfo) result := new(coretypes.ResultABCIInfo)
_, err := c.caller.Call(ctx, "abci_info", map[string]interface{}{}, result)
if err != nil {
if err := c.caller.Call(ctx, "abci_info", map[string]interface{}{}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
} }
@ -235,13 +231,11 @@ func (c *baseRPCClient) ABCIQueryWithOptions(
data bytes.HexBytes, data bytes.HexBytes,
opts rpcclient.ABCIQueryOptions) (*coretypes.ResultABCIQuery, error) { opts rpcclient.ABCIQueryOptions) (*coretypes.ResultABCIQuery, error) {
result := new(coretypes.ResultABCIQuery) result := new(coretypes.ResultABCIQuery)
_, err := c.caller.Call(ctx, "abci_query",
if err := c.caller.Call(ctx, "abci_query",
map[string]interface{}{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove}, map[string]interface{}{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove},
result)
if err != nil {
result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
} }
@ -250,8 +244,7 @@ func (c *baseRPCClient) BroadcastTxCommit(
tx types.Tx, tx types.Tx,
) (*coretypes.ResultBroadcastTxCommit, error) { ) (*coretypes.ResultBroadcastTxCommit, error) {
result := new(coretypes.ResultBroadcastTxCommit) result := new(coretypes.ResultBroadcastTxCommit)
_, err := c.caller.Call(ctx, "broadcast_tx_commit", map[string]interface{}{"tx": tx}, result)
if err != nil {
if err := c.caller.Call(ctx, "broadcast_tx_commit", map[string]interface{}{"tx": tx}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -277,8 +270,7 @@ func (c *baseRPCClient) broadcastTX(
tx types.Tx, tx types.Tx,
) (*coretypes.ResultBroadcastTx, error) { ) (*coretypes.ResultBroadcastTx, error) {
result := new(coretypes.ResultBroadcastTx) result := new(coretypes.ResultBroadcastTx)
_, err := c.caller.Call(ctx, route, map[string]interface{}{"tx": tx}, result)
if err != nil {
if err := c.caller.Call(ctx, route, map[string]interface{}{"tx": tx}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -293,8 +285,7 @@ func (c *baseRPCClient) UnconfirmedTxs(
if limit != nil { if limit != nil {
params["limit"] = limit params["limit"] = limit
} }
_, err := c.caller.Call(ctx, "unconfirmed_txs", params, result)
if err != nil {
if err := c.caller.Call(ctx, "unconfirmed_txs", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -302,8 +293,7 @@ func (c *baseRPCClient) UnconfirmedTxs(
func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*coretypes.ResultUnconfirmedTxs, error) { func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*coretypes.ResultUnconfirmedTxs, error) {
result := new(coretypes.ResultUnconfirmedTxs) result := new(coretypes.ResultUnconfirmedTxs)
_, err := c.caller.Call(ctx, "num_unconfirmed_txs", map[string]interface{}{}, result)
if err != nil {
if err := c.caller.Call(ctx, "num_unconfirmed_txs", map[string]interface{}{}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -311,16 +301,14 @@ func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*coretypes.Resul
func (c *baseRPCClient) CheckTx(ctx context.Context, tx types.Tx) (*coretypes.ResultCheckTx, error) { func (c *baseRPCClient) CheckTx(ctx context.Context, tx types.Tx) (*coretypes.ResultCheckTx, error) {
result := new(coretypes.ResultCheckTx) result := new(coretypes.ResultCheckTx)
_, err := c.caller.Call(ctx, "check_tx", map[string]interface{}{"tx": tx}, result)
if err != nil {
if err := c.caller.Call(ctx, "check_tx", map[string]interface{}{"tx": tx}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
} }
func (c *baseRPCClient) RemoveTx(ctx context.Context, txKey types.TxKey) error { func (c *baseRPCClient) RemoveTx(ctx context.Context, txKey types.TxKey) error {
_, err := c.caller.Call(ctx, "remove_tx", map[string]interface{}{"tx_key": txKey}, nil)
if err != nil {
if err := c.caller.Call(ctx, "remove_tx", map[string]interface{}{"tx_key": txKey}, nil); err != nil {
return err return err
} }
return nil return nil
@ -328,8 +316,7 @@ func (c *baseRPCClient) RemoveTx(ctx context.Context, txKey types.TxKey) error {
func (c *baseRPCClient) NetInfo(ctx context.Context) (*coretypes.ResultNetInfo, error) { func (c *baseRPCClient) NetInfo(ctx context.Context) (*coretypes.ResultNetInfo, error) {
result := new(coretypes.ResultNetInfo) result := new(coretypes.ResultNetInfo)
_, err := c.caller.Call(ctx, "net_info", map[string]interface{}{}, result)
if err != nil {
if err := c.caller.Call(ctx, "net_info", map[string]interface{}{}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -337,8 +324,7 @@ func (c *baseRPCClient) NetInfo(ctx context.Context) (*coretypes.ResultNetInfo,
func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*coretypes.ResultDumpConsensusState, error) { func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*coretypes.ResultDumpConsensusState, error) {
result := new(coretypes.ResultDumpConsensusState) result := new(coretypes.ResultDumpConsensusState)
_, err := c.caller.Call(ctx, "dump_consensus_state", map[string]interface{}{}, result)
if err != nil {
if err := c.caller.Call(ctx, "dump_consensus_state", map[string]interface{}{}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -346,8 +332,7 @@ func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*coretypes.Resu
func (c *baseRPCClient) ConsensusState(ctx context.Context) (*coretypes.ResultConsensusState, error) { func (c *baseRPCClient) ConsensusState(ctx context.Context) (*coretypes.ResultConsensusState, error) {
result := new(coretypes.ResultConsensusState) result := new(coretypes.ResultConsensusState)
_, err := c.caller.Call(ctx, "consensus_state", map[string]interface{}{}, result)
if err != nil {
if err := c.caller.Call(ctx, "consensus_state", map[string]interface{}{}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -362,8 +347,7 @@ func (c *baseRPCClient) ConsensusParams(
if height != nil { if height != nil {
params["height"] = height params["height"] = height
} }
_, err := c.caller.Call(ctx, "consensus_params", params, result)
if err != nil {
if err := c.caller.Call(ctx, "consensus_params", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -371,8 +355,7 @@ func (c *baseRPCClient) ConsensusParams(
func (c *baseRPCClient) Health(ctx context.Context) (*coretypes.ResultHealth, error) { func (c *baseRPCClient) Health(ctx context.Context) (*coretypes.ResultHealth, error) {
result := new(coretypes.ResultHealth) result := new(coretypes.ResultHealth)
_, err := c.caller.Call(ctx, "health", map[string]interface{}{}, result)
if err != nil {
if err := c.caller.Call(ctx, "health", map[string]interface{}{}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -384,10 +367,9 @@ func (c *baseRPCClient) BlockchainInfo(
maxHeight int64, maxHeight int64,
) (*coretypes.ResultBlockchainInfo, error) { ) (*coretypes.ResultBlockchainInfo, error) {
result := new(coretypes.ResultBlockchainInfo) result := new(coretypes.ResultBlockchainInfo)
_, err := c.caller.Call(ctx, "blockchain",
if err := c.caller.Call(ctx, "blockchain",
map[string]interface{}{"minHeight": minHeight, "maxHeight": maxHeight}, map[string]interface{}{"minHeight": minHeight, "maxHeight": maxHeight},
result)
if err != nil {
result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -395,8 +377,7 @@ func (c *baseRPCClient) BlockchainInfo(
func (c *baseRPCClient) Genesis(ctx context.Context) (*coretypes.ResultGenesis, error) { func (c *baseRPCClient) Genesis(ctx context.Context) (*coretypes.ResultGenesis, error) {
result := new(coretypes.ResultGenesis) result := new(coretypes.ResultGenesis)
_, err := c.caller.Call(ctx, "genesis", map[string]interface{}{}, result)
if err != nil {
if err := c.caller.Call(ctx, "genesis", map[string]interface{}{}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -404,8 +385,7 @@ func (c *baseRPCClient) Genesis(ctx context.Context) (*coretypes.ResultGenesis,
func (c *baseRPCClient) GenesisChunked(ctx context.Context, id uint) (*coretypes.ResultGenesisChunk, error) { func (c *baseRPCClient) GenesisChunked(ctx context.Context, id uint) (*coretypes.ResultGenesisChunk, error) {
result := new(coretypes.ResultGenesisChunk) result := new(coretypes.ResultGenesisChunk)
_, err := c.caller.Call(ctx, "genesis_chunked", map[string]interface{}{"chunk": id}, result)
if err != nil {
if err := c.caller.Call(ctx, "genesis_chunked", map[string]interface{}{"chunk": id}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -417,8 +397,7 @@ func (c *baseRPCClient) Block(ctx context.Context, height *int64) (*coretypes.Re
if height != nil { if height != nil {
params["height"] = height params["height"] = height
} }
_, err := c.caller.Call(ctx, "block", params, result)
if err != nil {
if err := c.caller.Call(ctx, "block", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -429,8 +408,7 @@ func (c *baseRPCClient) BlockByHash(ctx context.Context, hash bytes.HexBytes) (*
params := map[string]interface{}{ params := map[string]interface{}{
"hash": hash, "hash": hash,
} }
_, err := c.caller.Call(ctx, "block_by_hash", params, result)
if err != nil {
if err := c.caller.Call(ctx, "block_by_hash", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -445,8 +423,7 @@ func (c *baseRPCClient) BlockResults(
if height != nil { if height != nil {
params["height"] = height params["height"] = height
} }
_, err := c.caller.Call(ctx, "block_results", params, result)
if err != nil {
if err := c.caller.Call(ctx, "block_results", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -458,8 +435,7 @@ func (c *baseRPCClient) Header(ctx context.Context, height *int64) (*coretypes.R
if height != nil { if height != nil {
params["height"] = height params["height"] = height
} }
_, err := c.caller.Call(ctx, "header", params, result)
if err != nil {
if err := c.caller.Call(ctx, "header", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -470,8 +446,7 @@ func (c *baseRPCClient) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (
params := map[string]interface{}{ params := map[string]interface{}{
"hash": hash, "hash": hash,
} }
_, err := c.caller.Call(ctx, "header_by_hash", params, result)
if err != nil {
if err := c.caller.Call(ctx, "header_by_hash", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -483,8 +458,7 @@ func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*coretypes.R
if height != nil { if height != nil {
params["height"] = height params["height"] = height
} }
_, err := c.caller.Call(ctx, "commit", params, result)
if err != nil {
if err := c.caller.Call(ctx, "commit", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -496,8 +470,7 @@ func (c *baseRPCClient) Tx(ctx context.Context, hash bytes.HexBytes, prove bool)
"hash": hash, "hash": hash,
"prove": prove, "prove": prove,
} }
_, err := c.caller.Call(ctx, "tx", params, result)
if err != nil {
if err := c.caller.Call(ctx, "tx", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -526,8 +499,7 @@ func (c *baseRPCClient) TxSearch(
params["per_page"] = perPage params["per_page"] = perPage
} }
_, err := c.caller.Call(ctx, "tx_search", params, result)
if err != nil {
if err := c.caller.Call(ctx, "tx_search", params, result); err != nil {
return nil, err return nil, err
} }
@ -554,8 +526,7 @@ func (c *baseRPCClient) BlockSearch(
params["per_page"] = perPage params["per_page"] = perPage
} }
_, err := c.caller.Call(ctx, "block_search", params, result)
if err != nil {
if err := c.caller.Call(ctx, "block_search", params, result); err != nil {
return nil, err return nil, err
} }
@ -579,8 +550,7 @@ func (c *baseRPCClient) Validators(
if height != nil { if height != nil {
params["height"] = height params["height"] = height
} }
_, err := c.caller.Call(ctx, "validators", params, result)
if err != nil {
if err := c.caller.Call(ctx, "validators", params, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil
@ -591,8 +561,7 @@ func (c *baseRPCClient) BroadcastEvidence(
ev types.Evidence, ev types.Evidence,
) (*coretypes.ResultBroadcastEvidence, error) { ) (*coretypes.ResultBroadcastEvidence, error) {
result := new(coretypes.ResultBroadcastEvidence) result := new(coretypes.ResultBroadcastEvidence)
_, err := c.caller.Call(ctx, "broadcast_evidence", map[string]interface{}{"evidence": ev}, result)
if err != nil {
if err := c.caller.Call(ctx, "broadcast_evidence", map[string]interface{}{"evidence": ev}, result); err != nil {
return nil, err return nil, err
} }
return result, nil return result, nil


+ 6
- 12
rpc/jsonrpc/client/decode.go View File

@ -9,33 +9,27 @@ import (
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types" rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
) )
func unmarshalResponseBytes(
responseBytes []byte,
expectedID rpctypes.JSONRPCIntID,
result interface{},
) (interface{}, error) {
func unmarshalResponseBytes(responseBytes []byte, expectedID rpctypes.JSONRPCIntID, result interface{}) error {
// Read response. If rpc/core/types is imported, the result will unmarshal // Read response. If rpc/core/types is imported, the result will unmarshal
// into the correct type. // into the correct type.
response := &rpctypes.RPCResponse{} response := &rpctypes.RPCResponse{}
if err := json.Unmarshal(responseBytes, response); err != nil { if err := json.Unmarshal(responseBytes, response); err != nil {
return nil, fmt.Errorf("error unmarshaling: %w", err)
return fmt.Errorf("error unmarshaling: %w", err)
} }
if response.Error != nil { if response.Error != nil {
return nil, response.Error
return response.Error
} }
if err := validateAndVerifyID(response, expectedID); err != nil { if err := validateAndVerifyID(response, expectedID); err != nil {
return nil, fmt.Errorf("wrong ID: %w", err)
return fmt.Errorf("wrong ID: %w", err)
} }
// Unmarshal the RawMessage into the result. // Unmarshal the RawMessage into the result.
if err := tmjson.Unmarshal(response.Result, result); err != nil { if err := tmjson.Unmarshal(response.Result, result); err != nil {
return nil, fmt.Errorf("error unmarshaling result: %w", err)
return fmt.Errorf("error unmarshaling result: %w", err)
} }
return result, nil
return nil
} }
func unmarshalResponseBytesArray( func unmarshalResponseBytesArray(


+ 19
- 23
rpc/jsonrpc/client/http_json_client.go View File

@ -106,9 +106,15 @@ func (u parsedURL) GetTrimmedURL() string {
//------------------------------------------------------------- //-------------------------------------------------------------
// Caller implementers can facilitate calling the JSON-RPC endpoint.
// A Caller handles the round trip of a single JSON-RPC request. The
// implementation is responsible for assigning request IDs, marshaling
// parameters, and unmarshaling results.
type Caller interface { type Caller interface {
Call(ctx context.Context, method string, params map[string]interface{}, result interface{}) (interface{}, error)
// Call sends a new request for method to the server with the given
// parameters. If params == nil, the request has empty parameters.
// If result == nil, any result value must be discarded without error.
// Otherwise the concrete value of result must be a pointer.
Call(ctx context.Context, method string, params, result interface{}) error
} }
//------------------------------------------------------------- //-------------------------------------------------------------
@ -174,28 +180,23 @@ func NewWithHTTPClient(remote string, c *http.Client) (*Client, error) {
// Call issues a POST HTTP request. Requests are JSON encoded. Content-Type: // Call issues a POST HTTP request. Requests are JSON encoded. Content-Type:
// application/json. // application/json.
func (c *Client) Call(
ctx context.Context,
method string,
params map[string]interface{},
result interface{},
) (interface{}, error) {
func (c *Client) Call(ctx context.Context, method string, params, result interface{}) error {
id := c.nextRequestID() id := c.nextRequestID()
request, err := rpctypes.MapToRequest(id, method, params)
request, err := rpctypes.ParamsToRequest(id, method, params)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encode params: %w", err)
return fmt.Errorf("failed to encode params: %w", err)
} }
requestBytes, err := json.Marshal(request) requestBytes, err := json.Marshal(request)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
return fmt.Errorf("failed to marshal request: %w", err)
} }
requestBuf := bytes.NewBuffer(requestBytes) requestBuf := bytes.NewBuffer(requestBytes)
httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, c.address, requestBuf) httpRequest, err := http.NewRequestWithContext(ctx, http.MethodPost, c.address, requestBuf)
if err != nil { if err != nil {
return nil, fmt.Errorf("request setup failed: %w", err)
return fmt.Errorf("request setup failed: %w", err)
} }
httpRequest.Header.Set("Content-Type", "application/json") httpRequest.Header.Set("Content-Type", "application/json")
@ -206,14 +207,14 @@ func (c *Client) Call(
httpResponse, err := c.client.Do(httpRequest) httpResponse, err := c.client.Do(httpRequest)
if err != nil { if err != nil {
return nil, err
return err
} }
defer httpResponse.Body.Close() defer httpResponse.Body.Close()
responseBytes, err := io.ReadAll(httpResponse.Body) responseBytes, err := io.ReadAll(httpResponse.Body)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
return fmt.Errorf("failed to read response body: %w", err)
} }
return unmarshalResponseBytes(responseBytes, id, result) return unmarshalResponseBytes(responseBytes, id, result)
@ -340,19 +341,14 @@ func (b *RequestBatch) Send(ctx context.Context) ([]interface{}, error) {
// Call enqueues a request to call the given RPC method with the specified // Call enqueues a request to call the given RPC method with the specified
// parameters, in the same way that the `Client.Call` function would. // parameters, in the same way that the `Client.Call` function would.
func (b *RequestBatch) Call(
_ context.Context,
method string,
params map[string]interface{},
result interface{},
) (interface{}, error) {
func (b *RequestBatch) Call(_ context.Context, method string, params, result interface{}) error {
id := b.client.nextRequestID() id := b.client.nextRequestID()
request, err := rpctypes.MapToRequest(id, method, params)
request, err := rpctypes.ParamsToRequest(id, method, params)
if err != nil { if err != nil {
return nil, err
return err
} }
b.enqueue(&jsonRPCBufferedRequest{request: request, result: result}) b.enqueue(&jsonRPCBufferedRequest{request: request, result: result})
return result, nil
return nil
} }
//------------------------------------------------------------- //-------------------------------------------------------------


+ 1
- 1
rpc/jsonrpc/client/ws_client.go View File

@ -217,7 +217,7 @@ func (c *WSClient) Send(ctx context.Context, request rpctypes.RPCRequest) error
// Call enqueues a call request onto the Send queue. Requests are JSON encoded. // Call enqueues a call request onto the Send queue. Requests are JSON encoded.
func (c *WSClient) Call(ctx context.Context, method string, params map[string]interface{}) error { func (c *WSClient) Call(ctx context.Context, method string, params map[string]interface{}) error {
request, err := rpctypes.MapToRequest(c.nextRequestID(), method, params)
request, err := rpctypes.ParamsToRequest(c.nextRequestID(), method, params)
if err != nil { if err != nil {
return err return err
} }


+ 4
- 4
rpc/jsonrpc/jsonrpc_test.go View File

@ -148,7 +148,7 @@ func echoViaHTTP(ctx context.Context, cl client.Caller, val string) (string, err
"arg": val, "arg": val,
} }
result := new(ResultEcho) result := new(ResultEcho)
if _, err := cl.Call(ctx, "echo", params, result); err != nil {
if err := cl.Call(ctx, "echo", params, result); err != nil {
return "", err return "", err
} }
return result.Value, nil return result.Value, nil
@ -159,7 +159,7 @@ func echoIntViaHTTP(ctx context.Context, cl client.Caller, val int) (int, error)
"arg": val, "arg": val,
} }
result := new(ResultEchoInt) result := new(ResultEchoInt)
if _, err := cl.Call(ctx, "echo_int", params, result); err != nil {
if err := cl.Call(ctx, "echo_int", params, result); err != nil {
return 0, err return 0, err
} }
return result.Value, nil return result.Value, nil
@ -170,7 +170,7 @@ func echoBytesViaHTTP(ctx context.Context, cl client.Caller, bytes []byte) ([]by
"arg": bytes, "arg": bytes,
} }
result := new(ResultEchoBytes) result := new(ResultEchoBytes)
if _, err := cl.Call(ctx, "echo_bytes", params, result); err != nil {
if err := cl.Call(ctx, "echo_bytes", params, result); err != nil {
return []byte{}, err return []byte{}, err
} }
return result.Value, nil return result.Value, nil
@ -181,7 +181,7 @@ func echoDataBytesViaHTTP(ctx context.Context, cl client.Caller, bytes tmbytes.H
"arg": bytes, "arg": bytes,
} }
result := new(ResultEchoDataBytes) result := new(ResultEchoDataBytes)
if _, err := cl.Call(ctx, "echo_data_bytes", params, result); err != nil {
if err := cl.Call(ctx, "echo_data_bytes", params, result); err != nil {
return []byte{}, err return []byte{}, err
} }
return result.Value, nil return result.Value, nil


+ 1
- 1
rpc/jsonrpc/server/ws_handler_test.go View File

@ -28,7 +28,7 @@ func TestWebsocketManagerHandler(t *testing.T) {
} }
// check basic functionality works // check basic functionality works
req, err := rpctypes.MapToRequest(
req, err := rpctypes.ParamsToRequest(
rpctypes.JSONRPCStringID("TestWebsocketManager"), rpctypes.JSONRPCStringID("TestWebsocketManager"),
"c", "c",
map[string]interface{}{"s": "a", "i": 10}, map[string]interface{}{"s": "a", "i": 10},


+ 19
- 9
rpc/jsonrpc/types/types.go View File

@ -98,17 +98,27 @@ func (req RPCRequest) String() string {
return fmt.Sprintf("RPCRequest{%s %s/%X}", req.ID, req.Method, req.Params) return fmt.Sprintf("RPCRequest{%s %s/%X}", req.ID, req.Method, req.Params)
} }
func MapToRequest(id jsonrpcid, method string, params map[string]interface{}) (RPCRequest, error) {
var paramsMap = make(map[string]json.RawMessage, len(params))
for name, value := range params {
valueJSON, err := tmjson.Marshal(value)
if err != nil {
return RPCRequest{}, err
// ParamsToRequest constructs a new RPCRequest with the given ID, method, and parameters.
func ParamsToRequest(id jsonrpcid, method string, params interface{}) (RPCRequest, error) {
var payload json.RawMessage
var err error
switch t := params.(type) {
case map[string]interface{}:
// TODO(creachadair): This special case preserves existing behavior that
// relies on the custom JSON encoding library. Remove it once that
// requirement has been removed.
paramsMap := make(map[string]json.RawMessage, len(t))
for name, value := range t {
valueJSON, err := tmjson.Marshal(value)
if err != nil {
return RPCRequest{}, err
}
paramsMap[name] = valueJSON
} }
paramsMap[name] = valueJSON
payload, err = json.Marshal(paramsMap)
default:
payload, err = json.Marshal(params)
} }
payload, err := json.Marshal(paramsMap)
if err != nil { if err != nil {
return RPCRequest{}, err return RPCRequest{}, err
} }


+ 1
- 1
rpc/test/helpers.go View File

@ -32,7 +32,7 @@ func waitForRPC(ctx context.Context, conf *config.Config) {
} }
result := new(coretypes.ResultStatus) result := new(coretypes.ResultStatus)
for { for {
_, err := client.Call(ctx, "status", map[string]interface{}{}, result)
err := client.Call(ctx, "status", map[string]interface{}{}, result)
if err == nil { if err == nil {
return return
} }


Loading…
Cancel
Save