github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/rpc/client/http/http.go (about)

     1  package http
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net/http"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/lazyledger/lazyledger-core/libs/bytes"
    11  	tmjson "github.com/lazyledger/lazyledger-core/libs/json"
    12  	"github.com/lazyledger/lazyledger-core/libs/log"
    13  	tmpubsub "github.com/lazyledger/lazyledger-core/libs/pubsub"
    14  	"github.com/lazyledger/lazyledger-core/libs/service"
    15  	tmsync "github.com/lazyledger/lazyledger-core/libs/sync"
    16  	rpcclient "github.com/lazyledger/lazyledger-core/rpc/client"
    17  	ctypes "github.com/lazyledger/lazyledger-core/rpc/core/types"
    18  	jsonrpcclient "github.com/lazyledger/lazyledger-core/rpc/jsonrpc/client"
    19  	"github.com/lazyledger/lazyledger-core/types"
    20  )
    21  
    22  /*
    23  HTTP is a Client implementation that communicates with a Tendermint node over
    24  JSON RPC and WebSockets.
    25  
    26  This is the main implementation you probably want to use in production code.
    27  There are other implementations when calling the Tendermint node in-process
    28  (Local), or when you want to mock out the server for test code (mock).
    29  
    30  You can subscribe for any event published by Tendermint using Subscribe method.
    31  Note delivery is best-effort. If you don't read events fast enough or network is
    32  slow, Tendermint might cancel the subscription. The client will attempt to
    33  resubscribe (you don't need to do anything). It will keep trying every second
    34  indefinitely until successful.
    35  
    36  Request batching is available for JSON RPC requests over HTTP, which conforms to
    37  the JSON RPC specification (https://www.jsonrpc.org/specification#batch). See
    38  the example for more details.
    39  
    40  Example:
    41  
    42  		c, err := New("http://192.168.1.10:26657", "/websocket")
    43  		if err != nil {
    44  			// handle error
    45  		}
    46  
    47  		// call Start/Stop if you're subscribing to events
    48  		err = c.Start()
    49  		if err != nil {
    50  			// handle error
    51  		}
    52  		defer c.Stop()
    53  
    54  		res, err := c.Status()
    55  		if err != nil {
    56  			// handle error
    57  		}
    58  
    59  		// handle result
    60  */
    61  type HTTP struct {
    62  	remote string
    63  	rpc    *jsonrpcclient.Client
    64  
    65  	*baseRPCClient
    66  	*WSEvents
    67  }
    68  
    69  // BatchHTTP provides the same interface as `HTTP`, but allows for batching of
    70  // requests (as per https://www.jsonrpc.org/specification#batch). Do not
    71  // instantiate directly - rather use the HTTP.NewBatch() method to create an
    72  // instance of this struct.
    73  //
    74  // Batching of HTTP requests is thread-safe in the sense that multiple
    75  // goroutines can each create their own batches and send them using the same
    76  // HTTP client. Multiple goroutines could also enqueue transactions in a single
    77  // batch, but ordering of transactions in the batch cannot be guaranteed in such
    78  // an example.
    79  type BatchHTTP struct {
    80  	rpcBatch *jsonrpcclient.RequestBatch
    81  	*baseRPCClient
    82  }
    83  
    84  // rpcClient is an internal interface to which our RPC clients (batch and
    85  // non-batch) must conform. Acts as an additional code-level sanity check to
    86  // make sure the implementations stay coherent.
    87  type rpcClient interface {
    88  	rpcclient.ABCIClient
    89  	rpcclient.HistoryClient
    90  	rpcclient.NetworkClient
    91  	rpcclient.SignClient
    92  	rpcclient.StatusClient
    93  }
    94  
    95  // baseRPCClient implements the basic RPC method logic without the actual
    96  // underlying RPC call functionality, which is provided by `caller`.
    97  type baseRPCClient struct {
    98  	caller jsonrpcclient.Caller
    99  }
   100  
   101  var _ rpcClient = (*HTTP)(nil)
   102  var _ rpcClient = (*BatchHTTP)(nil)
   103  var _ rpcClient = (*baseRPCClient)(nil)
   104  
   105  //-----------------------------------------------------------------------------
   106  // HTTP
   107  
   108  // New takes a remote endpoint in the form <protocol>://<host>:<port> and
   109  // the websocket path (which always seems to be "/websocket")
   110  // An error is returned on invalid remote. The function panics when remote is nil.
   111  func New(remote, wsEndpoint string) (*HTTP, error) {
   112  	httpClient, err := jsonrpcclient.DefaultHTTPClient(remote)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	return NewWithClient(remote, wsEndpoint, httpClient)
   117  }
   118  
   119  // NewWithTimeout does the same thing as New, except you can set a Timeout for
   120  // http.Client. A Timeout of zero means no timeout.
   121  func NewWithTimeout(remote, wsEndpoint string, timeout uint) (*HTTP, error) {
   122  	httpClient, err := jsonrpcclient.DefaultHTTPClient(remote)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  	httpClient.Timeout = time.Duration(timeout) * time.Second
   127  	return NewWithClient(remote, wsEndpoint, httpClient)
   128  }
   129  
   130  // NewWithClient allows for setting a custom http client (See New).
   131  // An error is returned on invalid remote. The function panics when remote is nil.
   132  func NewWithClient(remote, wsEndpoint string, client *http.Client) (*HTTP, error) {
   133  	if client == nil {
   134  		panic("nil http.Client provided")
   135  	}
   136  
   137  	rc, err := jsonrpcclient.NewWithHTTPClient(remote, client)
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  
   142  	wsEvents, err := newWSEvents(remote, wsEndpoint)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	httpClient := &HTTP{
   148  		rpc:           rc,
   149  		remote:        remote,
   150  		baseRPCClient: &baseRPCClient{caller: rc},
   151  		WSEvents:      wsEvents,
   152  	}
   153  
   154  	return httpClient, nil
   155  }
   156  
   157  var _ rpcclient.Client = (*HTTP)(nil)
   158  
   159  // SetLogger sets a logger.
   160  func (c *HTTP) SetLogger(l log.Logger) {
   161  	c.WSEvents.SetLogger(l)
   162  }
   163  
   164  // Remote returns the remote network address in a string form.
   165  func (c *HTTP) Remote() string {
   166  	return c.remote
   167  }
   168  
   169  // NewBatch creates a new batch client for this HTTP client.
   170  func (c *HTTP) NewBatch() *BatchHTTP {
   171  	rpcBatch := c.rpc.NewRequestBatch()
   172  	return &BatchHTTP{
   173  		rpcBatch: rpcBatch,
   174  		baseRPCClient: &baseRPCClient{
   175  			caller: rpcBatch,
   176  		},
   177  	}
   178  }
   179  
   180  //-----------------------------------------------------------------------------
   181  // BatchHTTP
   182  
   183  // Send is a convenience function for an HTTP batch that will trigger the
   184  // compilation of the batched requests and send them off using the client as a
   185  // single request. On success, this returns a list of the deserialized results
   186  // from each request in the sent batch.
   187  func (b *BatchHTTP) Send(ctx context.Context) ([]interface{}, error) {
   188  	return b.rpcBatch.Send(ctx)
   189  }
   190  
   191  // Clear will empty out this batch of requests and return the number of requests
   192  // that were cleared out.
   193  func (b *BatchHTTP) Clear() int {
   194  	return b.rpcBatch.Clear()
   195  }
   196  
   197  // Count returns the number of enqueued requests waiting to be sent.
   198  func (b *BatchHTTP) Count() int {
   199  	return b.rpcBatch.Count()
   200  }
   201  
   202  //-----------------------------------------------------------------------------
   203  // baseRPCClient
   204  
   205  func (c *baseRPCClient) Status(ctx context.Context) (*ctypes.ResultStatus, error) {
   206  	result := new(ctypes.ResultStatus)
   207  	_, err := c.caller.Call(ctx, "status", map[string]interface{}{}, result)
   208  	if err != nil {
   209  		return nil, err
   210  	}
   211  
   212  	return result, nil
   213  }
   214  
   215  func (c *baseRPCClient) ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) {
   216  	result := new(ctypes.ResultABCIInfo)
   217  	_, err := c.caller.Call(ctx, "abci_info", map[string]interface{}{}, result)
   218  	if err != nil {
   219  		return nil, err
   220  	}
   221  
   222  	return result, nil
   223  }
   224  
   225  func (c *baseRPCClient) ABCIQuery(
   226  	ctx context.Context,
   227  	path string,
   228  	data bytes.HexBytes,
   229  ) (*ctypes.ResultABCIQuery, error) {
   230  	return c.ABCIQueryWithOptions(ctx, path, data, rpcclient.DefaultABCIQueryOptions)
   231  }
   232  
   233  func (c *baseRPCClient) ABCIQueryWithOptions(
   234  	ctx context.Context,
   235  	path string,
   236  	data bytes.HexBytes,
   237  	opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
   238  	result := new(ctypes.ResultABCIQuery)
   239  	_, err := c.caller.Call(ctx, "abci_query",
   240  		map[string]interface{}{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove},
   241  		result)
   242  	if err != nil {
   243  		return nil, err
   244  	}
   245  
   246  	return result, nil
   247  }
   248  
   249  func (c *baseRPCClient) BroadcastTxCommit(
   250  	ctx context.Context,
   251  	tx types.Tx,
   252  ) (*ctypes.ResultBroadcastTxCommit, error) {
   253  	result := new(ctypes.ResultBroadcastTxCommit)
   254  	_, err := c.caller.Call(ctx, "broadcast_tx_commit", map[string]interface{}{"tx": tx}, result)
   255  	if err != nil {
   256  		return nil, err
   257  	}
   258  	return result, nil
   259  }
   260  
   261  func (c *baseRPCClient) BroadcastTxAsync(
   262  	ctx context.Context,
   263  	tx types.Tx,
   264  ) (*ctypes.ResultBroadcastTx, error) {
   265  	return c.broadcastTX(ctx, "broadcast_tx_async", tx)
   266  }
   267  
   268  func (c *baseRPCClient) BroadcastTxSync(
   269  	ctx context.Context,
   270  	tx types.Tx,
   271  ) (*ctypes.ResultBroadcastTx, error) {
   272  	return c.broadcastTX(ctx, "broadcast_tx_sync", tx)
   273  }
   274  
   275  func (c *baseRPCClient) broadcastTX(
   276  	ctx context.Context,
   277  	route string,
   278  	tx types.Tx,
   279  ) (*ctypes.ResultBroadcastTx, error) {
   280  	result := new(ctypes.ResultBroadcastTx)
   281  	_, err := c.caller.Call(ctx, route, map[string]interface{}{"tx": tx}, result)
   282  	if err != nil {
   283  		return nil, err
   284  	}
   285  	return result, nil
   286  }
   287  
   288  func (c *baseRPCClient) UnconfirmedTxs(
   289  	ctx context.Context,
   290  	limit *int,
   291  ) (*ctypes.ResultUnconfirmedTxs, error) {
   292  	result := new(ctypes.ResultUnconfirmedTxs)
   293  	params := make(map[string]interface{})
   294  	if limit != nil {
   295  		params["limit"] = limit
   296  	}
   297  	_, err := c.caller.Call(ctx, "unconfirmed_txs", params, result)
   298  	if err != nil {
   299  		return nil, err
   300  	}
   301  	return result, nil
   302  }
   303  
   304  func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUnconfirmedTxs, error) {
   305  	result := new(ctypes.ResultUnconfirmedTxs)
   306  	_, err := c.caller.Call(ctx, "num_unconfirmed_txs", map[string]interface{}{}, result)
   307  	if err != nil {
   308  		return nil, err
   309  	}
   310  	return result, nil
   311  }
   312  
   313  func (c *baseRPCClient) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) {
   314  	result := new(ctypes.ResultCheckTx)
   315  	_, err := c.caller.Call(ctx, "check_tx", map[string]interface{}{"tx": tx}, result)
   316  	if err != nil {
   317  		return nil, err
   318  	}
   319  	return result, nil
   320  }
   321  
   322  func (c *baseRPCClient) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) {
   323  	result := new(ctypes.ResultNetInfo)
   324  	_, err := c.caller.Call(ctx, "net_info", map[string]interface{}{}, result)
   325  	if err != nil {
   326  		return nil, err
   327  	}
   328  	return result, nil
   329  }
   330  
   331  func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) {
   332  	result := new(ctypes.ResultDumpConsensusState)
   333  	_, err := c.caller.Call(ctx, "dump_consensus_state", map[string]interface{}{}, result)
   334  	if err != nil {
   335  		return nil, err
   336  	}
   337  	return result, nil
   338  }
   339  
   340  func (c *baseRPCClient) ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) {
   341  	result := new(ctypes.ResultConsensusState)
   342  	_, err := c.caller.Call(ctx, "consensus_state", map[string]interface{}{}, result)
   343  	if err != nil {
   344  		return nil, err
   345  	}
   346  	return result, nil
   347  }
   348  
   349  func (c *baseRPCClient) ConsensusParams(
   350  	ctx context.Context,
   351  	height *int64,
   352  ) (*ctypes.ResultConsensusParams, error) {
   353  	result := new(ctypes.ResultConsensusParams)
   354  	params := make(map[string]interface{})
   355  	if height != nil {
   356  		params["height"] = height
   357  	}
   358  	_, err := c.caller.Call(ctx, "consensus_params", params, result)
   359  	if err != nil {
   360  		return nil, err
   361  	}
   362  	return result, nil
   363  }
   364  
   365  func (c *baseRPCClient) Health(ctx context.Context) (*ctypes.ResultHealth, error) {
   366  	result := new(ctypes.ResultHealth)
   367  	_, err := c.caller.Call(ctx, "health", map[string]interface{}{}, result)
   368  	if err != nil {
   369  		return nil, err
   370  	}
   371  	return result, nil
   372  }
   373  
   374  func (c *baseRPCClient) BlockchainInfo(
   375  	ctx context.Context,
   376  	minHeight,
   377  	maxHeight int64,
   378  ) (*ctypes.ResultBlockchainInfo, error) {
   379  	result := new(ctypes.ResultBlockchainInfo)
   380  	_, err := c.caller.Call(ctx, "blockchain",
   381  		map[string]interface{}{"minHeight": minHeight, "maxHeight": maxHeight},
   382  		result)
   383  	if err != nil {
   384  		return nil, err
   385  	}
   386  	return result, nil
   387  }
   388  
   389  func (c *baseRPCClient) Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) {
   390  	result := new(ctypes.ResultGenesis)
   391  	_, err := c.caller.Call(ctx, "genesis", map[string]interface{}{}, result)
   392  	if err != nil {
   393  		return nil, err
   394  	}
   395  	return result, nil
   396  }
   397  
   398  func (c *baseRPCClient) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) {
   399  	result := new(ctypes.ResultBlock)
   400  	params := make(map[string]interface{})
   401  	if height != nil {
   402  		params["height"] = height
   403  	}
   404  	_, err := c.caller.Call(ctx, "block", params, result)
   405  	if err != nil {
   406  		return nil, err
   407  	}
   408  	return result, nil
   409  }
   410  
   411  func (c *baseRPCClient) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBlock, error) {
   412  	result := new(ctypes.ResultBlock)
   413  	params := map[string]interface{}{
   414  		"hash": hash,
   415  	}
   416  	_, err := c.caller.Call(ctx, "block_by_hash", params, result)
   417  	if err != nil {
   418  		return nil, err
   419  	}
   420  	return result, nil
   421  }
   422  
   423  func (c *baseRPCClient) BlockResults(
   424  	ctx context.Context,
   425  	height *int64,
   426  ) (*ctypes.ResultBlockResults, error) {
   427  	result := new(ctypes.ResultBlockResults)
   428  	params := make(map[string]interface{})
   429  	if height != nil {
   430  		params["height"] = height
   431  	}
   432  	_, err := c.caller.Call(ctx, "block_results", params, result)
   433  	if err != nil {
   434  		return nil, err
   435  	}
   436  	return result, nil
   437  }
   438  
   439  func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) {
   440  	result := new(ctypes.ResultCommit)
   441  	params := make(map[string]interface{})
   442  	if height != nil {
   443  		params["height"] = height
   444  	}
   445  	_, err := c.caller.Call(ctx, "commit", params, result)
   446  	if err != nil {
   447  		return nil, err
   448  	}
   449  	return result, nil
   450  }
   451  
   452  func (c *baseRPCClient) DataAvailabilityHeader(
   453  	ctx context.Context,
   454  	height *int64,
   455  ) (*ctypes.ResultDataAvailabilityHeader, error) {
   456  	result := new(ctypes.ResultDataAvailabilityHeader)
   457  	params := make(map[string]interface{})
   458  	if height != nil {
   459  		params["height"] = height
   460  	}
   461  	_, err := c.caller.Call(ctx, "data_availability_header", params, result)
   462  	if err != nil {
   463  		return nil, err
   464  	}
   465  	return result, nil
   466  }
   467  
   468  func (c *baseRPCClient) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
   469  	result := new(ctypes.ResultTx)
   470  	params := map[string]interface{}{
   471  		"hash":  hash,
   472  		"prove": prove,
   473  	}
   474  	_, err := c.caller.Call(ctx, "tx", params, result)
   475  	if err != nil {
   476  		return nil, err
   477  	}
   478  	return result, nil
   479  }
   480  
   481  func (c *baseRPCClient) TxSearch(
   482  	ctx context.Context,
   483  	query string,
   484  	prove bool,
   485  	page,
   486  	perPage *int,
   487  	orderBy string,
   488  ) (
   489  	*ctypes.ResultTxSearch, error) {
   490  	result := new(ctypes.ResultTxSearch)
   491  	params := map[string]interface{}{
   492  		"query":    query,
   493  		"prove":    prove,
   494  		"order_by": orderBy,
   495  	}
   496  	if page != nil {
   497  		params["page"] = page
   498  	}
   499  	if perPage != nil {
   500  		params["per_page"] = perPage
   501  	}
   502  	_, err := c.caller.Call(ctx, "tx_search", params, result)
   503  	if err != nil {
   504  		return nil, err
   505  	}
   506  	return result, nil
   507  }
   508  
   509  func (c *baseRPCClient) Validators(
   510  	ctx context.Context,
   511  	height *int64,
   512  	page,
   513  	perPage *int,
   514  ) (*ctypes.ResultValidators, error) {
   515  	result := new(ctypes.ResultValidators)
   516  	params := make(map[string]interface{})
   517  	if page != nil {
   518  		params["page"] = page
   519  	}
   520  	if perPage != nil {
   521  		params["per_page"] = perPage
   522  	}
   523  	if height != nil {
   524  		params["height"] = height
   525  	}
   526  	_, err := c.caller.Call(ctx, "validators", params, result)
   527  	if err != nil {
   528  		return nil, err
   529  	}
   530  	return result, nil
   531  }
   532  
   533  func (c *baseRPCClient) BroadcastEvidence(
   534  	ctx context.Context,
   535  	ev types.Evidence,
   536  ) (*ctypes.ResultBroadcastEvidence, error) {
   537  	result := new(ctypes.ResultBroadcastEvidence)
   538  	_, err := c.caller.Call(ctx, "broadcast_evidence", map[string]interface{}{"evidence": ev}, result)
   539  	if err != nil {
   540  		return nil, err
   541  	}
   542  	return result, nil
   543  }
   544  
   545  //-----------------------------------------------------------------------------
   546  // WSEvents
   547  
   548  var errNotRunning = errors.New("client is not running. Use .Start() method to start")
   549  
   550  // WSEvents is a wrapper around WSClient, which implements EventsClient.
   551  type WSEvents struct {
   552  	service.BaseService
   553  	remote   string
   554  	endpoint string
   555  	ws       *jsonrpcclient.WSClient
   556  
   557  	mtx           tmsync.RWMutex
   558  	subscriptions map[string]chan ctypes.ResultEvent // query -> chan
   559  }
   560  
   561  func newWSEvents(remote, endpoint string) (*WSEvents, error) {
   562  	w := &WSEvents{
   563  		endpoint:      endpoint,
   564  		remote:        remote,
   565  		subscriptions: make(map[string]chan ctypes.ResultEvent),
   566  	}
   567  	w.BaseService = *service.NewBaseService(nil, "WSEvents", w)
   568  
   569  	var err error
   570  	w.ws, err = jsonrpcclient.NewWS(w.remote, w.endpoint, jsonrpcclient.OnReconnect(func() {
   571  		// resubscribe immediately
   572  		w.redoSubscriptionsAfter(0 * time.Second)
   573  	}))
   574  	if err != nil {
   575  		return nil, err
   576  	}
   577  	w.ws.SetLogger(w.Logger)
   578  
   579  	return w, nil
   580  }
   581  
   582  // OnStart implements service.Service by starting WSClient and event loop.
   583  func (w *WSEvents) OnStart() error {
   584  	if err := w.ws.Start(); err != nil {
   585  		return err
   586  	}
   587  
   588  	go w.eventListener()
   589  
   590  	return nil
   591  }
   592  
   593  // OnStop implements service.Service by stopping WSClient.
   594  func (w *WSEvents) OnStop() {
   595  	if err := w.ws.Stop(); err != nil {
   596  		w.Logger.Error("Can't stop ws client", "err", err)
   597  	}
   598  }
   599  
   600  // Subscribe implements EventsClient by using WSClient to subscribe given
   601  // subscriber to query. By default, returns a channel with cap=1. Error is
   602  // returned if it fails to subscribe.
   603  //
   604  // Channel is never closed to prevent clients from seeing an erroneous event.
   605  //
   606  // It returns an error if WSEvents is not running.
   607  func (w *WSEvents) Subscribe(ctx context.Context, subscriber, query string,
   608  	outCapacity ...int) (out <-chan ctypes.ResultEvent, err error) {
   609  
   610  	if !w.IsRunning() {
   611  		return nil, errNotRunning
   612  	}
   613  
   614  	if err := w.ws.Subscribe(ctx, query); err != nil {
   615  		return nil, err
   616  	}
   617  
   618  	outCap := 1
   619  	if len(outCapacity) > 0 {
   620  		outCap = outCapacity[0]
   621  	}
   622  
   623  	outc := make(chan ctypes.ResultEvent, outCap)
   624  	w.mtx.Lock()
   625  	// subscriber param is ignored because Tendermint will override it with
   626  	// remote IP anyway.
   627  	w.subscriptions[query] = outc
   628  	w.mtx.Unlock()
   629  
   630  	return outc, nil
   631  }
   632  
   633  // Unsubscribe implements EventsClient by using WSClient to unsubscribe given
   634  // subscriber from query.
   635  //
   636  // It returns an error if WSEvents is not running.
   637  func (w *WSEvents) Unsubscribe(ctx context.Context, subscriber, query string) error {
   638  	if !w.IsRunning() {
   639  		return errNotRunning
   640  	}
   641  
   642  	if err := w.ws.Unsubscribe(ctx, query); err != nil {
   643  		return err
   644  	}
   645  
   646  	w.mtx.Lock()
   647  	_, ok := w.subscriptions[query]
   648  	if ok {
   649  		delete(w.subscriptions, query)
   650  	}
   651  	w.mtx.Unlock()
   652  
   653  	return nil
   654  }
   655  
   656  // UnsubscribeAll implements EventsClient by using WSClient to unsubscribe
   657  // given subscriber from all the queries.
   658  //
   659  // It returns an error if WSEvents is not running.
   660  func (w *WSEvents) UnsubscribeAll(ctx context.Context, subscriber string) error {
   661  	if !w.IsRunning() {
   662  		return errNotRunning
   663  	}
   664  
   665  	if err := w.ws.UnsubscribeAll(ctx); err != nil {
   666  		return err
   667  	}
   668  
   669  	w.mtx.Lock()
   670  	w.subscriptions = make(map[string]chan ctypes.ResultEvent)
   671  	w.mtx.Unlock()
   672  
   673  	return nil
   674  }
   675  
   676  // After being reconnected, it is necessary to redo subscription to server
   677  // otherwise no data will be automatically received.
   678  func (w *WSEvents) redoSubscriptionsAfter(d time.Duration) {
   679  	time.Sleep(d)
   680  
   681  	w.mtx.RLock()
   682  	defer w.mtx.RUnlock()
   683  	for q := range w.subscriptions {
   684  		err := w.ws.Subscribe(context.Background(), q)
   685  		if err != nil {
   686  			w.Logger.Error("Failed to resubscribe", "err", err)
   687  		}
   688  	}
   689  }
   690  
   691  func isErrAlreadySubscribed(err error) bool {
   692  	return strings.Contains(err.Error(), tmpubsub.ErrAlreadySubscribed.Error())
   693  }
   694  
   695  func (w *WSEvents) eventListener() {
   696  	for {
   697  		select {
   698  		case resp, ok := <-w.ws.ResponsesCh:
   699  			if !ok {
   700  				return
   701  			}
   702  
   703  			if resp.Error != nil {
   704  				w.Logger.Error("WS error", "err", resp.Error.Error())
   705  				// Error can be ErrAlreadySubscribed or max client (subscriptions per
   706  				// client) reached or Tendermint exited.
   707  				// We can ignore ErrAlreadySubscribed, but need to retry in other
   708  				// cases.
   709  				if !isErrAlreadySubscribed(resp.Error) {
   710  					// Resubscribe after 1 second to give Tendermint time to restart (if
   711  					// crashed).
   712  					w.redoSubscriptionsAfter(1 * time.Second)
   713  				}
   714  				continue
   715  			}
   716  
   717  			result := new(ctypes.ResultEvent)
   718  			err := tmjson.Unmarshal(resp.Result, result)
   719  			if err != nil {
   720  				w.Logger.Error("failed to unmarshal response", "err", err)
   721  				continue
   722  			}
   723  
   724  			w.mtx.RLock()
   725  			if out, ok := w.subscriptions[result.Query]; ok {
   726  				if cap(out) == 0 {
   727  					out <- *result
   728  				} else {
   729  					select {
   730  					case out <- *result:
   731  					default:
   732  						w.Logger.Error("wanted to publish ResultEvent, but out channel is full", "result", result, "query", result.Query)
   733  					}
   734  				}
   735  			}
   736  			w.mtx.RUnlock()
   737  		case <-w.Quit():
   738  			return
   739  		}
   740  	}
   741  }