code.vegaprotocol.io/vega@v0.79.0/datanode/gateway/graphql/market_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 22 "code.vegaprotocol.io/vega/logging" 23 v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2" 24 "code.vegaprotocol.io/vega/protos/vega" 25 types "code.vegaprotocol.io/vega/protos/vega" 26 ) 27 28 type myMarketResolver VegaResolverRoot 29 30 func (r *myMarketResolver) EnableTxReordering(ctx context.Context, obj *types.Market) (bool, error) { 31 return obj.EnableTransactionReordering, nil 32 } 33 34 func (r *myMarketResolver) LiquidityProvisionsConnection( 35 ctx context.Context, 36 market *types.Market, 37 party *string, 38 live *bool, 39 pagination *v2.Pagination, 40 ) (*v2.LiquidityProvisionsConnection, error) { 41 var pid string 42 if party != nil { 43 pid = *party 44 } 45 46 var marketID string 47 if market != nil { 48 marketID = market.Id 49 } 50 51 var l bool 52 if live != nil { 53 l = *live 54 } 55 56 req := v2.ListLiquidityProvisionsRequest{ 57 PartyId: &pid, 58 MarketId: &marketID, 59 Live: &l, 60 Pagination: pagination, 61 } 62 63 res, err := r.tradingDataClientV2.ListLiquidityProvisions(ctx, &req) 64 if err != nil { 65 r.log.Error("tradingData client", logging.Error(err)) 66 return nil, err 67 } 68 69 return res.LiquidityProvisions, nil 70 } 71 72 func (r *myMarketResolver) LiquidityProvisions(ctx context.Context, market *vega.Market, party *string, live *bool, pagination *v2.Pagination) ( 73 *v2.LiquidityProvisionsWithPendingConnection, error, 74 ) { 75 var pid string 76 if party != nil { 77 pid = *party 78 } 79 80 var marketID string 81 if market != nil { 82 marketID = market.Id 83 } 84 85 var l bool 86 if live != nil { 87 l = *live 88 } 89 90 req := v2.ListAllLiquidityProvisionsRequest{ 91 PartyId: &pid, 92 MarketId: &marketID, 93 Live: &l, 94 Pagination: pagination, 95 } 96 97 res, err := r.tradingDataClientV2.ListAllLiquidityProvisions(ctx, &req) 98 if err != nil { 99 r.log.Error("tradingData client", logging.Error(err)) 100 return nil, err 101 } 102 103 return res.LiquidityProvisions, nil 104 } 105 106 func (r *myMarketResolver) Data(ctx context.Context, market *types.Market) (*types.MarketData, error) { 107 req := v2.GetLatestMarketDataRequest{ 108 MarketId: market.Id, 109 } 110 res, err := r.tradingDataClientV2.GetLatestMarketData(ctx, &req) 111 if err != nil { 112 r.log.Error("tradingData client", logging.Error(err)) 113 return nil, err 114 } 115 return res.MarketData, nil 116 } 117 118 func (r *myMarketResolver) OrdersConnection( 119 ctx context.Context, 120 market *types.Market, 121 pagination *v2.Pagination, 122 filter *OrderByPartyIdsFilter, 123 ) (*v2.OrderConnection, error) { 124 req := v2.ListOrdersRequest{ 125 Pagination: pagination, 126 Filter: &v2.OrderFilter{ 127 MarketIds: []string{market.Id}, 128 }, 129 } 130 131 if filter != nil { 132 req.Filter.PartyIds = filter.PartyIds 133 if filter.Order != nil { 134 req.Filter.Statuses = filter.Order.Statuses 135 req.Filter.Types = filter.Order.Types 136 req.Filter.TimeInForces = filter.Order.TimeInForces 137 req.Filter.ExcludeLiquidity = filter.Order.ExcludeLiquidity 138 req.Filter.Reference = filter.Order.Reference 139 req.Filter.DateRange = filter.Order.DateRange 140 req.Filter.LiveOnly = filter.Order.LiveOnly 141 } 142 } 143 144 res, err := r.tradingDataClientV2.ListOrders(ctx, &req) 145 if err != nil { 146 r.log.Error("tradingData client", logging.Error(err)) 147 return nil, err 148 } 149 150 return res.Orders, nil 151 } 152 153 func (r *myMarketResolver) TradesConnection(ctx context.Context, market *types.Market, dateRange *v2.DateRange, pagination *v2.Pagination) (*v2.TradeConnection, error) { 154 req := v2.ListTradesRequest{ 155 MarketIds: []string{market.Id}, 156 Pagination: pagination, 157 DateRange: dateRange, 158 } 159 res, err := r.tradingDataClientV2.ListTrades(ctx, &req) 160 if err != nil { 161 r.log.Error("tradingData client", logging.Error(err)) 162 return nil, err 163 } 164 return res.Trades, nil 165 } 166 167 func (r *myMarketResolver) Depth(ctx context.Context, market *types.Market, maxDepth *int) (*types.MarketDepth, error) { 168 if market == nil { 169 return nil, errors.New("market missing or empty") 170 } 171 172 req := v2.GetLatestMarketDepthRequest{MarketId: market.Id} 173 if maxDepth != nil { 174 if *maxDepth <= 0 { 175 return nil, errors.New("invalid maxDepth, must be a positive number") 176 } 177 reqDepth := uint64(*maxDepth) 178 req.MaxDepth = &reqDepth 179 } 180 181 // Look for market depth for the given market (will validate market internally) 182 // Note: Market depth is also known as OrderBook depth within the matching-engine 183 res, err := r.tradingDataClientV2.GetLatestMarketDepth(ctx, &req) 184 if err != nil { 185 r.log.Error("trading data client", logging.Error(err)) 186 return nil, err 187 } 188 189 return &types.MarketDepth{ 190 MarketId: res.MarketId, 191 Buy: res.Buy, 192 Sell: res.Sell, 193 SequenceNumber: res.SequenceNumber, 194 }, nil 195 } 196 197 func (r *myMarketResolver) AccountsConnection(ctx context.Context, market *types.Market, partyID *string, pagination *v2.Pagination, includeDerivedParties *bool) (*v2.AccountsConnection, error) { 198 filter := v2.AccountFilter{MarketIds: []string{market.Id}} 199 ptyID := "" 200 201 if partyID != nil { 202 // get margin account for a party 203 ptyID = *partyID 204 filter.PartyIds = []string{ptyID} 205 filter.AccountTypes = []types.AccountType{types.AccountType_ACCOUNT_TYPE_MARGIN} 206 } else { 207 filter.AccountTypes = []types.AccountType{ 208 types.AccountType_ACCOUNT_TYPE_INSURANCE, 209 types.AccountType_ACCOUNT_TYPE_FEES_LIQUIDITY, 210 } 211 } 212 213 req := v2.ListAccountsRequest{Filter: &filter, Pagination: pagination, IncludeDerivedParties: includeDerivedParties} 214 215 res, err := r.tradingDataClientV2.ListAccounts(ctx, &req) 216 if err != nil { 217 r.log.Error("unable to get market accounts", 218 logging.Error(err), 219 logging.String("market-id", market.Id), 220 logging.String("party-id", ptyID)) 221 return nil, err 222 } 223 return res.Accounts, nil 224 } 225 226 func (r *myMarketResolver) DecimalPlaces(_ context.Context, obj *types.Market) (int, error) { 227 return int(obj.DecimalPlaces), nil 228 } 229 230 func (r *myMarketResolver) PositionDecimalPlaces(_ context.Context, obj *types.Market) (int, error) { 231 return int(obj.PositionDecimalPlaces), nil 232 } 233 234 func (r *myMarketResolver) OpeningAuction(_ context.Context, obj *types.Market) (*AuctionDuration, error) { 235 return &AuctionDuration{ 236 DurationSecs: int(obj.OpeningAuction.Duration), 237 Volume: int(obj.OpeningAuction.Volume), 238 }, nil 239 } 240 241 func (r *myMarketResolver) PriceMonitoringSettings(_ context.Context, obj *types.Market) (*PriceMonitoringSettings, error) { 242 return PriceMonitoringSettingsFromProto(obj.PriceMonitoringSettings) 243 } 244 245 func (r *myMarketResolver) LiquidityMonitoringParameters(_ context.Context, obj *types.Market) (*LiquidityMonitoringParameters, error) { 246 return &LiquidityMonitoringParameters{ 247 TargetStakeParameters: &TargetStakeParameters{ 248 TimeWindow: int(obj.LiquidityMonitoringParameters.TargetStakeParameters.TimeWindow), 249 ScalingFactor: obj.LiquidityMonitoringParameters.TargetStakeParameters.ScalingFactor, 250 }, 251 }, nil 252 } 253 254 func (r *myMarketResolver) MarketProposal(ctx context.Context, obj *types.Market) (ProposalNode, error) { 255 resp, err := r.tradingDataClientV2.GetGovernanceData(ctx, &v2.GetGovernanceDataRequest{ 256 ProposalId: &obj.Id, 257 }) 258 // it's possible to not find a proposal as of now. 259 // some market are loaded at startup, without 260 // going through the proposal phase 261 if err != nil { 262 return nil, nil //nolint:nilerr 263 } 264 265 resolver := (*proposalEdgeResolver)(r) 266 if resp.GetData().ProposalType == vega.GovernanceData_TYPE_BATCH { 267 return resolver.BatchProposal(ctx, resp.GetData()) 268 } 269 270 return resp.Data, nil 271 } 272 273 func (r *myMarketResolver) Proposal(ctx context.Context, obj *types.Market) (*vega.GovernanceData, error) { 274 resp, err := r.tradingDataClientV2.GetGovernanceData(ctx, &v2.GetGovernanceDataRequest{ 275 ProposalId: &obj.Id, 276 }) 277 // it's possible to not find a proposal as of now. 278 // some market are loaded at startup, without 279 // going through the proposal phase 280 if err != nil { 281 return nil, nil //nolint:nilerr 282 } 283 284 return resp.Data, nil 285 } 286 287 func (r *myMarketResolver) RiskFactors(ctx context.Context, obj *types.Market) (*types.RiskFactor, error) { 288 rf, err := r.tradingDataClientV2.GetRiskFactors(ctx, &v2.GetRiskFactorsRequest{ 289 MarketId: obj.Id, 290 }) 291 if err != nil { 292 return nil, err 293 } 294 295 return rf.RiskFactor, nil 296 } 297 298 func (r *myMarketResolver) CandlesConnection(ctx context.Context, market *types.Market, sinceRaw string, toRaw *string, 299 interval vega.Interval, pagination *v2.Pagination, 300 ) (*v2.CandleDataConnection, error) { 301 return handleCandleConnectionRequest(ctx, r.tradingDataClientV2, market, sinceRaw, toRaw, interval, pagination) 302 } 303 304 func (r *myMarketResolver) LiquiditySLAParameters(ctx context.Context, obj *types.Market) (*types.LiquiditySLAParameters, error) { 305 return obj.LiquiditySlaParams, nil 306 } 307 308 func (r *myMarketResolver) AllowedEmptyAMMLevels(ctx context.Context, obj *types.Market) (int, error) { 309 return int(obj.AllowedEmptyAmmLevels), nil 310 }