Skip to content

Commit

Permalink
chore: decouple HTTP client and Tendermint API client
Browse files Browse the repository at this point in the history
  • Loading branch information
freak12techno committed Feb 25, 2024
1 parent 64cafa1 commit ab9361b
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 76 deletions.
92 changes: 92 additions & 0 deletions pkg/http/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package http

import (
"encoding/json"
"fmt"
"main/pkg/types/query_info"
"net/http"
"time"

"github.com/rs/zerolog"
)

type Client struct {
logger zerolog.Logger
host string
timeout time.Duration
}

func NewClient(
logger *zerolog.Logger,
host string,
chainName string,
) *Client {
return &Client{
logger: logger.With().
Str("component", "tendermint_api_client").
Str("url", host).
Str("chain", chainName).
Logger(),
host: host,
timeout: 60 * time.Second,
}
}

func (c *Client) Get(url string, target interface{}) (error, query_info.QueryInfo) {
return c.GetWithHeaders(url, target, map[string]string{})
}

func (c *Client) GetWithHeaders(
relativeURL string,
target interface{},
headers map[string]string,
) (error, query_info.QueryInfo) {
url := fmt.Sprintf("%s%s", c.host, relativeURL)

client := &http.Client{Timeout: c.timeout}
start := time.Now()
queryInfo := query_info.QueryInfo{
Success: false,
Node: c.host,
Time: 0,
}

req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return err, queryInfo
}

req.Header.Set("User-Agent", "cosmos-transactions-bot")

for key, value := range headers {
req.Header.Set(key, value)
}

c.logger.Trace().Str("url", url).Msg("Doing a query...")

res, err := client.Do(req)
queryInfo.Time = time.Since(start)
if err != nil {
c.logger.Warn().Str("url", url).Err(err).Msg("Query failed")
return err, queryInfo
}
defer res.Body.Close()

if res.StatusCode >= http.StatusBadRequest {
c.logger.Warn().
Str("url", url).
Err(err).
Int("status", res.StatusCode).
Msg("Query returned bad HTTP code")
return fmt.Errorf("bad HTTP code: %d", res.StatusCode), queryInfo
}

c.logger.Debug().Str("url", url).Dur("duration", time.Since(start)).Msg("Query is finished")

if err := json.NewDecoder(res.Body).Decode(target); err != nil {
return err, queryInfo
}

queryInfo.Success = true
return nil, queryInfo
}
88 changes: 12 additions & 76 deletions pkg/tendermint/api/api_client.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package api

import (
"encoding/json"
"fmt"
"main/pkg/http"
"main/pkg/types/query_info"
"net/http"
"strconv"
"time"

"github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"

Expand All @@ -17,28 +15,25 @@ import (
)

type TendermintApiClient struct {
Logger zerolog.Logger
URL string
Timeout time.Duration
Logger zerolog.Logger
Client *http.Client
}

func NewTendermintApiClient(logger *zerolog.Logger, url string, chain *configTypes.Chain) *TendermintApiClient {
return &TendermintApiClient{
Logger: logger.With().
Str("component", "tendermint_api_client").
Str("url", url).
Str("chain", chain.Name).
Logger(),
URL: url,
Timeout: 60 * time.Second,
Client: http.NewClient(logger, url, chain.Name),
}
}

func (c *TendermintApiClient) GetValidator(address string) (*responses.Validator, error, query_info.QueryInfo) {
url := fmt.Sprintf("/cosmos/staking/v1beta1/validators/%s", address)

var response *responses.ValidatorResponse
err, queryInfo := c.Get(url, &response)
err, queryInfo := c.Client.Get(url, &response)
if err != nil {
return nil, err, queryInfo
}
Expand All @@ -62,7 +57,7 @@ func (c *TendermintApiClient) GetDelegatorsRewardsAtBlock(
}

var response *responses.RewardsResponse
err, queryInfo := c.GetWithHeaders(url, &response, headers)
err, queryInfo := c.Client.GetWithHeaders(url, &response, headers)
if err != nil || response == nil {
return nil, err, queryInfo
}
Expand All @@ -84,7 +79,7 @@ func (c *TendermintApiClient) GetValidatorCommissionAtBlock(
}

var response *responses.CommissionResponse
err, queryInfo := c.GetWithHeaders(url, &response, headers)
err, queryInfo := c.Client.GetWithHeaders(url, &response, headers)
if err != nil || response == nil {
return nil, err, queryInfo
}
Expand All @@ -96,7 +91,7 @@ func (c *TendermintApiClient) GetProposal(id string) (*responses.Proposal, error
url := fmt.Sprintf("/cosmos/gov/v1beta1/proposals/%s", id)

var response *responses.ProposalResponse
err, queryInfo := c.Get(url, &response)
err, queryInfo := c.Client.Get(url, &response)
if err != nil {
return nil, err, queryInfo
}
Expand All @@ -108,7 +103,7 @@ func (c *TendermintApiClient) GetStakingParams() (*responses.StakingParams, erro
url := fmt.Sprintf("/cosmos/staking/v1beta1/params")

var response *responses.StakingParamsResponse
err, queryInfo := c.Get(url, &response)
err, queryInfo := c.Client.Get(url, &response)
if err != nil {
return nil, err, queryInfo
}
Expand All @@ -123,7 +118,7 @@ func (c *TendermintApiClient) GetIbcChannel(
url := fmt.Sprintf("/ibc/core/channel/v1/channels/%s/ports/%s", channel, port)

var response *responses.IbcChannelResponse
err, queryInfo := c.Get(url, &response)
err, queryInfo := c.Client.Get(url, &response)
if err != nil {
return nil, err, queryInfo
}
Expand All @@ -137,7 +132,7 @@ func (c *TendermintApiClient) GetIbcConnectionClientState(
url := fmt.Sprintf("/ibc/core/connection/v1/connections/%s/client_state", connectionID)

var response *responses.IbcClientStateResponse
err, queryInfo := c.Get(url, &response)
err, queryInfo := c.Client.Get(url, &response)
if err != nil {
return nil, err, queryInfo
}
Expand All @@ -151,69 +146,10 @@ func (c *TendermintApiClient) GetIbcDenomTrace(
url := fmt.Sprintf("/ibc/apps/transfer/v1/denom_traces/%s", hash)

var response *responses.IbcDenomTraceResponse
err, queryInfo := c.Get(url, &response)
err, queryInfo := c.Client.Get(url, &response)
if err != nil {
return nil, err, queryInfo
}

return &response.DenomTrace, nil, queryInfo
}

func (c *TendermintApiClient) Get(url string, target interface{}) (error, query_info.QueryInfo) {
return c.GetWithHeaders(url, target, map[string]string{})
}

func (c *TendermintApiClient) GetWithHeaders(
relativeURL string,
target interface{},
headers map[string]string,
) (error, query_info.QueryInfo) {
url := fmt.Sprintf("%s%s", c.URL, relativeURL)

client := &http.Client{Timeout: c.Timeout}
start := time.Now()
queryInfo := query_info.QueryInfo{
Success: false,
Node: c.URL,
Time: 0,
}

req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return err, queryInfo
}

req.Header.Set("User-Agent", "cosmos-transactions-bot")

for key, value := range headers {
req.Header.Set(key, value)
}

c.Logger.Trace().Str("url", url).Msg("Doing a query...")

res, err := client.Do(req)
queryInfo.Time = time.Since(start)
if err != nil {
c.Logger.Warn().Str("url", url).Err(err).Msg("Query failed")
return err, queryInfo
}
defer res.Body.Close()

if res.StatusCode >= http.StatusBadRequest {
c.Logger.Warn().
Str("url", url).
Err(err).
Int("status", res.StatusCode).
Msg("Query returned bad HTTP code")
return fmt.Errorf("bad HTTP code: %d", res.StatusCode), queryInfo
}

c.Logger.Debug().Str("url", url).Dur("duration", time.Since(start)).Msg("Query is finished")

if err := json.NewDecoder(res.Body).Decode(target); err != nil {
return err, queryInfo
}

queryInfo.Success = true
return nil, queryInfo
}

0 comments on commit ab9361b

Please sign in to comment.