github.com/noirx94/tendermintmp@v0.0.1/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/tendermint/tendermint/libs/bytes"
    11  	tmjson "github.com/tendermint/tendermint/libs/json"
    12  	"github.com/tendermint/tendermint/libs/log"
    13  	tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
    14  	"github.com/tendermint/tendermint/libs/service"
    15  	tmsync "github.com/tendermint/tendermint/libs/sync"
    16  	rpcclient "github.com/tendermint/tendermint/rpc/client"
    17  	ctypes "github.com/tendermint/tendermint/rpc/core/types"
    18  	jsonrpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client"
    19  	"github.com/tendermint/tendermint/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  // Create timeout enabled http client
   120  func NewWithTimeout(remote, wsEndpoint string, timeout uint) (*HTTP, error) {
   121  	httpClient, err := jsonrpcclient.DefaultHTTPClient(remote)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  	httpClient.Timeout = time.Duration(timeout) * time.Second
   126  	return NewWithClient(remote, wsEndpoint, httpClient)
   127  }
   128  
   129  // NewWithClient allows for setting a custom http client (See New).
   130  // An error is returned on invalid remote. The function panics when remote is nil.
   131  func NewWithClient(remote, wsEndpoint string, client *http.Client) (*HTTP, error) {
   132  	if client == nil {
   133  		panic("nil http.Client provided")
   134  	}
   135  
   136  	rc, err := jsonrpcclient.NewWithHTTPClient(remote, client)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	wsEvents, err := newWSEvents(remote, wsEndpoint)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  
   146  	httpClient := &HTTP{
   147  		rpc:           rc,
   148  		remote:        remote,
   149  		baseRPCClient: &baseRPCClient{caller: rc},
   150  		WSEvents:      wsEvents,
   151  	}
   152  
   153  	return httpClient, nil
   154  }
   155  
   156  var _ rpcclient.Client = (*HTTP)(nil)
   157  
   158  // SetLogger sets a logger.
   159  func (c *HTTP) SetLogger(l log.Logger) {
   160  	c.WSEvents.SetLogger(l)
   161  }
   162  
   163  // Remote returns the remote network address in a string form.
   164  func (c *HTTP) Remote() string {
   165  	return c.remote
   166  }
   167  
   168  // NewBatch creates a new batch client for this HTTP client.
   169  func (c *HTTP) NewBatch() *BatchHTTP {
   170  	rpcBatch := c.rpc.NewRequestBatch()
   171  	return &BatchHTTP{
   172  		rpcBatch: rpcBatch,
   173  		baseRPCClient: &baseRPCClient{
   174  			caller: rpcBatch,
   175  		},
   176  	}
   177  }
   178  
   179  //-----------------------------------------------------------------------------
   180  // BatchHTTP
   181  
   182  // Send is a convenience function for an HTTP batch that will trigger the
   183  // compilation of the batched requests and send them off using the client as a
   184  // single request. On success, this returns a list of the deserialized results
   185  // from each request in the sent batch.
   186  func (b *BatchHTTP) Send(ctx context.Context) ([]interface{}, error) {
   187  	return b.rpcBatch.Send(ctx)
   188  }
   189  
   190  // Clear will empty out this batch of requests and return the number of requests
   191  // that were cleared out.
   192  func (b *BatchHTTP) Clear() int {
   193  	return b.rpcBatch.Clear()
   194  }
   195  
   196  // Count returns the number of enqueued requests waiting to be sent.
   197  func (b *BatchHTTP) Count() int {
   198  	return b.rpcBatch.Count()
   199  }
   200  
   201  //-----------------------------------------------------------------------------
   202  // baseRPCClient
   203  
   204  func (c *baseRPCClient) Status(ctx context.Context) (*ctypes.ResultStatus, error) {
   205  	result := new(ctypes.ResultStatus)
   206  	_, err := c.caller.Call(ctx, "status", map[string]interface{}{}, result)
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  
   211  	return result, nil
   212  }
   213  
   214  func (c *baseRPCClient) ABCIInfo(ctx context.Context) (*ctypes.ResultABCIInfo, error) {
   215  	result := new(ctypes.ResultABCIInfo)
   216  	_, err := c.caller.Call(ctx, "abci_info", map[string]interface{}{}, result)
   217  	if err != nil {
   218  		return nil, err
   219  	}
   220  
   221  	return result, nil
   222  }
   223  
   224  func (c *baseRPCClient) ABCIQuery(
   225  	ctx context.Context,
   226  	path string,
   227  	data bytes.HexBytes,
   228  ) (*ctypes.ResultABCIQuery, error) {
   229  	return c.ABCIQueryWithOptions(ctx, path, data, rpcclient.DefaultABCIQueryOptions)
   230  }
   231  
   232  func (c *baseRPCClient) ABCIQueryWithOptions(
   233  	ctx context.Context,
   234  	path string,
   235  	data bytes.HexBytes,
   236  	opts rpcclient.ABCIQueryOptions) (*ctypes.ResultABCIQuery, error) {
   237  	result := new(ctypes.ResultABCIQuery)
   238  	_, err := c.caller.Call(ctx, "abci_query",
   239  		map[string]interface{}{"path": path, "data": data, "height": opts.Height, "prove": opts.Prove},
   240  		result)
   241  	if err != nil {
   242  		return nil, err
   243  	}
   244  
   245  	return result, nil
   246  }
   247  
   248  func (c *baseRPCClient) BroadcastTxCommit(
   249  	ctx context.Context,
   250  	tx types.Tx,
   251  ) (*ctypes.ResultBroadcastTxCommit, error) {
   252  	result := new(ctypes.ResultBroadcastTxCommit)
   253  	_, err := c.caller.Call(ctx, "broadcast_tx_commit", map[string]interface{}{"tx": tx}, result)
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	return result, nil
   258  }
   259  
   260  func (c *baseRPCClient) BroadcastTxAsync(
   261  	ctx context.Context,
   262  	tx types.Tx,
   263  ) (*ctypes.ResultBroadcastTx, error) {
   264  	return c.broadcastTX(ctx, "broadcast_tx_async", tx)
   265  }
   266  
   267  func (c *baseRPCClient) BroadcastTxSync(
   268  	ctx context.Context,
   269  	tx types.Tx,
   270  ) (*ctypes.ResultBroadcastTx, error) {
   271  	return c.broadcastTX(ctx, "broadcast_tx_sync", tx)
   272  }
   273  
   274  func (c *baseRPCClient) broadcastTX(
   275  	ctx context.Context,
   276  	route string,
   277  	tx types.Tx,
   278  ) (*ctypes.ResultBroadcastTx, error) {
   279  	result := new(ctypes.ResultBroadcastTx)
   280  	_, err := c.caller.Call(ctx, route, map[string]interface{}{"tx": tx}, result)
   281  	if err != nil {
   282  		return nil, err
   283  	}
   284  	return result, nil
   285  }
   286  
   287  func (c *baseRPCClient) UnconfirmedTxs(
   288  	ctx context.Context,
   289  	limit *int,
   290  ) (*ctypes.ResultUnconfirmedTxs, error) {
   291  	result := new(ctypes.ResultUnconfirmedTxs)
   292  	params := make(map[string]interface{})
   293  	if limit != nil {
   294  		params["limit"] = limit
   295  	}
   296  	_, err := c.caller.Call(ctx, "unconfirmed_txs", params, result)
   297  	if err != nil {
   298  		return nil, err
   299  	}
   300  	return result, nil
   301  }
   302  
   303  func (c *baseRPCClient) NumUnconfirmedTxs(ctx context.Context) (*ctypes.ResultUnconfirmedTxs, error) {
   304  	result := new(ctypes.ResultUnconfirmedTxs)
   305  	_, err := c.caller.Call(ctx, "num_unconfirmed_txs", map[string]interface{}{}, result)
   306  	if err != nil {
   307  		return nil, err
   308  	}
   309  	return result, nil
   310  }
   311  
   312  func (c *baseRPCClient) CheckTx(ctx context.Context, tx types.Tx) (*ctypes.ResultCheckTx, error) {
   313  	result := new(ctypes.ResultCheckTx)
   314  	_, err := c.caller.Call(ctx, "check_tx", map[string]interface{}{"tx": tx}, result)
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  	return result, nil
   319  }
   320  
   321  func (c *baseRPCClient) NetInfo(ctx context.Context) (*ctypes.ResultNetInfo, error) {
   322  	result := new(ctypes.ResultNetInfo)
   323  	_, err := c.caller.Call(ctx, "net_info", map[string]interface{}{}, result)
   324  	if err != nil {
   325  		return nil, err
   326  	}
   327  	return result, nil
   328  }
   329  
   330  func (c *baseRPCClient) DumpConsensusState(ctx context.Context) (*ctypes.ResultDumpConsensusState, error) {
   331  	result := new(ctypes.ResultDumpConsensusState)
   332  	_, err := c.caller.Call(ctx, "dump_consensus_state", map[string]interface{}{}, result)
   333  	if err != nil {
   334  		return nil, err
   335  	}
   336  	return result, nil
   337  }
   338  
   339  func (c *baseRPCClient) ConsensusState(ctx context.Context) (*ctypes.ResultConsensusState, error) {
   340  	result := new(ctypes.ResultConsensusState)
   341  	_, err := c.caller.Call(ctx, "consensus_state", map[string]interface{}{}, result)
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  	return result, nil
   346  }
   347  
   348  func (c *baseRPCClient) ConsensusParams(
   349  	ctx context.Context,
   350  	height *int64,
   351  ) (*ctypes.ResultConsensusParams, error) {
   352  	result := new(ctypes.ResultConsensusParams)
   353  	params := make(map[string]interface{})
   354  	if height != nil {
   355  		params["height"] = height
   356  	}
   357  	_, err := c.caller.Call(ctx, "consensus_params", params, result)
   358  	if err != nil {
   359  		return nil, err
   360  	}
   361  	return result, nil
   362  }
   363  
   364  func (c *baseRPCClient) Health(ctx context.Context) (*ctypes.ResultHealth, error) {
   365  	result := new(ctypes.ResultHealth)
   366  	_, err := c.caller.Call(ctx, "health", map[string]interface{}{}, result)
   367  	if err != nil {
   368  		return nil, err
   369  	}
   370  	return result, nil
   371  }
   372  
   373  func (c *baseRPCClient) BlockchainInfo(
   374  	ctx context.Context,
   375  	minHeight,
   376  	maxHeight int64,
   377  ) (*ctypes.ResultBlockchainInfo, error) {
   378  	result := new(ctypes.ResultBlockchainInfo)
   379  	_, err := c.caller.Call(ctx, "blockchain",
   380  		map[string]interface{}{"minHeight": minHeight, "maxHeight": maxHeight},
   381  		result)
   382  	if err != nil {
   383  		return nil, err
   384  	}
   385  	return result, nil
   386  }
   387  
   388  func (c *baseRPCClient) Genesis(ctx context.Context) (*ctypes.ResultGenesis, error) {
   389  	result := new(ctypes.ResultGenesis)
   390  	_, err := c.caller.Call(ctx, "genesis", map[string]interface{}{}, result)
   391  	if err != nil {
   392  		return nil, err
   393  	}
   394  	return result, nil
   395  }
   396  
   397  func (c *baseRPCClient) GenesisChunked(ctx context.Context, id uint) (*ctypes.ResultGenesisChunk, error) {
   398  	result := new(ctypes.ResultGenesisChunk)
   399  	_, err := c.caller.Call(ctx, "genesis_chunked", map[string]interface{}{"chunk": id}, result)
   400  	if err != nil {
   401  		return nil, err
   402  	}
   403  	return result, nil
   404  }
   405  
   406  func (c *baseRPCClient) Block(ctx context.Context, height *int64) (*ctypes.ResultBlock, error) {
   407  	result := new(ctypes.ResultBlock)
   408  	params := make(map[string]interface{})
   409  	if height != nil {
   410  		params["height"] = height
   411  	}
   412  	_, err := c.caller.Call(ctx, "block", params, result)
   413  	if err != nil {
   414  		return nil, err
   415  	}
   416  	return result, nil
   417  }
   418  
   419  func (c *baseRPCClient) BlockByHash(ctx context.Context, hash []byte) (*ctypes.ResultBlock, error) {
   420  	result := new(ctypes.ResultBlock)
   421  	params := map[string]interface{}{
   422  		"hash": hash,
   423  	}
   424  	_, err := c.caller.Call(ctx, "block_by_hash", params, result)
   425  	if err != nil {
   426  		return nil, err
   427  	}
   428  	return result, nil
   429  }
   430  
   431  func (c *baseRPCClient) BlockResults(
   432  	ctx context.Context,
   433  	height *int64,
   434  ) (*ctypes.ResultBlockResults, error) {
   435  	result := new(ctypes.ResultBlockResults)
   436  	params := make(map[string]interface{})
   437  	if height != nil {
   438  		params["height"] = height
   439  	}
   440  	_, err := c.caller.Call(ctx, "block_results", params, result)
   441  	if err != nil {
   442  		return nil, err
   443  	}
   444  	return result, nil
   445  }
   446  
   447  func (c *baseRPCClient) Commit(ctx context.Context, height *int64) (*ctypes.ResultCommit, error) {
   448  	result := new(ctypes.ResultCommit)
   449  	params := make(map[string]interface{})
   450  	if height != nil {
   451  		params["height"] = height
   452  	}
   453  	_, err := c.caller.Call(ctx, "commit", params, result)
   454  	if err != nil {
   455  		return nil, err
   456  	}
   457  	return result, nil
   458  }
   459  
   460  func (c *baseRPCClient) Tx(ctx context.Context, hash []byte, prove bool) (*ctypes.ResultTx, error) {
   461  	result := new(ctypes.ResultTx)
   462  	params := map[string]interface{}{
   463  		"hash":  hash,
   464  		"prove": prove,
   465  	}
   466  	_, err := c.caller.Call(ctx, "tx", params, result)
   467  	if err != nil {
   468  		return nil, err
   469  	}
   470  	return result, nil
   471  }
   472  
   473  func (c *baseRPCClient) TxSearch(
   474  	ctx context.Context,
   475  	query string,
   476  	prove bool,
   477  	page,
   478  	perPage *int,
   479  	orderBy string,
   480  ) (*ctypes.ResultTxSearch, error) {
   481  
   482  	result := new(ctypes.ResultTxSearch)
   483  	params := map[string]interface{}{
   484  		"query":    query,
   485  		"prove":    prove,
   486  		"order_by": orderBy,
   487  	}
   488  
   489  	if page != nil {
   490  		params["page"] = page
   491  	}
   492  	if perPage != nil {
   493  		params["per_page"] = perPage
   494  	}
   495  
   496  	_, err := c.caller.Call(ctx, "tx_search", params, result)
   497  	if err != nil {
   498  		return nil, err
   499  	}
   500  
   501  	return result, nil
   502  }
   503  
   504  func (c *baseRPCClient) BlockSearch(
   505  	ctx context.Context,
   506  	query string,
   507  	page, perPage *int,
   508  	orderBy string,
   509  ) (*ctypes.ResultBlockSearch, error) {
   510  
   511  	result := new(ctypes.ResultBlockSearch)
   512  	params := map[string]interface{}{
   513  		"query":    query,
   514  		"order_by": orderBy,
   515  	}
   516  
   517  	if page != nil {
   518  		params["page"] = page
   519  	}
   520  	if perPage != nil {
   521  		params["per_page"] = perPage
   522  	}
   523  
   524  	_, err := c.caller.Call(ctx, "block_search", params, result)
   525  	if err != nil {
   526  		return nil, err
   527  	}
   528  
   529  	return result, nil
   530  }
   531  
   532  func (c *baseRPCClient) Validators(
   533  	ctx context.Context,
   534  	height *int64,
   535  	page,
   536  	perPage *int,
   537  ) (*ctypes.ResultValidators, error) {
   538  	result := new(ctypes.ResultValidators)
   539  	params := make(map[string]interface{})
   540  	if page != nil {
   541  		params["page"] = page
   542  	}
   543  	if perPage != nil {
   544  		params["per_page"] = perPage
   545  	}
   546  	if height != nil {
   547  		params["height"] = height
   548  	}
   549  	_, err := c.caller.Call(ctx, "validators", params, result)
   550  	if err != nil {
   551  		return nil, err
   552  	}
   553  	return result, nil
   554  }
   555  
   556  func (c *baseRPCClient) BroadcastEvidence(
   557  	ctx context.Context,
   558  	ev types.Evidence,
   559  ) (*ctypes.ResultBroadcastEvidence, error) {
   560  	result := new(ctypes.ResultBroadcastEvidence)
   561  	_, err := c.caller.Call(ctx, "broadcast_evidence", map[string]interface{}{"evidence": ev}, result)
   562  	if err != nil {
   563  		return nil, err
   564  	}
   565  	return result, nil
   566  }
   567  
   568  //-----------------------------------------------------------------------------
   569  // WSEvents
   570  
   571  var errNotRunning = errors.New("client is not running. Use .Start() method to start")
   572  
   573  // WSEvents is a wrapper around WSClient, which implements EventsClient.
   574  type WSEvents struct {
   575  	service.BaseService
   576  	remote   string
   577  	endpoint string
   578  	ws       *jsonrpcclient.WSClient
   579  
   580  	mtx           tmsync.RWMutex
   581  	subscriptions map[string]chan ctypes.ResultEvent // query -> chan
   582  }
   583  
   584  func newWSEvents(remote, endpoint string) (*WSEvents, error) {
   585  	w := &WSEvents{
   586  		endpoint:      endpoint,
   587  		remote:        remote,
   588  		subscriptions: make(map[string]chan ctypes.ResultEvent),
   589  	}
   590  	w.BaseService = *service.NewBaseService(nil, "WSEvents", w)
   591  
   592  	var err error
   593  	w.ws, err = jsonrpcclient.NewWS(w.remote, w.endpoint, jsonrpcclient.OnReconnect(func() {
   594  		// resubscribe immediately
   595  		w.redoSubscriptionsAfter(0 * time.Second)
   596  	}))
   597  	if err != nil {
   598  		return nil, err
   599  	}
   600  	w.ws.SetLogger(w.Logger)
   601  
   602  	return w, nil
   603  }
   604  
   605  // OnStart implements service.Service by starting WSClient and event loop.
   606  func (w *WSEvents) OnStart() error {
   607  	if err := w.ws.Start(); err != nil {
   608  		return err
   609  	}
   610  
   611  	go w.eventListener()
   612  
   613  	return nil
   614  }
   615  
   616  // OnStop implements service.Service by stopping WSClient.
   617  func (w *WSEvents) OnStop() {
   618  	if err := w.ws.Stop(); err != nil {
   619  		w.Logger.Error("Can't stop ws client", "err", err)
   620  	}
   621  }
   622  
   623  // Subscribe implements EventsClient by using WSClient to subscribe given
   624  // subscriber to query. By default, returns a channel with cap=1. Error is
   625  // returned if it fails to subscribe.
   626  //
   627  // Channel is never closed to prevent clients from seeing an erroneous event.
   628  //
   629  // It returns an error if WSEvents is not running.
   630  func (w *WSEvents) Subscribe(ctx context.Context, subscriber, query string,
   631  	outCapacity ...int) (out <-chan ctypes.ResultEvent, err error) {
   632  
   633  	if !w.IsRunning() {
   634  		return nil, errNotRunning
   635  	}
   636  
   637  	if err := w.ws.Subscribe(ctx, query); err != nil {
   638  		return nil, err
   639  	}
   640  
   641  	outCap := 1
   642  	if len(outCapacity) > 0 {
   643  		outCap = outCapacity[0]
   644  	}
   645  
   646  	outc := make(chan ctypes.ResultEvent, outCap)
   647  	w.mtx.Lock()
   648  	// subscriber param is ignored because Tendermint will override it with
   649  	// remote IP anyway.
   650  	w.subscriptions[query] = outc
   651  	w.mtx.Unlock()
   652  
   653  	return outc, nil
   654  }
   655  
   656  // Unsubscribe implements EventsClient by using WSClient to unsubscribe given
   657  // subscriber from query.
   658  //
   659  // It returns an error if WSEvents is not running.
   660  func (w *WSEvents) Unsubscribe(ctx context.Context, subscriber, query string) error {
   661  	if !w.IsRunning() {
   662  		return errNotRunning
   663  	}
   664  
   665  	if err := w.ws.Unsubscribe(ctx, query); err != nil {
   666  		return err
   667  	}
   668  
   669  	w.mtx.Lock()
   670  	_, ok := w.subscriptions[query]
   671  	if ok {
   672  		delete(w.subscriptions, query)
   673  	}
   674  	w.mtx.Unlock()
   675  
   676  	return nil
   677  }
   678  
   679  // UnsubscribeAll implements EventsClient by using WSClient to unsubscribe
   680  // given subscriber from all the queries.
   681  //
   682  // It returns an error if WSEvents is not running.
   683  func (w *WSEvents) UnsubscribeAll(ctx context.Context, subscriber string) error {
   684  	if !w.IsRunning() {
   685  		return errNotRunning
   686  	}
   687  
   688  	if err := w.ws.UnsubscribeAll(ctx); err != nil {
   689  		return err
   690  	}
   691  
   692  	w.mtx.Lock()
   693  	w.subscriptions = make(map[string]chan ctypes.ResultEvent)
   694  	w.mtx.Unlock()
   695  
   696  	return nil
   697  }
   698  
   699  // After being reconnected, it is necessary to redo subscription to server
   700  // otherwise no data will be automatically received.
   701  func (w *WSEvents) redoSubscriptionsAfter(d time.Duration) {
   702  	time.Sleep(d)
   703  
   704  	w.mtx.RLock()
   705  	defer w.mtx.RUnlock()
   706  	for q := range w.subscriptions {
   707  		err := w.ws.Subscribe(context.Background(), q)
   708  		if err != nil {
   709  			w.Logger.Error("Failed to resubscribe", "err", err)
   710  		}
   711  	}
   712  }
   713  
   714  func isErrAlreadySubscribed(err error) bool {
   715  	return strings.Contains(err.Error(), tmpubsub.ErrAlreadySubscribed.Error())
   716  }
   717  
   718  func (w *WSEvents) eventListener() {
   719  	for {
   720  		select {
   721  		case resp, ok := <-w.ws.ResponsesCh:
   722  			if !ok {
   723  				return
   724  			}
   725  
   726  			if resp.Error != nil {
   727  				w.Logger.Error("WS error", "err", resp.Error.Error())
   728  				// Error can be ErrAlreadySubscribed or max client (subscriptions per
   729  				// client) reached or Tendermint exited.
   730  				// We can ignore ErrAlreadySubscribed, but need to retry in other
   731  				// cases.
   732  				if !isErrAlreadySubscribed(resp.Error) {
   733  					// Resubscribe after 1 second to give Tendermint time to restart (if
   734  					// crashed).
   735  					w.redoSubscriptionsAfter(1 * time.Second)
   736  				}
   737  				continue
   738  			}
   739  
   740  			result := new(ctypes.ResultEvent)
   741  			err := tmjson.Unmarshal(resp.Result, result)
   742  			if err != nil {
   743  				w.Logger.Error("failed to unmarshal response", "err", err)
   744  				continue
   745  			}
   746  
   747  			w.mtx.RLock()
   748  			if out, ok := w.subscriptions[result.Query]; ok {
   749  				if cap(out) == 0 {
   750  					out <- *result
   751  				} else {
   752  					select {
   753  					case out <- *result:
   754  					default:
   755  						w.Logger.Error("wanted to publish ResultEvent, but out channel is full", "result", result, "query", result.Query)
   756  					}
   757  				}
   758  			}
   759  			w.mtx.RUnlock()
   760  		case <-w.Quit():
   761  			return
   762  		}
   763  	}
   764  }