github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/rpc/client/http/http.go (about)

     1  package http
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net/http"
     7  	"time"
     8  
     9  	"github.com/ari-anchor/sei-tendermint/libs/bytes"
    10  	rpcclient "github.com/ari-anchor/sei-tendermint/rpc/client"
    11  	"github.com/ari-anchor/sei-tendermint/rpc/coretypes"
    12  	jsonrpcclient "github.com/ari-anchor/sei-tendermint/rpc/jsonrpc/client"
    13  	"github.com/ari-anchor/sei-tendermint/types"
    14  )
    15  
    16  /*
    17  HTTP is a Client implementation that communicates with a Tendermint node over
    18  JSON RPC and WebSockets.
    19  
    20  This is the main implementation you probably want to use in production code.
    21  There are other implementations when calling the Tendermint node in-process
    22  (Local), or when you want to mock out the server for test code (mock).
    23  
    24  You can subscribe for any event published by Tendermint using Subscribe method.
    25  Note delivery is best-effort. If you don't read events fast enough or network is
    26  slow, Tendermint might cancel the subscription. The client will attempt to
    27  resubscribe (you don't need to do anything). It will keep trying every second
    28  indefinitely until successful.
    29  
    30  Request batching is available for JSON RPC requests over HTTP, which conforms to
    31  the JSON RPC specification (https://www.jsonrpc.org/specification#batch). See
    32  the example for more details.
    33  
    34  Example:
    35  
    36  	c, err := New("http://192.168.1.10:26657")
    37  	if err != nil {
    38  		// handle error
    39  	}
    40  
    41  	// call Start/Stop if you're subscribing to events
    42  	err = c.Start()
    43  	if err != nil {
    44  		// handle error
    45  	}
    46  	defer c.Stop()
    47  
    48  	res, err := c.Status()
    49  	if err != nil {
    50  		// handle error
    51  	}
    52  
    53  	// handle result
    54  */
    55  type HTTP struct {
    56  	remote string
    57  	rpc    *jsonrpcclient.Client
    58  
    59  	*baseRPCClient
    60  	*wsEvents
    61  }
    62  
    63  // BatchHTTP provides the same interface as `HTTP`, but allows for batching of
    64  // requests (as per https://www.jsonrpc.org/specification#batch). Do not
    65  // instantiate directly - rather use the HTTP.NewBatch() method to create an
    66  // instance of this struct.
    67  //
    68  // Batching of HTTP requests is thread-safe in the sense that multiple
    69  // goroutines can each create their own batches and send them using the same
    70  // HTTP client. Multiple goroutines could also enqueue transactions in a single
    71  // batch, but ordering of transactions in the batch cannot be guaranteed in such
    72  // an example.
    73  type BatchHTTP struct {
    74  	rpcBatch *jsonrpcclient.RequestBatch
    75  	*baseRPCClient
    76  }
    77  
    78  // rpcClient is an internal interface to which our RPC clients (batch and
    79  // non-batch) must conform. Acts as an additional code-level sanity check to
    80  // make sure the implementations stay coherent.
    81  type rpcClient interface {
    82  	rpcclient.ABCIClient
    83  	rpcclient.HistoryClient
    84  	rpcclient.NetworkClient
    85  	rpcclient.SignClient
    86  	rpcclient.StatusClient
    87  }
    88  
    89  // baseRPCClient implements the basic RPC method logic without the actual
    90  // underlying RPC call functionality, which is provided by `caller`.
    91  type baseRPCClient struct {
    92  	caller jsonrpcclient.Caller
    93  }
    94  
    95  var (
    96  	_ rpcClient = (*HTTP)(nil)
    97  	_ rpcClient = (*BatchHTTP)(nil)
    98  	_ rpcClient = (*baseRPCClient)(nil)
    99  )
   100  
   101  //-----------------------------------------------------------------------------
   102  // HTTP
   103  
   104  // New takes a remote endpoint in the form <protocol>://<host>:<port>. An error
   105  // is returned on invalid remote.
   106  func New(remote string) (*HTTP, error) {
   107  	c, err := jsonrpcclient.DefaultHTTPClient(remote)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  	return NewWithClient(remote, c)
   112  }
   113  
   114  // NewWithTimeout does the same thing as New, except you can set a Timeout for
   115  // http.Client. A Timeout of zero means no timeout.
   116  func NewWithTimeout(remote string, t time.Duration) (*HTTP, error) {
   117  	c, err := jsonrpcclient.DefaultHTTPClient(remote)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	c.Timeout = t
   122  	return NewWithClient(remote, c)
   123  }
   124  
   125  // NewWithClient constructs an RPC client using a custom HTTP client.
   126  // An error is reported if c == nil or remote is an invalid address.
   127  func NewWithClient(remote string, c *http.Client) (*HTTP, error) {
   128  	if c == nil {
   129  		return nil, errors.New("nil client")
   130  	}
   131  	rpc, err := jsonrpcclient.NewWithHTTPClient(remote, c)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  
   136  	wsEvents, err := newWsEvents(remote)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	httpClient := &HTTP{
   142  		rpc:           rpc,
   143  		remote:        remote,
   144  		baseRPCClient: &baseRPCClient{caller: rpc},
   145  		wsEvents:      wsEvents,
   146  	}
   147  
   148  	return httpClient, nil
   149  }
   150  
   151  var _ rpcclient.Client = (*HTTP)(nil)
   152  
   153  // Remote returns the remote network address in a string form.
   154  func (c *HTTP) Remote() string {
   155  	return c.remote
   156  }
   157  
   158  // NewBatch creates a new batch client for this HTTP client.
   159  func (c *HTTP) NewBatch() *BatchHTTP {
   160  	rpcBatch := c.rpc.NewRequestBatch()
   161  	return &BatchHTTP{
   162  		rpcBatch: rpcBatch,
   163  		baseRPCClient: &baseRPCClient{
   164  			caller: rpcBatch,
   165  		},
   166  	}
   167  }
   168  
   169  //-----------------------------------------------------------------------------
   170  // BatchHTTP
   171  
   172  // Send is a convenience function for an HTTP batch that will trigger the
   173  // compilation of the batched requests and send them off using the client as a
   174  // single request. On success, this returns a list of the deserialized results
   175  // from each request in the sent batch.
   176  func (b *BatchHTTP) Send(ctx context.Context) ([]interface{}, error) {
   177  	return b.rpcBatch.Send(ctx)
   178  }
   179  
   180  // Clear will empty out this batch of requests and return the number of requests
   181  // that were cleared out.
   182  func (b *BatchHTTP) Clear() int {
   183  	return b.rpcBatch.Clear()
   184  }
   185  
   186  // Count returns the number of enqueued requests waiting to be sent.
   187  func (b *BatchHTTP) Count() int {
   188  	return b.rpcBatch.Count()
   189  }
   190  
   191  //-----------------------------------------------------------------------------
   192  // baseRPCClient
   193  
   194  func (c *baseRPCClient) Status(ctx context.Context) (*coretypes.ResultStatus, error) {
   195  	result := new(coretypes.ResultStatus)
   196  	if err := c.caller.Call(ctx, "status", nil, result); err != nil {
   197  		return nil, err
   198  	}
   199  	return result, nil
   200  }
   201  
   202  func (c *baseRPCClient) ABCIInfo(ctx context.Context) (*coretypes.ResultABCIInfo, error) {
   203  	result := new(coretypes.ResultABCIInfo)
   204  	if err := c.caller.Call(ctx, "abci_info", nil, result); err != nil {
   205  		return nil, err
   206  	}
   207  	return result, nil
   208  }
   209  
   210  func (c *baseRPCClient) ABCIQuery(ctx context.Context, path string, data bytes.HexBytes) (*coretypes.ResultABCIQuery, error) {
   211  	return c.ABCIQueryWithOptions(ctx, path, data, rpcclient.DefaultABCIQueryOptions)
   212  }
   213  
   214  func (c *baseRPCClient) ABCIQueryWithOptions(ctx context.Context, path string, data bytes.HexBytes, opts rpcclient.ABCIQueryOptions) (*coretypes.ResultABCIQuery, error) {
   215  	result := new(coretypes.ResultABCIQuery)
   216  	if err := c.caller.Call(ctx, "abci_query", &coretypes.RequestABCIQuery{
   217  		Path:   path,
   218  		Data:   data,
   219  		Height: coretypes.Int64(opts.Height),
   220  		Prove:  opts.Prove,
   221  	}, result); err != nil {
   222  		return nil, err
   223  	}
   224  	return result, nil
   225  }
   226  
   227  func (c *baseRPCClient) BroadcastTxCommit(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTxCommit, error) {
   228  	result := new(coretypes.ResultBroadcastTxCommit)
   229  	if err := c.caller.Call(ctx, "broadcast_tx_commit", &coretypes.RequestBroadcastTx{
   230  		Tx: tx,
   231  	}, result); err != nil {
   232  		return nil, err
   233  	}
   234  	return result, nil
   235  }
   236  
   237  func (c *baseRPCClient) BroadcastTxAsync(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
   238  	return c.broadcastTX(ctx, "broadcast_tx_async", tx)
   239  }
   240  
   241  func (c *baseRPCClient) BroadcastTxSync(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
   242  	return c.broadcastTX(ctx, "broadcast_tx_sync", tx)
   243  }
   244  
   245  func (c *baseRPCClient) BroadcastTx(ctx context.Context, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
   246  	return c.broadcastTX(ctx, "broadcast_tx_sync", tx)
   247  }
   248  
   249  func (c *baseRPCClient) broadcastTX(ctx context.Context, route string, tx types.Tx) (*coretypes.ResultBroadcastTx, error) {
   250  	result := new(coretypes.ResultBroadcastTx)
   251  	if err := c.caller.Call(ctx, route, &coretypes.RequestBroadcastTx{Tx: tx}, result); err != nil {
   252  		return nil, err
   253  	}
   254  	return result, nil
   255  }
   256  
   257  func (c *baseRPCClient) UnconfirmedTxs(ctx context.Context, page *int, perPage *int) (*coretypes.ResultUnconfirmedTxs, error) {
   258  	result := new(coretypes.ResultUnconfirmedTxs)
   259  
   260  	if err := c.caller.Call(ctx, "unconfirmed_txs", &coretypes.RequestUnconfirmedTxs{
   261  		Page:    coretypes.Int64Ptr(page),
   262  		PerPage: coretypes.Int64Ptr(perPage),
   263  	}, result); err != nil {
   264  		return nil, err
   265  	}
   266  	return result, nil
   267  }
   268  
   269  func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*coretypes.ResultUnconfirmedTxs, error) {
   270  	result := new(coretypes.ResultUnconfirmedTxs)
   271  	if err := c.caller.Call(ctx, "num_unconfirmed_txs", nil, result); err != nil {
   272  		return nil, err
   273  	}
   274  	return result, nil
   275  }
   276  
   277  func (c *baseRPCClient) CheckTx(ctx context.Context, tx types.Tx) (*coretypes.ResultCheckTx, error) {
   278  	result := new(coretypes.ResultCheckTx)
   279  	if err := c.caller.Call(ctx, "check_tx", &coretypes.RequestCheckTx{Tx: tx}, result); err != nil {
   280  		return nil, err
   281  	}
   282  	return result, nil
   283  }
   284  
   285  func (c *baseRPCClient) RemoveTx(ctx context.Context, txKey types.TxKey) error {
   286  	if err := c.caller.Call(ctx, "remove_tx", &coretypes.RequestRemoveTx{TxKey: txKey}, nil); err != nil {
   287  		return err
   288  	}
   289  	return nil
   290  }
   291  
   292  func (c *baseRPCClient) NetInfo(ctx context.Context) (*coretypes.ResultNetInfo, error) {
   293  	result := new(coretypes.ResultNetInfo)
   294  	if err := c.caller.Call(ctx, "net_info", nil, result); err != nil {
   295  		return nil, err
   296  	}
   297  	return result, nil
   298  }
   299  
   300  func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*coretypes.ResultDumpConsensusState, error) {
   301  	result := new(coretypes.ResultDumpConsensusState)
   302  	if err := c.caller.Call(ctx, "dump_consensus_state", nil, result); err != nil {
   303  		return nil, err
   304  	}
   305  	return result, nil
   306  }
   307  
   308  func (c *baseRPCClient) ConsensusState(ctx context.Context) (*coretypes.ResultConsensusState, error) {
   309  	result := new(coretypes.ResultConsensusState)
   310  	if err := c.caller.Call(ctx, "consensus_state", nil, result); err != nil {
   311  		return nil, err
   312  	}
   313  	return result, nil
   314  }
   315  
   316  func (c *baseRPCClient) ConsensusParams(ctx context.Context, height *int64) (*coretypes.ResultConsensusParams, error) {
   317  	result := new(coretypes.ResultConsensusParams)
   318  	if err := c.caller.Call(ctx, "consensus_params", &coretypes.RequestConsensusParams{
   319  		Height: (*coretypes.Int64)(height),
   320  	}, result); err != nil {
   321  		return nil, err
   322  	}
   323  	return result, nil
   324  }
   325  
   326  func (c *baseRPCClient) Events(ctx context.Context, req *coretypes.RequestEvents) (*coretypes.ResultEvents, error) {
   327  	result := new(coretypes.ResultEvents)
   328  	if err := c.caller.Call(ctx, "events", req, result); err != nil {
   329  		return nil, err
   330  	}
   331  	return result, nil
   332  }
   333  
   334  func (c *baseRPCClient) Health(ctx context.Context) (*coretypes.ResultHealth, error) {
   335  	result := new(coretypes.ResultHealth)
   336  	if err := c.caller.Call(ctx, "health", nil, result); err != nil {
   337  		return nil, err
   338  	}
   339  	return result, nil
   340  }
   341  
   342  func (c *baseRPCClient) BlockchainInfo(ctx context.Context, minHeight, maxHeight int64) (*coretypes.ResultBlockchainInfo, error) {
   343  	result := new(coretypes.ResultBlockchainInfo)
   344  	if err := c.caller.Call(ctx, "blockchain", &coretypes.RequestBlockchainInfo{
   345  		MinHeight: coretypes.Int64(minHeight),
   346  		MaxHeight: coretypes.Int64(maxHeight),
   347  	}, result); err != nil {
   348  		return nil, err
   349  	}
   350  	return result, nil
   351  }
   352  
   353  func (c *baseRPCClient) Genesis(ctx context.Context) (*coretypes.ResultGenesis, error) {
   354  	result := new(coretypes.ResultGenesis)
   355  	if err := c.caller.Call(ctx, "genesis", nil, result); err != nil {
   356  		return nil, err
   357  	}
   358  	return result, nil
   359  }
   360  
   361  func (c *baseRPCClient) GenesisChunked(ctx context.Context, id uint) (*coretypes.ResultGenesisChunk, error) {
   362  	result := new(coretypes.ResultGenesisChunk)
   363  	if err := c.caller.Call(ctx, "genesis_chunked", &coretypes.RequestGenesisChunked{
   364  		Chunk: coretypes.Int64(id),
   365  	}, result); err != nil {
   366  		return nil, err
   367  	}
   368  	return result, nil
   369  }
   370  
   371  func (c *baseRPCClient) Block(ctx context.Context, height *int64) (*coretypes.ResultBlock, error) {
   372  	result := new(coretypes.ResultBlock)
   373  	if err := c.caller.Call(ctx, "block", &coretypes.RequestBlockInfo{
   374  		Height: (*coretypes.Int64)(height),
   375  	}, result); err != nil {
   376  		return nil, err
   377  	}
   378  	return result, nil
   379  }
   380  
   381  func (c *baseRPCClient) BlockByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultBlock, error) {
   382  	result := new(coretypes.ResultBlock)
   383  	if err := c.caller.Call(ctx, "block_by_hash", &coretypes.RequestBlockByHash{Hash: hash}, result); err != nil {
   384  		return nil, err
   385  	}
   386  	return result, nil
   387  }
   388  
   389  func (c *baseRPCClient) BlockResults(ctx context.Context, height *int64) (*coretypes.ResultBlockResults, error) {
   390  	result := new(coretypes.ResultBlockResults)
   391  	if err := c.caller.Call(ctx, "block_results", &coretypes.RequestBlockInfo{
   392  		Height: (*coretypes.Int64)(height),
   393  	}, result); err != nil {
   394  		return nil, err
   395  	}
   396  	return result, nil
   397  }
   398  
   399  func (c *baseRPCClient) Header(ctx context.Context, height *int64) (*coretypes.ResultHeader, error) {
   400  	result := new(coretypes.ResultHeader)
   401  	if err := c.caller.Call(ctx, "header", &coretypes.RequestBlockInfo{
   402  		Height: (*coretypes.Int64)(height),
   403  	}, result); err != nil {
   404  		return nil, err
   405  	}
   406  	return result, nil
   407  }
   408  
   409  func (c *baseRPCClient) HeaderByHash(ctx context.Context, hash bytes.HexBytes) (*coretypes.ResultHeader, error) {
   410  	result := new(coretypes.ResultHeader)
   411  	if err := c.caller.Call(ctx, "header_by_hash", &coretypes.RequestBlockByHash{
   412  		Hash: hash,
   413  	}, result); err != nil {
   414  		return nil, err
   415  	}
   416  	return result, nil
   417  }
   418  
   419  func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*coretypes.ResultCommit, error) {
   420  	result := new(coretypes.ResultCommit)
   421  	if err := c.caller.Call(ctx, "commit", &coretypes.RequestBlockInfo{
   422  		Height: (*coretypes.Int64)(height),
   423  	}, result); err != nil {
   424  		return nil, err
   425  	}
   426  	return result, nil
   427  }
   428  
   429  func (c *baseRPCClient) Tx(ctx context.Context, hash bytes.HexBytes, prove bool) (*coretypes.ResultTx, error) {
   430  	result := new(coretypes.ResultTx)
   431  	if err := c.caller.Call(ctx, "tx", &coretypes.RequestTx{Hash: hash, Prove: prove}, result); err != nil {
   432  		return nil, err
   433  	}
   434  	return result, nil
   435  }
   436  
   437  func (c *baseRPCClient) TxSearch(ctx context.Context, query string, prove bool, page, perPage *int, orderBy string) (*coretypes.ResultTxSearch, error) {
   438  	result := new(coretypes.ResultTxSearch)
   439  	if err := c.caller.Call(ctx, "tx_search", &coretypes.RequestTxSearch{
   440  		Query:   query,
   441  		Prove:   prove,
   442  		OrderBy: orderBy,
   443  		Page:    coretypes.Int64Ptr(page),
   444  		PerPage: coretypes.Int64Ptr(perPage),
   445  	}, result); err != nil {
   446  		return nil, err
   447  	}
   448  
   449  	return result, nil
   450  }
   451  
   452  func (c *baseRPCClient) BlockSearch(ctx context.Context, query string, page, perPage *int, orderBy string) (*coretypes.ResultBlockSearch, error) {
   453  	result := new(coretypes.ResultBlockSearch)
   454  	if err := c.caller.Call(ctx, "block_search", &coretypes.RequestBlockSearch{
   455  		Query:   query,
   456  		OrderBy: orderBy,
   457  		Page:    coretypes.Int64Ptr(page),
   458  		PerPage: coretypes.Int64Ptr(perPage),
   459  	}, result); err != nil {
   460  		return nil, err
   461  	}
   462  
   463  	return result, nil
   464  }
   465  
   466  func (c *baseRPCClient) Validators(ctx context.Context, height *int64, page, perPage *int) (*coretypes.ResultValidators, error) {
   467  	result := new(coretypes.ResultValidators)
   468  	if err := c.caller.Call(ctx, "validators", &coretypes.RequestValidators{
   469  		Height:  (*coretypes.Int64)(height),
   470  		Page:    coretypes.Int64Ptr(page),
   471  		PerPage: coretypes.Int64Ptr(perPage),
   472  	}, result); err != nil {
   473  		return nil, err
   474  	}
   475  	return result, nil
   476  }
   477  
   478  func (c *baseRPCClient) BroadcastEvidence(ctx context.Context, ev types.Evidence) (*coretypes.ResultBroadcastEvidence, error) {
   479  	result := new(coretypes.ResultBroadcastEvidence)
   480  	if err := c.caller.Call(ctx, "broadcast_evidence", &coretypes.RequestBroadcastEvidence{
   481  		Evidence: ev,
   482  	}, result); err != nil {
   483  		return nil, err
   484  	}
   485  	return result, nil
   486  }