github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/market/mysterium/mysterium_api.go (about)

     1  /*
     2   * Copyright (C) 2017 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package mysterium
    19  
    20  import (
    21  	"github.com/pkg/errors"
    22  	"github.com/rs/zerolog/log"
    23  
    24  	"github.com/mysteriumnetwork/node/market"
    25  	"github.com/mysteriumnetwork/node/requests"
    26  )
    27  
    28  // MysteriumAPI provides access to Mysterium owned central discovery service.
    29  type MysteriumAPI struct {
    30  	httpClient          *requests.HTTPClient
    31  	discoveryAPIAddress string
    32  }
    33  
    34  // NewClient creates a Discovery client.
    35  func NewClient(httpClient *requests.HTTPClient, discoveryAPIAddress string) *MysteriumAPI {
    36  	return &MysteriumAPI{
    37  		httpClient:          httpClient,
    38  		discoveryAPIAddress: discoveryAPIAddress,
    39  	}
    40  }
    41  
    42  // QueryProposals returns active service proposals.
    43  func (mApi *MysteriumAPI) QueryProposals(query ProposalsQuery) ([]market.ServiceProposal, error) {
    44  	req, err := requests.NewGetRequest(mApi.discoveryAPIAddress, "proposals", query.ToURLValues())
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	res, err := mApi.httpClient.Do(req)
    50  	if err != nil {
    51  		return nil, errors.Wrap(err, "cannot fetch proposals")
    52  	}
    53  	defer res.Body.Close()
    54  
    55  	if err := requests.ParseResponseError(res); err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	var proposals []market.ServiceProposal
    60  	if err := requests.ParseResponseJSON(res, &proposals); err != nil {
    61  		return nil, errors.Wrap(err, "cannot parse proposals response")
    62  	}
    63  
    64  	total := len(proposals)
    65  	supported := supportedProposalsOnly(proposals)
    66  	log.Debug().Msgf("Total proposals: %d supported: %d", total, len(supported))
    67  	return supported, nil
    68  }
    69  
    70  // QueryCountries returns active service proposals number per country.
    71  func (mApi *MysteriumAPI) QueryCountries(query ProposalsQuery) (map[string]int, error) {
    72  	req, err := requests.NewGetRequest(mApi.discoveryAPIAddress, "countries", query.ToURLValues())
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	res, err := mApi.httpClient.Do(req)
    78  	if err != nil {
    79  		return nil, errors.Wrap(err, "cannot fetch countries")
    80  	}
    81  	defer res.Body.Close()
    82  
    83  	if err := requests.ParseResponseError(res); err != nil {
    84  		return nil, err
    85  	}
    86  
    87  	countries := make(map[string]int, 0)
    88  	if err := requests.ParseResponseJSON(res, &countries); err != nil {
    89  		return nil, errors.Wrap(err, "cannot parse countries response")
    90  	}
    91  
    92  	return countries, nil
    93  }
    94  
    95  // GetPricing gets the pricing from discovery.
    96  func (mApi *MysteriumAPI) GetPricing() (market.LatestPrices, error) {
    97  	req, err := requests.NewGetRequest(mApi.discoveryAPIAddress, "prices", nil)
    98  	if err != nil {
    99  		return market.LatestPrices{}, err
   100  	}
   101  
   102  	res, err := mApi.httpClient.Do(req)
   103  	if err != nil {
   104  		return market.LatestPrices{}, errors.Wrap(err, "cannot fetch pricing")
   105  	}
   106  	defer res.Body.Close()
   107  
   108  	result := market.LatestPrices{}
   109  	if err := requests.ParseResponseJSON(res, &result); err != nil {
   110  		return market.LatestPrices{}, errors.Wrap(err, "cannot parse pricing response")
   111  	}
   112  	return result, nil
   113  }
   114  
   115  func supportedProposalsOnly(proposals []market.ServiceProposal) (supported []market.ServiceProposal) {
   116  	for _, proposal := range proposals {
   117  		if proposal.Validate() == nil && proposal.IsSupported() {
   118  			supported = append(supported, proposal)
   119  		}
   120  	}
   121  	return
   122  }