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 }