code.vegaprotocol.io/vega@v0.79.0/datanode/service/market.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package service
    17  
    18  import (
    19  	"context"
    20  	"sync"
    21  
    22  	"code.vegaprotocol.io/vega/datanode/entities"
    23  	"code.vegaprotocol.io/vega/libs/num"
    24  )
    25  
    26  type MarketStore interface {
    27  	Upsert(ctx context.Context, market *entities.Market) error
    28  	GetByID(ctx context.Context, marketID string) (entities.Market, error)
    29  	GetByIDs(ctx context.Context, markets []string) ([]entities.Market, error)
    30  	GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.Market, error)
    31  	GetAllPaged(ctx context.Context, marketID string, pagination entities.CursorPagination, includeSettled bool) ([]entities.Market, entities.PageInfo, error)
    32  	ListSuccessorMarkets(ctx context.Context, marketID string, fullHistory bool, pagination entities.CursorPagination) ([]entities.SuccessorMarket, entities.PageInfo, error)
    33  	GetAllFees(ctx context.Context) ([]entities.Market, error)
    34  }
    35  
    36  type Markets struct {
    37  	store       MarketStore
    38  	cacheLock   sync.RWMutex
    39  	sf          map[entities.MarketID]num.Decimal
    40  	isSpotCache map[entities.MarketID]bool
    41  }
    42  
    43  func NewMarkets(store MarketStore) *Markets {
    44  	return &Markets{
    45  		store:       store,
    46  		sf:          map[entities.MarketID]num.Decimal{},
    47  		isSpotCache: map[entities.MarketID]bool{},
    48  	}
    49  }
    50  
    51  func (m *Markets) Initialise(ctx context.Context) error {
    52  	return nil
    53  }
    54  
    55  func (m *Markets) GetAllFees(ctx context.Context) ([]entities.Market, error) {
    56  	return m.store.GetAllFees(ctx)
    57  }
    58  
    59  func (m *Markets) Upsert(ctx context.Context, market *entities.Market) error {
    60  	if err := m.store.Upsert(ctx, market); err != nil {
    61  		return err
    62  	}
    63  	m.cacheLock.Lock()
    64  	if market.State == entities.MarketStateSettled || market.State == entities.MarketStateRejected || market.State == entities.MarketStateCancelled {
    65  		// a settled, cancelled, or rejected market can be safely removed from this map.
    66  		delete(m.sf, market.ID)
    67  		delete(m.isSpotCache, market.ID)
    68  	} else {
    69  		// just in case this gets updated, or the market is new.
    70  		m.sf[market.ID] = num.DecimalFromFloat(10).Pow(num.DecimalFromInt64(int64(market.PositionDecimalPlaces)))
    71  		m.isSpotCache[market.ID] = market.TradableInstrument.Instrument.GetSpot() != nil
    72  	}
    73  	m.cacheLock.Unlock()
    74  	return nil
    75  }
    76  
    77  func (m *Markets) GetByID(ctx context.Context, marketID string) (entities.Market, error) {
    78  	return m.store.GetByID(ctx, marketID)
    79  }
    80  
    81  func (m *Markets) GetByIDs(ctx context.Context, markets []string) ([]entities.Market, error) {
    82  	return m.store.GetByIDs(ctx, markets)
    83  }
    84  
    85  func (m *Markets) GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.Market, error) {
    86  	return m.store.GetByTxHash(ctx, txHash)
    87  }
    88  
    89  func (m *Markets) GetMarketScalingFactor(ctx context.Context, marketID string) (num.Decimal, bool) {
    90  	m.cacheLock.Lock()
    91  	defer m.cacheLock.Unlock()
    92  	if pf, ok := m.sf[entities.MarketID(marketID)]; ok {
    93  		return pf, true
    94  	}
    95  
    96  	market, err := m.store.GetByID(ctx, marketID)
    97  	if err != nil {
    98  		return num.Decimal{}, false
    99  	}
   100  
   101  	pf := num.DecimalFromFloat(10).Pow(num.DecimalFromInt64(int64(market.PositionDecimalPlaces)))
   102  	return pf, true
   103  }
   104  
   105  func (m *Markets) IsSpotMarket(ctx context.Context, marketID string) bool {
   106  	m.cacheLock.Lock()
   107  	defer m.cacheLock.Unlock()
   108  	if is, ok := m.isSpotCache[entities.MarketID(marketID)]; ok {
   109  		return is
   110  	}
   111  
   112  	market, err := m.store.GetByID(ctx, marketID)
   113  	if err != nil {
   114  		return false
   115  	}
   116  	return market.TradableInstrument.Instrument.GetSpot() != nil
   117  }
   118  
   119  func (m *Markets) GetAllPaged(ctx context.Context, marketID string, pagination entities.CursorPagination, includeSettled bool) ([]entities.Market, entities.PageInfo, error) {
   120  	return m.store.GetAllPaged(ctx, marketID, pagination, includeSettled)
   121  }
   122  
   123  func (m *Markets) ListSuccessorMarkets(ctx context.Context, marketID string, childrenOnly bool, pagination entities.CursorPagination) ([]entities.SuccessorMarket, entities.PageInfo, error) {
   124  	return m.store.ListSuccessorMarkets(ctx, marketID, childrenOnly, pagination)
   125  }