code.vegaprotocol.io/vega@v0.79.0/datanode/api/server.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 api 17 18 import ( 19 "context" 20 "fmt" 21 "io" 22 "net" 23 "net/http" 24 "strconv" 25 "time" 26 27 "code.vegaprotocol.io/vega/core/events" 28 "code.vegaprotocol.io/vega/datanode/candlesv2" 29 "code.vegaprotocol.io/vega/datanode/contextutil" 30 "code.vegaprotocol.io/vega/datanode/entities" 31 "code.vegaprotocol.io/vega/datanode/gateway" 32 "code.vegaprotocol.io/vega/datanode/networkhistory/segment" 33 "code.vegaprotocol.io/vega/datanode/ratelimit" 34 "code.vegaprotocol.io/vega/datanode/service" 35 "code.vegaprotocol.io/vega/libs/subscribers" 36 "code.vegaprotocol.io/vega/logging" 37 protoapi "code.vegaprotocol.io/vega/protos/data-node/api/v2" 38 v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2" 39 vegaprotoapi "code.vegaprotocol.io/vega/protos/vega/api/v1" 40 eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1" 41 42 "github.com/fullstorydev/grpcui/standalone" 43 "golang.org/x/sync/errgroup" 44 "google.golang.org/grpc" 45 "google.golang.org/grpc/codes" 46 "google.golang.org/grpc/metadata" 47 "google.golang.org/grpc/peer" 48 "google.golang.org/grpc/reflection" 49 "google.golang.org/grpc/status" 50 ) 51 52 // VolumeDiscountService ... 53 // 54 //go:generate go run github.com/golang/mock/mockgen -destination mocks/volume_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api VolumeDiscountService 55 type VolumeDiscountService interface { 56 Stats(ctx context.Context, atEpoch *uint64, partyID *string, pagination entities.CursorPagination) ([]entities.FlattenVolumeDiscountStats, entities.PageInfo, error) 57 } 58 59 // EpochService 60 // 61 //go:generate go run github.com/golang/mock/mockgen -destination mocks/epoch_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api EpochService 62 type EpochService interface { 63 GetCurrent(ctx context.Context) (entities.Epoch, error) 64 GetByBlock(ctx context.Context, height uint64) (entities.Epoch, error) 65 Get(ctx context.Context, ID uint64) (entities.Epoch, error) 66 GetAll(ctx context.Context) ([]entities.Epoch, error) 67 } 68 69 type ReferralSetService interface { 70 GetReferralSetStats(ctx context.Context, setID *entities.ReferralSetID, atEpoch *uint64, referee *entities.PartyID, pagination entities.CursorPagination) ([]entities.FlattenReferralSetStats, entities.PageInfo, error) 71 ListReferralSets(ctx context.Context, referralSetID *entities.ReferralSetID, referrer, referee *entities.PartyID, pagination entities.CursorPagination) ([]entities.ReferralSet, entities.PageInfo, error) 72 ListReferralSetReferees(ctx context.Context, referralSetID *entities.ReferralSetID, referrer, referee *entities.PartyID, pagination entities.CursorPagination, aggregationEpochs uint32) ([]entities.ReferralSetRefereeStats, entities.PageInfo, error) 73 } 74 75 // EventService ... 76 // 77 //go:generate go run github.com/golang/mock/mockgen -destination mocks/event_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api EventService 78 type EventService interface { 79 ObserveEvents(ctx context.Context, retries int, eTypes []events.Type, batchSize int, filters ...subscribers.EventFilter) (<-chan []*eventspb.BusEvent, chan<- int) 80 } 81 82 // BlockService ... 83 // 84 //go:generate go run github.com/golang/mock/mockgen -destination mocks/block_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api BlockService 85 type BlockService interface { 86 GetLastBlock(ctx context.Context) (entities.Block, error) 87 } 88 89 // NetworkHistoryService ... 90 // 91 // it would be nice to use go:generate go run github.com/golang/mock/mockgen -destination mocks/networkhistory_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api NetworkHistoryService 92 // however it currently can't handle generic arguments and the generated code is not compilable without a bit of manual tweaking. 93 type NetworkHistoryService interface { 94 GetHighestBlockHeightHistorySegment() (segment.Full, error) 95 ListAllHistorySegments() (segment.Segments[segment.Full], error) 96 FetchHistorySegment(ctx context.Context, historySegmentID string) (segment.Full, error) 97 GetActivePeerIPAddresses() []string 98 CopyHistorySegmentToFile(ctx context.Context, historySegmentID string, outFile string) error 99 GetHistorySegmentReader(ctx context.Context, historySegmentID string) (io.ReadSeekCloser, int64, error) 100 GetSwarmKeySeed() string 101 GetConnectedPeerAddresses() ([]string, error) 102 GetIpfsAddress() (string, error) 103 GetSwarmKey() string 104 GetBootstrapPeers() []string 105 } 106 107 // MarketsService ... 108 // 109 //go:generate go run github.com/golang/mock/mockgen -destination mocks/markets_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api MarketsService 110 type MarketsService interface { 111 GetByID(ctx context.Context, marketID string) (entities.Market, error) 112 GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.Market, error) 113 GetAllPaged(ctx context.Context, marketID string, pagination entities.CursorPagination, includeSettled bool) ([]entities.Market, entities.PageInfo, error) 114 ListSuccessorMarkets(ctx context.Context, marketID string, childrenOnly bool, pagination entities.CursorPagination) ([]entities.SuccessorMarket, entities.PageInfo, error) 115 } 116 117 // MarketDataService ... 118 // 119 //go:generate go run github.com/golang/mock/mockgen -destination mocks/market_data_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api MarketDataService 120 type MarketDataService interface { 121 GetMarketDataByID(ctx context.Context, marketID string) (entities.MarketData, error) 122 GetMarketsData(ctx context.Context) ([]entities.MarketData, error) 123 GetHistoricMarketData(ctx context.Context, marketID string, start, end *time.Time, pagination entities.Pagination) ([]entities.MarketData, entities.PageInfo, error) 124 ObserveMarketData(ctx context.Context, retries int, marketID []string) (<-chan []*entities.MarketData, uint64) 125 } 126 127 // RiskFactorService ... 128 // 129 //go:generate go run github.com/golang/mock/mockgen -destination mocks/risk_factor_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api RiskFactorService 130 type RiskFactorService interface { 131 GetMarketRiskFactors(ctx context.Context, marketID string) (entities.RiskFactor, error) 132 } 133 134 // Asset service ... 135 // 136 //go:generate go run github.com/golang/mock/mockgen -destination mocks/asset_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api AssetService 137 type AssetService interface { 138 GetByID(ctx context.Context, id string) (entities.Asset, error) 139 GetByTxHash(ctx context.Context, txHash entities.TxHash) ([]entities.Asset, error) 140 GetAll(ctx context.Context) ([]entities.Asset, error) 141 GetAllWithCursorPagination(ctx context.Context, pagination entities.CursorPagination) ([]entities.Asset, entities.PageInfo, error) 142 } 143 144 //go:generate go run github.com/golang/mock/mockgen -destination mocks/amm_service_mock.go -package mocks code.vegaprotocol.io/vega/datanode/api AMMService 145 type AMMService interface { 146 GetSubKeysForParties(ctx context.Context, partyIDs []string, marketIDs []string) ([]string, error) 147 ListAll(ctx context.Context, liveOnly bool, pagination entities.CursorPagination) ([]entities.AMMPool, entities.PageInfo, error) 148 ListByMarket(ctx context.Context, marketID string, liveOnly bool, pagination entities.CursorPagination) ([]entities.AMMPool, entities.PageInfo, error) 149 ListByParty(ctx context.Context, partyID string, liveOnly bool, pagination entities.CursorPagination) ([]entities.AMMPool, entities.PageInfo, error) 150 ListByPool(ctx context.Context, poolID string, liveOnly bool, pagination entities.CursorPagination) ([]entities.AMMPool, entities.PageInfo, error) 151 ListByStatus(ctx context.Context, status entities.AMMStatus, pagination entities.CursorPagination) ([]entities.AMMPool, entities.PageInfo, error) 152 ListBySubAccount(ctx context.Context, ammPartyID string, liveOnly bool, pagination entities.CursorPagination) ([]entities.AMMPool, entities.PageInfo, error) 153 ListByPartyMarketStatus(ctx context.Context, party, market *string, status *entities.AMMStatus, liveOnly bool, pagination entities.CursorPagination) ([]entities.AMMPool, entities.PageInfo, error) 154 } 155 156 type PartyStatsSvc interface { 157 GetPartyStats(ctx context.Context, partyID string, marketIDs []string) (*v2.GetPartyDiscountStatsResponse, error) 158 } 159 160 // GRPCServer represent the grpc api provided by the vega node. 161 type GRPCServer struct { 162 Config 163 log *logging.Logger 164 srv *grpc.Server 165 vegaCoreServiceClient CoreServiceClient 166 167 eventService *subscribers.Service 168 coreProxySvc *coreProxyService 169 orderService *service.Order 170 candleService *candlesv2.Svc 171 networkLimitsService *service.NetworkLimits 172 marketDataService *service.MarketData 173 tradeService *service.Trade 174 AssetService AssetService 175 accountService *service.Account 176 rewardService *service.Reward 177 marketsService *service.Markets 178 delegationService *service.Delegation 179 epochService *service.Epoch 180 depositService *service.Deposit 181 withdrawalService *service.Withdrawal 182 governanceService *service.Governance 183 riskFactorService *service.RiskFactor 184 riskService *service.Risk 185 networkParameterService *service.NetworkParameter 186 blockService BlockService 187 partyService *service.Party 188 checkpointService *service.Checkpoint 189 oracleSpecService *service.OracleSpec 190 oracleDataService *service.OracleData 191 liquidityProvisionService *service.LiquidityProvision 192 positionService *service.Position 193 transferService *service.Transfer 194 stakeLinkingService *service.StakeLinking 195 notaryService *service.Notary 196 multiSigService *service.MultiSig 197 keyRotationService *service.KeyRotations 198 ethereumKeyRotationService *service.EthereumKeyRotation 199 nodeService *service.Node 200 marketDepthService *service.MarketDepth 201 ledgerService *service.Ledger 202 protocolUpgradeService *service.ProtocolUpgrade 203 networkHistoryService NetworkHistoryService 204 coreSnapshotService *service.SnapshotData 205 stopOrderService *service.StopOrders 206 fundingPeriodService *service.FundingPeriods 207 partyActivityStreak *service.PartyActivityStreak 208 referralProgramService *service.ReferralPrograms 209 referralSetsService *service.ReferralSets 210 teamsService *service.Teams 211 vestingStatsService *service.VestingStats 212 FeesStatsService *service.FeesStats 213 fundingPaymentService *service.FundingPayment 214 volumeDiscountStatsService *service.VolumeDiscountStats 215 volumeDiscountProgramService *service.VolumeDiscountPrograms 216 paidLiquidityFeesStatsService *service.PaidLiquidityFeesStats 217 partyLockedBalances *service.PartyLockedBalances 218 partyVestingBalances *service.PartyVestingBalances 219 transactionResults *service.TransactionResults 220 gamesService *service.Games 221 marginModesService *service.MarginModes 222 timeWeightedNotionalPositionService *service.TimeWeightedNotionalPosition 223 gameScoreService *service.GameScore 224 ammPoolService *service.AMMPools 225 volumeRebateStatsService *service.VolumeRebateStats 226 volumeRebateProgramService *service.VolumeRebatePrograms 227 228 eventObserver *eventObserver 229 230 // used in order to gracefully close streams 231 ctx context.Context 232 cfunc context.CancelFunc 233 234 trustedProxies map[string]struct{} 235 } 236 237 // NewGRPCServer create a new instance of the GPRC api for the vega node. 238 func NewGRPCServer( 239 log *logging.Logger, 240 config Config, 241 coreServiceClient CoreServiceClient, 242 eventService *subscribers.Service, 243 orderService *service.Order, 244 networkLimitsService *service.NetworkLimits, 245 marketDataService *service.MarketData, 246 tradeService *service.Trade, 247 assetService *service.Asset, 248 accountService *service.Account, 249 rewardService *service.Reward, 250 marketsService *service.Markets, 251 delegationService *service.Delegation, 252 epochService *service.Epoch, 253 depositService *service.Deposit, 254 withdrawalService *service.Withdrawal, 255 governanceService *service.Governance, 256 riskFactorService *service.RiskFactor, 257 riskService *service.Risk, 258 networkParameterService *service.NetworkParameter, 259 blockService BlockService, 260 checkpointService *service.Checkpoint, 261 partyService *service.Party, 262 candleService *candlesv2.Svc, 263 oracleSpecService *service.OracleSpec, 264 oracleDataService *service.OracleData, 265 liquidityProvisionService *service.LiquidityProvision, 266 positionService *service.Position, 267 transferService *service.Transfer, 268 stakeLinkingService *service.StakeLinking, 269 notaryService *service.Notary, 270 multiSigService *service.MultiSig, 271 keyRotationService *service.KeyRotations, 272 ethereumKeyRotationService *service.EthereumKeyRotation, 273 nodeService *service.Node, 274 marketDepthService *service.MarketDepth, 275 ledgerService *service.Ledger, 276 protocolUpgradeService *service.ProtocolUpgrade, 277 networkHistoryService NetworkHistoryService, 278 coreSnapshotService *service.SnapshotData, 279 stopOrderService *service.StopOrders, 280 fundingPeriodService *service.FundingPeriods, 281 partyActivityStreak *service.PartyActivityStreak, 282 referralProgramService *service.ReferralPrograms, 283 referralSetsService *service.ReferralSets, 284 teamsService *service.Teams, 285 vestingStatsService *service.VestingStats, 286 FeesStatsService *service.FeesStats, 287 fundingPaymentService *service.FundingPayment, 288 volumeDiscountStatsService *service.VolumeDiscountStats, 289 volumeDiscountProgramService *service.VolumeDiscountPrograms, 290 paidLiquidityFeesStatsService *service.PaidLiquidityFeesStats, 291 partyLockedBalances *service.PartyLockedBalances, 292 partyVestingBalances *service.PartyVestingBalances, 293 transactionResults *service.TransactionResults, 294 gameService *service.Games, 295 marginModesService *service.MarginModes, 296 timeWeightedNotionalPositionService *service.TimeWeightedNotionalPosition, 297 gameScoreService *service.GameScore, 298 ammPoolService *service.AMMPools, 299 volumeRebateStatsService *service.VolumeRebateStats, 300 volumeRebateProgramsService *service.VolumeRebatePrograms, 301 ) *GRPCServer { 302 // setup logger 303 log = log.Named(namedLogger) 304 log.SetLevel(config.Level.Get()) 305 ctx, cfunc := context.WithCancel(context.Background()) 306 tps := make(map[string]struct{}, len(config.RateLimit.TrustedProxies)) 307 for _, ip := range config.RateLimit.TrustedProxies { 308 tps[ip] = struct{}{} 309 } 310 311 return &GRPCServer{ 312 log: log, 313 Config: config, 314 vegaCoreServiceClient: coreServiceClient, 315 eventService: eventService, 316 orderService: orderService, 317 networkLimitsService: networkLimitsService, 318 tradeService: tradeService, 319 AssetService: assetService, 320 accountService: accountService, 321 rewardService: rewardService, 322 marketsService: marketsService, 323 delegationService: delegationService, 324 epochService: epochService, 325 depositService: depositService, 326 withdrawalService: withdrawalService, 327 multiSigService: multiSigService, 328 governanceService: governanceService, 329 riskFactorService: riskFactorService, 330 networkParameterService: networkParameterService, 331 blockService: blockService, 332 checkpointService: checkpointService, 333 partyService: partyService, 334 candleService: candleService, 335 oracleSpecService: oracleSpecService, 336 oracleDataService: oracleDataService, 337 liquidityProvisionService: liquidityProvisionService, 338 positionService: positionService, 339 transferService: transferService, 340 stakeLinkingService: stakeLinkingService, 341 notaryService: notaryService, 342 keyRotationService: keyRotationService, 343 ethereumKeyRotationService: ethereumKeyRotationService, 344 nodeService: nodeService, 345 marketDepthService: marketDepthService, 346 riskService: riskService, 347 marketDataService: marketDataService, 348 ledgerService: ledgerService, 349 protocolUpgradeService: protocolUpgradeService, 350 networkHistoryService: networkHistoryService, 351 coreSnapshotService: coreSnapshotService, 352 stopOrderService: stopOrderService, 353 fundingPeriodService: fundingPeriodService, 354 partyActivityStreak: partyActivityStreak, 355 referralProgramService: referralProgramService, 356 referralSetsService: referralSetsService, 357 teamsService: teamsService, 358 vestingStatsService: vestingStatsService, 359 FeesStatsService: FeesStatsService, 360 fundingPaymentService: fundingPaymentService, 361 volumeDiscountStatsService: volumeDiscountStatsService, 362 volumeDiscountProgramService: volumeDiscountProgramService, 363 paidLiquidityFeesStatsService: paidLiquidityFeesStatsService, 364 partyLockedBalances: partyLockedBalances, 365 partyVestingBalances: partyVestingBalances, 366 transactionResults: transactionResults, 367 gamesService: gameService, 368 marginModesService: marginModesService, 369 timeWeightedNotionalPositionService: timeWeightedNotionalPositionService, 370 gameScoreService: gameScoreService, 371 ammPoolService: ammPoolService, 372 volumeRebateStatsService: volumeRebateStatsService, 373 volumeRebateProgramService: volumeRebateProgramsService, 374 eventObserver: &eventObserver{ 375 log: log, 376 eventService: eventService, 377 Config: config, 378 }, 379 ctx: ctx, 380 cfunc: cfunc, 381 trustedProxies: tps, 382 } 383 } 384 385 // ReloadConf update the internal configuration of the GRPC server. 386 func (g *GRPCServer) ReloadConf(cfg Config) { 387 g.log.Info("reloading configuration") 388 if g.log.GetLevel() != cfg.Level.Get() { 389 g.log.Info("updating log level", 390 logging.String("old", g.log.GetLevel().String()), 391 logging.String("new", cfg.Level.String()), 392 ) 393 g.log.SetLevel(cfg.Level.Get()) 394 } 395 tps := make(map[string]struct{}, len(cfg.RateLimit.TrustedProxies)) 396 for _, ip := range cfg.RateLimit.TrustedProxies { 397 tps[ip] = struct{}{} 398 } 399 400 // TODO(): not updating the actual server for now, may need to look at this later 401 // e.g restart the http server on another port or whatever 402 g.Config = cfg 403 g.trustedProxies = tps 404 } 405 406 func (g *GRPCServer) ipFromContext(ctx context.Context, method string, log *logging.Logger) (string, error) { 407 // first check if the request is forwarded from our restproxy 408 tps := g.trustedProxies 409 if len(tps) > 0 { 410 // get the metadata 411 if md, ok := metadata.FromIncomingContext(ctx); ok { 412 // if trusted proxies are specified, the XFF header will be used to rate-limit the IP 413 // for which the request is forwarded. If no proxies are specified, or no trusted proxies 414 // are found, the peer is rate limited. 415 if forwardedFor, ok := md["x-forwarded-for"]; ok && len(forwardedFor) >= 2 { 416 // check the proxies for trusted 417 for _, pip := range forwardedFor[1:] { 418 // trusted proxy found, return 419 if _, ok := tps[pip]; ok { 420 log.Debug("grpc request x-forwarded-for", 421 logging.String("method", method), 422 logging.String("remote-ip-addr", forwardedFor[0]), 423 ) 424 return forwardedFor[0], nil 425 } 426 } 427 } 428 } 429 } 430 431 // if the request is not forwarded let's get it from the peer infos 432 p, ok := peer.FromContext(ctx) 433 if ok && p != nil { 434 log.Debug("grpc peer client request", 435 logging.String("method", method), 436 logging.String("remote-ip-addr", p.Addr.String())) 437 return p.Addr.String(), nil 438 } 439 440 return "", nil 441 } 442 443 func (g *GRPCServer) remoteAddrInterceptor(log *logging.Logger) grpc.UnaryServerInterceptor { 444 return func( 445 ctx context.Context, 446 req interface{}, 447 info *grpc.UnaryServerInfo, 448 handler grpc.UnaryHandler, 449 ) (resp interface{}, err error) { 450 ip, err := g.ipFromContext(ctx, info.FullMethod, log) 451 if err != nil { 452 return nil, status.Error(codes.PermissionDenied, err.Error()) 453 } 454 455 ctx = contextutil.WithRemoteIPAddr(ctx, ip) 456 457 // Calls the handler 458 h, err := handler(ctx, req) 459 460 log.Debug("Invoked RPC call", 461 logging.String("method", info.FullMethod), 462 logging.Error(err), 463 ) 464 465 return h, err 466 } 467 } 468 469 func headersInterceptor( 470 getLastBlock func(context.Context) (entities.Block, error), 471 log *logging.Logger, 472 ) grpc.UnaryServerInterceptor { 473 return func( 474 ctx context.Context, 475 req interface{}, 476 info *grpc.UnaryServerInfo, 477 handler grpc.UnaryHandler, 478 ) (interface{}, error) { 479 var ( 480 height int64 481 timestamp int64 482 ) 483 484 block, bErr := getLastBlock(ctx) 485 if bErr != nil { 486 log.Debug("failed to get last block", logging.Error(bErr)) 487 } else { 488 height = block.Height 489 timestamp = block.VegaTime.UnixNano() 490 } 491 492 for _, h := range []metadata.MD{ 493 // Deprecated: use 'X-Block-Height' and 'X-Block-Timestamp' instead to determine if data is fresh. 494 metadata.Pairs("X-Block-Height", strconv.FormatInt(height, 10)), 495 metadata.Pairs("X-Block-Timestamp", strconv.FormatInt(timestamp, 10)), 496 } { 497 if errH := grpc.SetHeader(ctx, h); errH != nil { 498 log.Error("failed to set header", logging.Error(errH)) 499 } 500 } 501 502 return handler(ctx, req) 503 } 504 } 505 506 func (g *GRPCServer) getTCPListener() (net.Listener, error) { 507 ip := g.IP 508 port := strconv.Itoa(g.Port) 509 510 g.log.Info("Starting gRPC based API", logging.String("addr", ip), logging.String("port", port)) 511 512 tpcLis, err := net.Listen("tcp", net.JoinHostPort(ip, port)) 513 if err != nil { 514 return nil, err 515 } 516 517 return tpcLis, nil 518 } 519 520 // Start starts the grpc server. 521 // Uses default TCP listener if no provided. 522 func (g *GRPCServer) Start(ctx context.Context, lis net.Listener) error { 523 if lis == nil { 524 tpcLis, err := g.getTCPListener() 525 if err != nil { 526 return err 527 } 528 529 lis = tpcLis 530 } 531 532 subscriptionRateLimiter := gateway.NewSubscriptionRateLimiter(g.log, g.Config.MaxSubscriptionPerClient) 533 534 rateLimit := ratelimit.NewFromConfig(&g.RateLimit, g.log) 535 intercept := grpc.ChainUnaryInterceptor( 536 g.remoteAddrInterceptor(g.log), 537 headersInterceptor(g.blockService.GetLastBlock, g.log), 538 rateLimit.GRPCInterceptor, 539 ) 540 541 streamIntercept := grpc.StreamInterceptor(subscriptionRateLimiter.WithGrpcInterceptor(g.ipFromContext)) 542 partyDiscountStats := service.NewPartyStatsService(g.epochService, 543 g.referralSetsService.ReferralSets, 544 g.volumeDiscountStatsService, 545 g.volumeRebateStatsService, 546 g.marketsService, 547 g.referralProgramService.ReferralPrograms, 548 g.volumeDiscountProgramService.VolumeDiscountPrograms, 549 g.volumeRebateProgramService.VolumeRebatePrograms, 550 ) 551 552 g.srv = grpc.NewServer(intercept, streamIntercept) 553 554 coreProxySvc := &coreProxyService{ 555 conf: g.Config, 556 coreServiceClient: g.vegaCoreServiceClient, 557 eventObserver: g.eventObserver, 558 } 559 g.coreProxySvc = coreProxySvc 560 vegaprotoapi.RegisterCoreServiceServer(g.srv, coreProxySvc) 561 562 tradingDataSvcV2 := &TradingDataServiceV2{ 563 config: g.Config, 564 log: g.log, 565 orderService: g.orderService, 566 networkLimitsService: g.networkLimitsService, 567 MarketDataService: g.marketDataService, 568 tradeService: g.tradeService, 569 multiSigService: g.multiSigService, 570 notaryService: g.notaryService, 571 AssetService: g.AssetService, 572 candleService: g.candleService, 573 MarketsService: g.marketsService, 574 575 partyService: g.partyService, 576 riskService: g.riskService, 577 positionService: g.positionService, 578 AccountService: g.accountService, 579 RewardService: g.rewardService, 580 depositService: g.depositService, 581 withdrawalService: g.withdrawalService, 582 oracleSpecService: g.oracleSpecService, 583 oracleDataService: g.oracleDataService, 584 liquidityProvisionService: g.liquidityProvisionService, 585 governanceService: g.governanceService, 586 transfersService: g.transferService, 587 delegationService: g.delegationService, 588 marketDepthService: g.marketDepthService, 589 nodeService: g.nodeService, 590 EpochService: g.epochService, 591 RiskFactorService: g.riskFactorService, 592 networkParameterService: g.networkParameterService, 593 checkpointService: g.checkpointService, 594 stakeLinkingService: g.stakeLinkingService, 595 eventService: g.eventService, 596 ledgerService: g.ledgerService, 597 keyRotationService: g.keyRotationService, 598 ethereumKeyRotationService: g.ethereumKeyRotationService, 599 blockService: g.blockService, 600 protocolUpgradeService: g.protocolUpgradeService, 601 NetworkHistoryService: g.networkHistoryService, 602 coreSnapshotService: g.coreSnapshotService, 603 stopOrderService: g.stopOrderService, 604 fundingPeriodService: g.fundingPeriodService, 605 partyActivityStreak: g.partyActivityStreak, 606 referralProgramService: g.referralProgramService, 607 ReferralSetsService: g.referralSetsService, 608 teamsService: g.teamsService, 609 feesStatsService: g.FeesStatsService, 610 fundingPaymentService: g.fundingPaymentService, 611 VolumeDiscountStatsService: g.volumeDiscountStatsService, 612 volumeDiscountProgramService: g.volumeDiscountProgramService, 613 paidLiquidityFeesStatsService: g.paidLiquidityFeesStatsService, 614 partyLockedBalances: g.partyLockedBalances, 615 partyVestingBalances: g.partyVestingBalances, 616 vestingStats: g.vestingStatsService, 617 transactionResults: g.transactionResults, 618 gamesService: g.gamesService, 619 marginModesService: g.marginModesService, 620 twNotionalPositionService: g.timeWeightedNotionalPositionService, 621 gameScoreService: g.gameScoreService, 622 AMMPoolService: g.ammPoolService, 623 volumeRebateStatsService: g.volumeRebateStatsService, 624 volumeRebateProgramService: g.volumeRebateProgramService, 625 partyDiscountStats: partyDiscountStats, 626 } 627 628 protoapi.RegisterTradingDataServiceServer(g.srv, tradingDataSvcV2) 629 630 eg, ctx := errgroup.WithContext(ctx) 631 632 if g.Reflection || g.WebUIEnabled { 633 reflection.Register(g.srv) 634 } 635 636 eg.Go(func() error { 637 <-ctx.Done() 638 g.stop() 639 return ctx.Err() 640 }) 641 642 eg.Go(func() error { 643 return g.srv.Serve(lis) 644 }) 645 646 if g.WebUIEnabled { 647 g.startWebUI(ctx) 648 } 649 650 return eg.Wait() 651 } 652 653 func (g *GRPCServer) stop() { 654 if g.srv == nil { 655 return 656 } 657 658 done := make(chan struct{}) 659 go func() { 660 g.log.Info("Gracefully stopping gRPC based API") 661 g.srv.GracefulStop() 662 done <- struct{}{} 663 }() 664 665 select { 666 case <-done: 667 case <-time.After(10 * time.Second): 668 g.log.Info("Force stopping gRPC based API") 669 g.srv.Stop() 670 } 671 } 672 673 func (g *GRPCServer) startWebUI(ctx context.Context) { 674 cc, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", g.Port), grpc.WithInsecure()) 675 if err != nil { 676 g.log.Error("failed to create client to local grpc server", logging.Error(err)) 677 return 678 } 679 680 uiHandler, err := standalone.HandlerViaReflection(ctx, cc, "vega data node") 681 if err != nil { 682 g.log.Error("failed to create grpc-ui server", logging.Error(err)) 683 return 684 } 685 686 uiListener, err := net.Listen("tcp", net.JoinHostPort(g.IP, strconv.Itoa(g.WebUIPort))) 687 if err != nil { 688 g.log.Error("failed to open listen socket on port", logging.Int("port", g.WebUIPort), logging.Error(err)) 689 return 690 } 691 692 g.log.Info("Starting gRPC Web UI", logging.String("addr", g.IP), logging.Int("port", g.WebUIPort)) 693 go http.Serve(uiListener, uiHandler) 694 }