code.vegaprotocol.io/vega@v0.79.0/datanode/gateway/graphql/market_data_resolvers.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 gql
    17  
    18  import (
    19  	"context"
    20  	"errors"
    21  	"io"
    22  	"strconv"
    23  
    24  	"code.vegaprotocol.io/vega/datanode/vegatime"
    25  	"code.vegaprotocol.io/vega/logging"
    26  	v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2"
    27  	types "code.vegaprotocol.io/vega/protos/vega"
    28  	vega "code.vegaprotocol.io/vega/protos/vega"
    29  	vegapb "code.vegaprotocol.io/vega/protos/vega"
    30  
    31  	"google.golang.org/grpc"
    32  )
    33  
    34  // MarketDepth returns the market depth resolver.
    35  func (r *VegaResolverRoot) MarketDepth() MarketDepthResolver {
    36  	return (*myMarketDepthResolver)(r)
    37  }
    38  
    39  func (r *VegaResolverRoot) ObservableMarketDepth() ObservableMarketDepthResolver {
    40  	return (*myObservableMarketDepthResolver)(r)
    41  }
    42  
    43  // MarketDepthUpdate returns the market depth update resolver.
    44  func (r *VegaResolverRoot) MarketDepthUpdate() MarketDepthUpdateResolver {
    45  	return (*myMarketDepthUpdateResolver)(r)
    46  }
    47  
    48  func (r *VegaResolverRoot) ObservableMarketDepthUpdate() ObservableMarketDepthUpdateResolver {
    49  	return (*myObservableMarketDepthUpdateResolver)(r)
    50  }
    51  
    52  // MarketData returns the market data resolver.
    53  func (r *VegaResolverRoot) MarketData() MarketDataResolver {
    54  	return (*myMarketDataResolver)(r)
    55  }
    56  
    57  func (r *VegaResolverRoot) ObservableMarketData() ObservableMarketDataResolver {
    58  	return (*myObservableMarketDataResolver)(r)
    59  }
    60  
    61  // BEGIN: MarketData resolver
    62  
    63  type myMarketDataResolver VegaResolverRoot
    64  
    65  // ActiveProtocolAutomatedPurchase implements MarketDataResolver.
    66  func (r *myMarketDataResolver) ActiveProtocolAutomatedPurchase(ctx context.Context, obj *vegapb.MarketData) (*ProtocolAutomatedPurchaseState, error) {
    67  	if obj.ActiveProtocolAutomatedPurchase != nil {
    68  		return &ProtocolAutomatedPurchaseState{
    69  			ID:      obj.ActiveProtocolAutomatedPurchase.Id,
    70  			OrderID: obj.ActiveProtocolAutomatedPurchase.OrderId,
    71  		}, nil
    72  	}
    73  	return nil, nil
    74  }
    75  
    76  func (r *myMarketDataResolver) MarkPriceType(_ context.Context, m *types.MarketData) (CompositePriceType, error) {
    77  	if m.MarkPriceType == types.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED {
    78  		return CompositePriceTypeCompositePriceTypeWeighted, nil
    79  	} else if m.MarkPriceType == types.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN {
    80  		return CompositePriceTypeCompositePriceTypeMedian, nil
    81  	} else {
    82  		return CompositePriceTypeCompositePriceTypeLastTrade, nil
    83  	}
    84  }
    85  
    86  func (r *myMarketDataResolver) AuctionStart(_ context.Context, m *types.MarketData) (*string, error) {
    87  	if m.AuctionStart <= 0 {
    88  		return nil, nil
    89  	}
    90  	s := vegatime.Format(vegatime.UnixNano(m.AuctionStart))
    91  	return &s, nil
    92  }
    93  
    94  func (r *myMarketDataResolver) AuctionEnd(_ context.Context, m *types.MarketData) (*string, error) {
    95  	if m.AuctionEnd <= 0 {
    96  		return nil, nil
    97  	}
    98  	s := vegatime.Format(vegatime.UnixNano(m.AuctionEnd))
    99  	return &s, nil
   100  }
   101  
   102  func (r *myMarketDataResolver) IndicativePrice(_ context.Context, m *types.MarketData) (string, error) {
   103  	return m.IndicativePrice, nil
   104  }
   105  
   106  func (r *myMarketDataResolver) IndicativeVolume(_ context.Context, m *types.MarketData) (string, error) {
   107  	return strconv.FormatUint(m.IndicativeVolume, 10), nil
   108  }
   109  
   110  func (r *myMarketDataResolver) BestBidPrice(_ context.Context, m *types.MarketData) (string, error) {
   111  	return m.BestBidPrice, nil
   112  }
   113  
   114  func (r *myMarketDataResolver) BestStaticBidPrice(_ context.Context, m *types.MarketData) (string, error) {
   115  	return m.BestStaticBidPrice, nil
   116  }
   117  
   118  func (r *myMarketDataResolver) BestStaticBidVolume(_ context.Context, m *types.MarketData) (string, error) {
   119  	return strconv.FormatUint(m.BestStaticBidVolume, 10), nil
   120  }
   121  
   122  func (r *myMarketDataResolver) OpenInterest(_ context.Context, m *types.MarketData) (string, error) {
   123  	return strconv.FormatUint(m.OpenInterest, 10), nil
   124  }
   125  
   126  func (r *myMarketDataResolver) BestBidVolume(_ context.Context, m *types.MarketData) (string, error) {
   127  	return strconv.FormatUint(m.BestBidVolume, 10), nil
   128  }
   129  
   130  func (r *myMarketDataResolver) BestOfferPrice(_ context.Context, m *types.MarketData) (string, error) {
   131  	return m.BestOfferPrice, nil
   132  }
   133  
   134  func (r *myMarketDataResolver) BestStaticOfferPrice(_ context.Context, m *types.MarketData) (string, error) {
   135  	return m.BestStaticOfferPrice, nil
   136  }
   137  
   138  func (r *myMarketDataResolver) BestStaticOfferVolume(_ context.Context, m *types.MarketData) (string, error) {
   139  	return strconv.FormatUint(m.BestStaticOfferVolume, 10), nil
   140  }
   141  
   142  func (r *myMarketDataResolver) BestOfferVolume(_ context.Context, m *types.MarketData) (string, error) {
   143  	return strconv.FormatUint(m.BestOfferVolume, 10), nil
   144  }
   145  
   146  func (r *myMarketDataResolver) MidPrice(_ context.Context, m *types.MarketData) (string, error) {
   147  	return m.MidPrice, nil
   148  }
   149  
   150  func (r *myMarketDataResolver) StaticMidPrice(_ context.Context, m *types.MarketData) (string, error) {
   151  	return m.StaticMidPrice, nil
   152  }
   153  
   154  func (r *myMarketDataResolver) MarkPrice(_ context.Context, m *types.MarketData) (string, error) {
   155  	return m.MarkPrice, nil
   156  }
   157  
   158  func (r *myMarketDataResolver) Timestamp(_ context.Context, m *types.MarketData) (string, error) {
   159  	return vegatime.Format(vegatime.UnixNano(m.Timestamp)), nil
   160  }
   161  
   162  func (r *myMarketDataResolver) Commitments(ctx context.Context, m *types.MarketData) (*MarketDataCommitments, error) {
   163  	// get all the commitments for the given market
   164  	req := v2.ListLiquidityProvisionsRequest{
   165  		MarketId: &m.Market,
   166  	}
   167  	res, err := r.tradingDataClientV2.ListLiquidityProvisions(ctx, &req)
   168  	if err != nil {
   169  		r.log.Error("tradingData client", logging.Error(err))
   170  		return nil, err
   171  	}
   172  
   173  	// now we split all the sells and buys
   174  	sells := []*types.LiquidityOrderReference{}
   175  	buys := []*types.LiquidityOrderReference{}
   176  
   177  	for _, v := range res.LiquidityProvisions.Edges {
   178  		sells = append(sells, v.Node.Sells...)
   179  		buys = append(buys, v.Node.Buys...)
   180  	}
   181  
   182  	return &MarketDataCommitments{
   183  		Sells: sells,
   184  		Buys:  buys,
   185  	}, nil
   186  }
   187  
   188  func (r *myMarketDataResolver) PriceMonitoringBounds(ctx context.Context, obj *types.MarketData) ([]*PriceMonitoringBounds, error) {
   189  	ret := make([]*PriceMonitoringBounds, 0, len(obj.PriceMonitoringBounds))
   190  	for _, b := range obj.PriceMonitoringBounds {
   191  		probability, err := strconv.ParseFloat(b.Trigger.Probability, 64)
   192  		if err != nil {
   193  			return nil, err
   194  		}
   195  
   196  		bounds := &PriceMonitoringBounds{
   197  			MinValidPrice: b.MinValidPrice,
   198  			MaxValidPrice: b.MaxValidPrice,
   199  			Trigger: &PriceMonitoringTrigger{
   200  				HorizonSecs:          int(b.Trigger.Horizon),
   201  				Probability:          probability,
   202  				AuctionExtensionSecs: int(b.Trigger.AuctionExtension),
   203  			},
   204  			ReferencePrice: b.ReferencePrice,
   205  		}
   206  		ret = append(ret, bounds)
   207  	}
   208  	return ret, nil
   209  }
   210  
   211  func (r *myMarketDataResolver) Market(ctx context.Context, m *types.MarketData) (*types.Market, error) {
   212  	return r.r.getMarketByID(ctx, m.Market)
   213  }
   214  
   215  func (r *myMarketDataResolver) MarketValueProxy(_ context.Context, m *types.MarketData) (string, error) {
   216  	return m.MarketValueProxy, nil
   217  }
   218  
   219  func (r *myMarketDataResolver) LiquidityProviderFeeShare(_ context.Context, m *types.MarketData) ([]*LiquidityProviderFeeShare, error) {
   220  	out := make([]*LiquidityProviderFeeShare, 0, len(m.LiquidityProviderFeeShare))
   221  	for _, v := range m.LiquidityProviderFeeShare {
   222  		out = append(out, &LiquidityProviderFeeShare{
   223  			Party:                 &types.Party{Id: v.Party},
   224  			EquityLikeShare:       v.EquityLikeShare,
   225  			AverageEntryValuation: v.AverageEntryValuation,
   226  			AverageScore:          v.AverageScore,
   227  			VirtualStake:          v.VirtualStake,
   228  		})
   229  	}
   230  	return out, nil
   231  }
   232  
   233  func (r *myMarketDataResolver) LiquidityProviderSLA(_ context.Context, m *types.MarketData) ([]*LiquidityProviderSLA, error) {
   234  	out := make([]*LiquidityProviderSLA, 0, len(m.LiquidityProviderSla))
   235  	for _, v := range m.LiquidityProviderSla {
   236  		out = append(out, &LiquidityProviderSLA{
   237  			Party:                            &vegapb.Party{Id: v.Party},
   238  			CurrentEpochFractionOfTimeOnBook: v.CurrentEpochFractionOfTimeOnBook,
   239  			LastEpochFractionOfTimeOnBook:    v.LastEpochFractionOfTimeOnBook,
   240  			LastEpochFeePenalty:              v.LastEpochFeePenalty,
   241  			LastEpochBondPenalty:             v.LastEpochBondPenalty,
   242  			HysteresisPeriodFeePenalties:     v.HysteresisPeriodFeePenalties,
   243  		})
   244  	}
   245  	return out, nil
   246  }
   247  
   248  func (r *myMarketDataResolver) NextMarkToMarket(_ context.Context, m *types.MarketData) (string, error) {
   249  	return vegatime.Format(vegatime.UnixNano(m.NextMarkToMarket)), nil
   250  }
   251  
   252  func (r *myMarketDataResolver) NextNetworkCloseout(_ context.Context, m *types.MarketData) (string, error) {
   253  	if m.NextNetworkCloseout == 0 {
   254  		return "", nil
   255  	}
   256  	return vegatime.Format(vegatime.UnixNano(m.NextNetworkCloseout)), nil
   257  }
   258  
   259  func (r *myMarketDataResolver) MarketGrowth(_ context.Context, m *types.MarketData) (string, error) {
   260  	return m.MarketGrowth, nil
   261  }
   262  
   263  func (r *myMarketDataResolver) ProductData(_ context.Context, m *types.MarketData) (ProductData, error) {
   264  	if m.GetProductData() == nil {
   265  		return nil, nil
   266  	}
   267  
   268  	switch pd := m.GetProductData().Data.(type) {
   269  	case *types.ProductData_PerpetualData:
   270  		return pd.PerpetualData, nil
   271  	}
   272  	return nil, nil
   273  }
   274  
   275  type myObservableMarketDataResolver myMarketDataResolver
   276  
   277  // ActiveProtocolAutomatedPurchase implements ObservableMarketDataResolver.
   278  func (r *myObservableMarketDataResolver) ActiveProtocolAutomatedPurchase(ctx context.Context, obj *vegapb.MarketData) (*ProtocolAutomatedPurchaseState, error) {
   279  	if obj.ActiveProtocolAutomatedPurchase != nil {
   280  		return &ProtocolAutomatedPurchaseState{
   281  			ID:      obj.ActiveProtocolAutomatedPurchase.Id,
   282  			OrderID: obj.ActiveProtocolAutomatedPurchase.OrderId,
   283  		}, nil
   284  	}
   285  	return nil, nil
   286  }
   287  
   288  func (r *myObservableMarketDataResolver) MarketID(ctx context.Context, m *types.MarketData) (string, error) {
   289  	return m.Market, nil
   290  }
   291  
   292  func (r *myObservableMarketDataResolver) AuctionStart(ctx context.Context, m *types.MarketData) (*string, error) {
   293  	return (*myMarketDataResolver)(r).AuctionStart(ctx, m)
   294  }
   295  
   296  func (r *myObservableMarketDataResolver) AuctionEnd(ctx context.Context, m *types.MarketData) (*string, error) {
   297  	return (*myMarketDataResolver)(r).AuctionEnd(ctx, m)
   298  }
   299  
   300  func (r *myObservableMarketDataResolver) IndicativePrice(ctx context.Context, m *types.MarketData) (string, error) {
   301  	return (*myMarketDataResolver)(r).IndicativePrice(ctx, m)
   302  }
   303  
   304  func (r *myObservableMarketDataResolver) IndicativeVolume(ctx context.Context, m *types.MarketData) (string, error) {
   305  	return (*myMarketDataResolver)(r).IndicativeVolume(ctx, m)
   306  }
   307  
   308  func (r *myObservableMarketDataResolver) BestBidPrice(ctx context.Context, m *types.MarketData) (string, error) {
   309  	return (*myMarketDataResolver)(r).BestBidPrice(ctx, m)
   310  }
   311  
   312  func (r *myObservableMarketDataResolver) BestStaticBidPrice(ctx context.Context, m *types.MarketData) (string, error) {
   313  	return (*myMarketDataResolver)(r).BestStaticBidPrice(ctx, m)
   314  }
   315  
   316  func (r *myObservableMarketDataResolver) BestStaticBidVolume(ctx context.Context, m *types.MarketData) (string, error) {
   317  	return (*myMarketDataResolver)(r).BestStaticBidVolume(ctx, m)
   318  }
   319  
   320  func (r *myObservableMarketDataResolver) OpenInterest(_ context.Context, m *types.MarketData) (string, error) {
   321  	return strconv.FormatUint(m.OpenInterest, 10), nil
   322  }
   323  
   324  func (r *myObservableMarketDataResolver) BestBidVolume(ctx context.Context, m *types.MarketData) (string, error) {
   325  	return (*myMarketDataResolver)(r).BestBidVolume(ctx, m)
   326  }
   327  
   328  func (r *myObservableMarketDataResolver) BestOfferPrice(ctx context.Context, m *types.MarketData) (string, error) {
   329  	return (*myMarketDataResolver)(r).BestOfferPrice(ctx, m)
   330  }
   331  
   332  func (r *myObservableMarketDataResolver) BestStaticOfferPrice(ctx context.Context, m *types.MarketData) (string, error) {
   333  	return (*myMarketDataResolver)(r).BestStaticOfferPrice(ctx, m)
   334  }
   335  
   336  func (r *myObservableMarketDataResolver) BestStaticOfferVolume(ctx context.Context, m *types.MarketData) (string, error) {
   337  	return (*myMarketDataResolver)(r).BestStaticOfferVolume(ctx, m)
   338  }
   339  
   340  func (r *myObservableMarketDataResolver) BestOfferVolume(ctx context.Context, m *types.MarketData) (string, error) {
   341  	return (*myMarketDataResolver)(r).BestOfferVolume(ctx, m)
   342  }
   343  
   344  func (r *myObservableMarketDataResolver) MidPrice(ctx context.Context, m *types.MarketData) (string, error) {
   345  	return (*myMarketDataResolver)(r).MidPrice(ctx, m)
   346  }
   347  
   348  func (r *myObservableMarketDataResolver) StaticMidPrice(ctx context.Context, m *types.MarketData) (string, error) {
   349  	return (*myMarketDataResolver)(r).StaticMidPrice(ctx, m)
   350  }
   351  
   352  func (r *myObservableMarketDataResolver) MarkPrice(ctx context.Context, m *types.MarketData) (string, error) {
   353  	return (*myMarketDataResolver)(r).MarkPrice(ctx, m)
   354  }
   355  
   356  func (r *myObservableMarketDataResolver) MarkPriceType(_ context.Context, m *types.MarketData) (CompositePriceType, error) {
   357  	if m.MarkPriceType == types.CompositePriceType_COMPOSITE_PRICE_TYPE_WEIGHTED {
   358  		return CompositePriceTypeCompositePriceTypeWeighted, nil
   359  	} else if m.MarkPriceType == types.CompositePriceType_COMPOSITE_PRICE_TYPE_MEDIAN {
   360  		return CompositePriceTypeCompositePriceTypeMedian, nil
   361  	} else {
   362  		return CompositePriceTypeCompositePriceTypeLastTrade, nil
   363  	}
   364  }
   365  
   366  func (r *myObservableMarketDataResolver) Timestamp(ctx context.Context, m *types.MarketData) (string, error) {
   367  	return (*myMarketDataResolver)(r).Timestamp(ctx, m)
   368  }
   369  
   370  func (r *myObservableMarketDataResolver) PriceMonitoringBounds(ctx context.Context, obj *types.MarketData) ([]*PriceMonitoringBounds, error) {
   371  	return (*myMarketDataResolver)(r).PriceMonitoringBounds(ctx, obj)
   372  }
   373  
   374  func (r *myObservableMarketDataResolver) ProductData(_ context.Context, m *types.MarketData) (ProductData, error) {
   375  	if m.GetProductData() == nil {
   376  		return nil, nil
   377  	}
   378  
   379  	switch pd := m.GetProductData().Data.(type) {
   380  	case *types.ProductData_PerpetualData:
   381  		return pd.PerpetualData, nil
   382  	}
   383  	return nil, nil
   384  }
   385  
   386  // ExtensionTrigger same as Trigger.
   387  func (r *myObservableMarketDataResolver) ExtensionTrigger(ctx context.Context, m *types.MarketData) (vega.AuctionTrigger, error) {
   388  	return m.ExtensionTrigger, nil
   389  }
   390  
   391  func (r *myObservableMarketDataResolver) MarketValueProxy(ctx context.Context, m *types.MarketData) (string, error) {
   392  	return (*myMarketDataResolver)(r).MarketValueProxy(ctx, m)
   393  }
   394  
   395  func (r *myObservableMarketDataResolver) LiquidityProviderFeeShare(ctx context.Context, m *types.MarketData) ([]*ObservableLiquidityProviderFeeShare, error) {
   396  	out := make([]*ObservableLiquidityProviderFeeShare, 0, len(m.LiquidityProviderFeeShare))
   397  	for _, v := range m.LiquidityProviderFeeShare {
   398  		out = append(out, &ObservableLiquidityProviderFeeShare{
   399  			PartyID:               v.Party,
   400  			EquityLikeShare:       v.EquityLikeShare,
   401  			AverageEntryValuation: v.AverageEntryValuation,
   402  			AverageScore:          v.AverageScore,
   403  		})
   404  	}
   405  	return out, nil
   406  }
   407  
   408  func (r *myObservableMarketDataResolver) LiquidityProviderSLA(ctx context.Context, m *types.MarketData) ([]*ObservableLiquidityProviderSLA, error) {
   409  	out := make([]*ObservableLiquidityProviderSLA, 0, len(m.LiquidityProviderSla))
   410  	for _, v := range m.LiquidityProviderSla {
   411  		out = append(out, &ObservableLiquidityProviderSLA{
   412  			Party:                            v.Party,
   413  			CurrentEpochFractionOfTimeOnBook: v.CurrentEpochFractionOfTimeOnBook,
   414  			LastEpochFractionOfTimeOnBook:    v.LastEpochFractionOfTimeOnBook,
   415  			LastEpochFeePenalty:              v.LastEpochFeePenalty,
   416  			LastEpochBondPenalty:             v.LastEpochBondPenalty,
   417  			HysteresisPeriodFeePenalties:     v.HysteresisPeriodFeePenalties,
   418  		})
   419  	}
   420  	return out, nil
   421  }
   422  
   423  func (r *myObservableMarketDataResolver) NextMarkToMarket(ctx context.Context, m *types.MarketData) (string, error) {
   424  	return (*myMarketDataResolver)(r).NextMarkToMarket(ctx, m)
   425  }
   426  
   427  func (r *myObservableMarketDataResolver) NextNetworkCloseout(ctx context.Context, m *types.MarketData) (string, error) {
   428  	return (*myMarketDataResolver)(r).NextNetworkCloseout(ctx, m)
   429  }
   430  
   431  func (r *myObservableMarketDataResolver) MarketGrowth(ctx context.Context, m *types.MarketData) (string, error) {
   432  	return (*myMarketDataResolver)(r).MarketGrowth(ctx, m)
   433  }
   434  
   435  // END: MarketData resolver
   436  
   437  // BEGIN: Market Depth Resolver
   438  
   439  type myMarketDepthResolver VegaResolverRoot
   440  
   441  func (r *myMarketDepthResolver) LastTrade(ctx context.Context, md *types.MarketDepth) (*types.Trade, error) {
   442  	if md == nil {
   443  		return nil, errors.New("invalid market depth")
   444  	}
   445  
   446  	req := v2.GetLastTradeRequest{MarketId: md.MarketId}
   447  	res, err := r.tradingDataClientV2.GetLastTrade(ctx, &req)
   448  	if err != nil {
   449  		r.log.Error("tradingData client", logging.Error(err))
   450  		return nil, err
   451  	}
   452  	return res.Trade, nil
   453  }
   454  
   455  func (r *myMarketDepthResolver) SequenceNumber(ctx context.Context, md *types.MarketDepth) (string, error) {
   456  	return strconv.FormatUint(md.SequenceNumber, 10), nil
   457  }
   458  
   459  func (r *myMarketDepthResolver) Market(ctx context.Context, md *types.MarketDepth) (*types.Market, error) {
   460  	return r.r.getMarketByID(ctx, md.MarketId)
   461  }
   462  
   463  type myObservableMarketDepthResolver myMarketDepthResolver
   464  
   465  func (r *myObservableMarketDepthResolver) LastTrade(ctx context.Context, md *types.MarketDepth) (*MarketDepthTrade, error) {
   466  	if md == nil {
   467  		return nil, errors.New("invalid market depth")
   468  	}
   469  
   470  	req := v2.GetLastTradeRequest{MarketId: md.MarketId}
   471  	res, err := r.tradingDataClientV2.GetLastTrade(ctx, &req)
   472  	if err != nil {
   473  		r.log.Error("tradingData client", logging.Error(err))
   474  		return nil, err
   475  	}
   476  	return &MarketDepthTrade{ID: res.Trade.Id, Price: res.Trade.Price, Size: strconv.FormatUint(res.Trade.Size, 10)}, nil
   477  }
   478  
   479  func (r *myObservableMarketDepthResolver) SequenceNumber(ctx context.Context, md *types.MarketDepth) (string, error) {
   480  	return (*myMarketDepthResolver)(r).SequenceNumber(ctx, md)
   481  }
   482  
   483  // END: Market Depth Resolver
   484  
   485  // BEGIN: Market Depth Update Resolver
   486  
   487  type myMarketDepthUpdateResolver VegaResolverRoot
   488  
   489  func (r *myMarketDepthUpdateResolver) SequenceNumber(ctx context.Context, md *types.MarketDepthUpdate) (string, error) {
   490  	return strconv.FormatUint(md.SequenceNumber, 10), nil
   491  }
   492  
   493  func (r *myMarketDepthUpdateResolver) PreviousSequenceNumber(ctx context.Context, md *types.MarketDepthUpdate) (string, error) {
   494  	return strconv.FormatUint(md.PreviousSequenceNumber, 10), nil
   495  }
   496  
   497  func (r *myMarketDepthUpdateResolver) Market(ctx context.Context, md *types.MarketDepthUpdate) (*types.Market, error) {
   498  	return r.r.getMarketByID(ctx, md.MarketId)
   499  }
   500  
   501  type myObservableMarketDepthUpdateResolver myMarketDepthUpdateResolver
   502  
   503  func (r *myObservableMarketDepthUpdateResolver) SequenceNumber(ctx context.Context, md *types.MarketDepthUpdate) (string, error) {
   504  	return (*myMarketDepthUpdateResolver)(r).SequenceNumber(ctx, md)
   505  }
   506  
   507  func (r *myObservableMarketDepthUpdateResolver) PreviousSequenceNumber(ctx context.Context, md *types.MarketDepthUpdate) (string, error) {
   508  	return (*myMarketDepthUpdateResolver)(r).PreviousSequenceNumber(ctx, md)
   509  }
   510  
   511  // END: Market Depth Update Resolver
   512  
   513  func (r *mySubscriptionResolver) MarketsDepth(ctx context.Context, marketIds []string) (<-chan []*types.MarketDepth, error) {
   514  	req := &v2.ObserveMarketsDepthRequest{
   515  		MarketIds: marketIds,
   516  	}
   517  	stream, err := r.tradingDataClientV2.ObserveMarketsDepth(ctx, req)
   518  	if err != nil {
   519  		return nil, err
   520  	}
   521  
   522  	return grpcStreamToGraphQlChannel[*v2.ObserveMarketsDepthResponse](ctx, r.log, "marketsDepth", stream,
   523  		func(md *v2.ObserveMarketsDepthResponse) []*types.MarketDepth {
   524  			return md.MarketDepth
   525  		}), nil
   526  }
   527  
   528  func (r *mySubscriptionResolver) MarketsDepthUpdate(ctx context.Context, marketIDs []string) (<-chan []*types.MarketDepthUpdate, error) {
   529  	req := &v2.ObserveMarketsDepthUpdatesRequest{
   530  		MarketIds: marketIDs,
   531  	}
   532  	stream, err := r.tradingDataClientV2.ObserveMarketsDepthUpdates(ctx, req)
   533  	if err != nil {
   534  		return nil, err
   535  	}
   536  
   537  	return grpcStreamToGraphQlChannel[*v2.ObserveMarketsDepthUpdatesResponse](ctx, r.log, "marketsDepthUpdate", stream,
   538  		func(md *v2.ObserveMarketsDepthUpdatesResponse) []*types.MarketDepthUpdate {
   539  			return md.Update
   540  		}), nil
   541  }
   542  
   543  func (r *mySubscriptionResolver) MarketsData(ctx context.Context, marketIds []string) (<-chan []*types.MarketData, error) {
   544  	req := &v2.ObserveMarketsDataRequest{
   545  		MarketIds: marketIds,
   546  	}
   547  	stream, err := r.tradingDataClientV2.ObserveMarketsData(ctx, req)
   548  	if err != nil {
   549  		return nil, err
   550  	}
   551  
   552  	return grpcStreamToGraphQlChannel[*v2.ObserveMarketsDataResponse](ctx, r.log, "marketsdata", stream,
   553  		func(md *v2.ObserveMarketsDataResponse) []*types.MarketData {
   554  			return md.MarketData
   555  		}), nil
   556  }
   557  
   558  type grpcStream[T any] interface {
   559  	Recv() (T, error)
   560  	grpc.ClientStream
   561  }
   562  
   563  func grpcStreamToGraphQlChannel[T any, Y any](ctx context.Context, log *logging.Logger, observableType string, stream grpcStream[T], grpcStreamTypeToGraphQlType func(T) Y) chan Y {
   564  	// should be just a wrapped version of ctx, but let's check both
   565  	sCtx := stream.Context()
   566  	c := make(chan Y)
   567  	go func() {
   568  		defer func() {
   569  			stream.CloseSend()
   570  			close(c)
   571  		}()
   572  		for {
   573  			md, err := stream.Recv()
   574  			if err == io.EOF {
   575  				log.Error(observableType+": stream closed by server", logging.Error(err))
   576  				break
   577  			}
   578  			if err != nil {
   579  				log.Error(observableType+": stream closed", logging.Error(err))
   580  				break
   581  			}
   582  			select {
   583  			case c <- grpcStreamTypeToGraphQlType(md):
   584  				log.Debugf("%s: data sent", observableType)
   585  				continue
   586  			case <-sCtx.Done():
   587  				log.Debugf("%s: stream closed by server", observableType)
   588  				break
   589  			case <-ctx.Done():
   590  				log.Debugf("%s: stream closed", observableType)
   591  				break
   592  			}
   593  		}
   594  	}()
   595  	return c
   596  }