github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/discovery/priced_repository.go (about)

     1  /*
     2   * Copyright (C) 2021 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 discovery
    19  
    20  import (
    21  	"github.com/rs/zerolog/log"
    22  
    23  	"github.com/mysteriumnetwork/node/core/discovery/proposal"
    24  	"github.com/mysteriumnetwork/node/market"
    25  )
    26  
    27  // PricedServiceProposalRepository enriches proposals with price data as pricing data is not available on raw proposals.
    28  type PricedServiceProposalRepository struct {
    29  	baseRepo      proposal.Repository
    30  	pip           PriceInfoProvider
    31  	filterPresets proposal.FilterPresetRepository
    32  }
    33  
    34  // PriceInfoProvider allows to fetch the current pricing for services.
    35  type PriceInfoProvider interface {
    36  	GetCurrentPrice(nodeType string, country string, serviceType string) (market.Price, error)
    37  }
    38  
    39  // NewPricedServiceProposalRepository returns a new instance of PricedServiceProposalRepository.
    40  func NewPricedServiceProposalRepository(baseRepo proposal.Repository, pip PriceInfoProvider, filterPresets proposal.FilterPresetRepository) *PricedServiceProposalRepository {
    41  	return &PricedServiceProposalRepository{
    42  		baseRepo:      baseRepo,
    43  		pip:           pip,
    44  		filterPresets: filterPresets,
    45  	}
    46  }
    47  
    48  // Proposal fetches the proposal from base repository and enriches it with pricing data.
    49  func (pspr *PricedServiceProposalRepository) Proposal(id market.ProposalID) (*proposal.PricedServiceProposal, error) {
    50  	prop, err := pspr.baseRepo.Proposal(id)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	// base repo can sometimes return nil proposals.
    56  	if prop == nil {
    57  		return nil, nil
    58  	}
    59  
    60  	priced, err := pspr.toPricedProposal(*prop)
    61  	return &priced, err
    62  }
    63  
    64  // Proposals fetches proposals from base repository and enriches them with pricing data.
    65  func (pspr *PricedServiceProposalRepository) Proposals(filter *proposal.Filter) ([]proposal.PricedServiceProposal, error) {
    66  	proposals, err := pspr.baseRepo.Proposals(filter)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	priced := pspr.toPricedProposals(proposals)
    71  
    72  	if filter != nil && filter.PresetID != 0 {
    73  		preset, err := pspr.filterPresets.Get(filter.PresetID)
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  		priced = preset.Filter(priced)
    78  	}
    79  
    80  	return priced, nil
    81  }
    82  
    83  // Countries fetches number of proposals per country from base repository.
    84  func (pspr *PricedServiceProposalRepository) Countries(filter *proposal.Filter) (map[string]int, error) {
    85  	return pspr.baseRepo.Countries(filter)
    86  }
    87  
    88  // EnrichProposalWithPrice adds pricing info to service proposal.
    89  func (pspr *PricedServiceProposalRepository) EnrichProposalWithPrice(in market.ServiceProposal) (proposal.PricedServiceProposal, error) {
    90  	return pspr.toPricedProposal(in)
    91  }
    92  
    93  func (pspr *PricedServiceProposalRepository) toPricedProposals(in []market.ServiceProposal) []proposal.PricedServiceProposal {
    94  	res := make([]proposal.PricedServiceProposal, 0)
    95  	for i := range in {
    96  		priced, err := pspr.toPricedProposal(in[i])
    97  		if err != nil {
    98  			log.Warn().Err(err).Msgf("could not add pricing info to proposal %v(%v)", in[i].ProviderID, in[i].ServiceType)
    99  			continue
   100  		}
   101  		res = append(res, priced)
   102  	}
   103  
   104  	return res
   105  }
   106  
   107  func (pspr *PricedServiceProposalRepository) toPricedProposal(in market.ServiceProposal) (proposal.PricedServiceProposal, error) {
   108  	price, err := pspr.pip.GetCurrentPrice(in.Location.IPType, in.Location.Country, in.ServiceType)
   109  	if err != nil {
   110  		return proposal.PricedServiceProposal{}, err
   111  	}
   112  
   113  	return proposal.PricedServiceProposal{
   114  		ServiceProposal: in,
   115  		Price:           price,
   116  	}, nil
   117  }