github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/tequilapi/endpoints/node.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 endpoints 19 20 import ( 21 "math/big" 22 "net/http" 23 "strconv" 24 25 "github.com/gin-gonic/gin" 26 "github.com/rs/zerolog/log" 27 28 "github.com/mysteriumnetwork/go-rest/apierror" 29 "github.com/mysteriumnetwork/payments/units" 30 31 "github.com/mysteriumnetwork/node/core/node" 32 "github.com/mysteriumnetwork/node/tequilapi/contract" 33 "github.com/mysteriumnetwork/node/tequilapi/launchpad" 34 "github.com/mysteriumnetwork/node/tequilapi/utils" 35 ) 36 37 type nodeMonitoringAgent interface { 38 Statuses() (node.MonitoringAgentStatuses, error) 39 Sessions(rangeTime string) ([]node.SessionItem, error) 40 TransferredData(rangeTime string) (node.TransferredData, error) 41 SessionsCount(rangeTime string) (node.SessionsCount, error) 42 ConsumersCount(rangeTime string) (node.ConsumersCount, error) 43 EarningsSeries(rangeTime string) (node.EarningsSeries, error) 44 SessionsSeries(rangeTime string) (node.SessionsSeries, error) 45 TransferredDataSeries(rangeTime string) (node.TransferredDataSeries, error) 46 ProviderActivityStats() (node.ActivityStats, error) 47 ProviderQuality() (node.QualityInfo, error) 48 EarningsPerService() (node.EarningsPerService, error) 49 } 50 51 // NodeEndpoint struct represents endpoints about node status 52 type NodeEndpoint struct { 53 nodeStatusProvider nodeStatusProvider 54 nodeMonitoringAgent nodeMonitoringAgent 55 launchpadAPI *launchpad.API 56 } 57 58 // NewNodeEndpoint creates and returns node endpoints 59 func NewNodeEndpoint(nodeStatusProvider nodeStatusProvider, nodeMonitoringAgent nodeMonitoringAgent) *NodeEndpoint { 60 return &NodeEndpoint{ 61 nodeStatusProvider: nodeStatusProvider, 62 nodeMonitoringAgent: nodeMonitoringAgent, 63 launchpadAPI: launchpad.New(), 64 } 65 } 66 67 // NodeStatus Status provides Node proposal status 68 // swagger:operation GET /node/monitoring-status provider NodeStatus 69 // 70 // --- 71 // summary: Provides Node proposal status 72 // description: Node Status as seen by monitoring agent 73 // responses: 74 // 200: 75 // description: Node status ("passed"/"failed"/"pending) 76 // schema: 77 // "$ref": "#/definitions/NodeStatusResponse" 78 func (ne *NodeEndpoint) NodeStatus(c *gin.Context) { 79 utils.WriteAsJSON(contract.NodeStatusResponse{Status: ne.nodeStatusProvider.Status()}, c.Writer) 80 } 81 82 // MonitoringAgentStatuses Statuses from monitoring agent 83 // swagger:operation GET /node/monitoring-agent-statuses provider MonitoringAgentStatuses 84 // 85 // --- 86 // summary: Provides Node connectivity statuses from monitoring agent 87 // description: Node connectivity statuses as seen by monitoring agent 88 // responses: 89 // 200: 90 // description: Monitoring agent statuses ("success"/"cancelled"/"connect_drop/"connect_fail/"internet_fail) 91 // schema: 92 // "$ref": "#/definitions/MonitoringAgentResponse" 93 func (ne *NodeEndpoint) MonitoringAgentStatuses(c *gin.Context) { 94 res, err := ne.nodeMonitoringAgent.Statuses() 95 if err != nil { 96 utils.WriteAsJSON(contract.MonitoringAgentResponse{Error: err.Error()}, c.Writer, http.StatusInternalServerError) 97 return 98 } 99 100 utils.WriteAsJSON(contract.MonitoringAgentResponse{Statuses: res}, c.Writer) 101 } 102 103 // GetProviderSessions A list of sessions metrics during a period of time 104 // swagger:operation GET /node/provider/sessions provider GetProviderSessions 105 // 106 // --- 107 // summary: Provides Node sessions data during a period of time 108 // description: Node sessions metrics during a period of time 109 // parameters: 110 // - in: query 111 // name: range 112 // description: period of time ("1d", "7d", "30d") 113 // type: string 114 // responses: 115 // 200: 116 // description: Provider sessions list 117 // schema: 118 // "$ref": "#/definitions/ProviderSessionsResponse" 119 // 400: 120 // description: Failed to parse or request validation failed 121 // schema: 122 // "$ref": "#/definitions/APIError" 123 // 500: 124 // description: Internal server error 125 // schema: 126 // "$ref": "#/definitions/APIError" 127 func (ne *NodeEndpoint) GetProviderSessions(c *gin.Context) { 128 rangeTime := c.Query("range") 129 130 switch rangeTime { 131 case "1d", "7d", "30d": 132 default: 133 c.Error(apierror.BadRequest("Invalid time range", contract.ErrorCodeProviderSessions)) 134 return 135 } 136 137 res, err := ne.nodeMonitoringAgent.Sessions(rangeTime) 138 if err != nil { 139 c.Error(apierror.Internal("Could not get provider sessions list: "+err.Error(), contract.ErrorCodeProviderSessions)) 140 return 141 } 142 143 utils.WriteAsJSON(contract.NewProviderSessionsResponse(res), c.Writer) 144 } 145 146 // GetProviderTransferredData A number of bytes transferred during a period of time 147 // swagger:operation GET /node/provider/transferred-data provider GetProviderTransferredData 148 // 149 // --- 150 // summary: Provides total traffic served by the provider during a period of time 151 // description: Node transferred data during a period of time 152 // parameters: 153 // - in: query 154 // name: range 155 // description: period of time ("1d", "7d", "30d") 156 // type: string 157 // responses: 158 // 200: 159 // description: Provider transferred data 160 // schema: 161 // "$ref": "#/definitions/ProviderTransferredDataResponse" 162 // 400: 163 // description: Failed to parse or request validation failed 164 // schema: 165 // "$ref": "#/definitions/APIError" 166 // 500: 167 // description: Internal server error 168 // schema: 169 // "$ref": "#/definitions/APIError" 170 func (ne *NodeEndpoint) GetProviderTransferredData(c *gin.Context) { 171 rangeTime := c.Query("range") 172 173 switch rangeTime { 174 case "1d", "7d", "30d": 175 default: 176 c.Error(apierror.BadRequest("Invalid time range", contract.ErrorCodeProviderTransferredData)) 177 return 178 } 179 180 res, err := ne.nodeMonitoringAgent.TransferredData(rangeTime) 181 if err != nil { 182 c.Error(apierror.Internal("Could not get provider transferred data: "+err.Error(), contract.ErrorCodeProviderTransferredData)) 183 return 184 } 185 186 utils.WriteAsJSON(contract.ProviderTransferredDataResponse{Bytes: res.Bytes}, c.Writer) 187 } 188 189 // GetProviderSessionsCount A number of sessions during a period of time 190 // swagger:operation GET /node/provider/sessions-count provider GetProviderSessionsCount 191 // 192 // --- 193 // summary: Provides Node sessions number during a period of time 194 // description: Node sessions count during a period of time 195 // parameters: 196 // - in: query 197 // name: range 198 // description: period of time ("1d", "7d", "30d") 199 // type: string 200 // responses: 201 // 200: 202 // description: Provider sessions count 203 // schema: 204 // "$ref": "#/definitions/ProviderSessionsCountResponse" 205 // 400: 206 // description: Failed to parse or request validation failed 207 // schema: 208 // "$ref": "#/definitions/APIError" 209 // 500: 210 // description: Internal server error 211 // schema: 212 // "$ref": "#/definitions/APIError" 213 func (ne *NodeEndpoint) GetProviderSessionsCount(c *gin.Context) { 214 rangeTime := c.Query("range") 215 216 switch rangeTime { 217 case "1d", "7d", "30d": 218 default: 219 c.Error(apierror.BadRequest("Invalid time range", contract.ErrorCodeProviderSessionsCount)) 220 return 221 } 222 223 res, err := ne.nodeMonitoringAgent.SessionsCount(rangeTime) 224 if err != nil { 225 c.Error(apierror.Internal("Could not get provider sessions count: "+err.Error(), contract.ErrorCodeProviderSessionsCount)) 226 return 227 } 228 229 utils.WriteAsJSON(contract.ProviderSessionsCountResponse{Count: res.Count}, c.Writer) 230 } 231 232 // GetProviderConsumersCount A number of consumers served during a period of time 233 // swagger:operation GET /node/provider/consumers-count provider GetProviderConsumersCount 234 // 235 // --- 236 // summary: Provides Node consumers number served during a period of time 237 // description: Node unique consumers count served during a period of time. 238 // parameters: 239 // - in: query 240 // name: range 241 // description: period of time ("1d", "7d", "30d") 242 // type: string 243 // responses: 244 // 200: 245 // description: Provider consumers count 246 // schema: 247 // "$ref": "#/definitions/ProviderConsumersCountResponse" 248 // 400: 249 // description: Failed to parse or request validation failed 250 // schema: 251 // "$ref": "#/definitions/APIError" 252 // 500: 253 // description: Internal server error 254 // schema: 255 // "$ref": "#/definitions/APIError" 256 func (ne *NodeEndpoint) GetProviderConsumersCount(c *gin.Context) { 257 rangeTime := c.Query("range") 258 259 switch rangeTime { 260 case "1d", "7d", "30d": 261 default: 262 c.Error(apierror.BadRequest("Invalid time range", contract.ErrorCodeProviderConsumersCount)) 263 return 264 } 265 266 res, err := ne.nodeMonitoringAgent.ConsumersCount(rangeTime) 267 if err != nil { 268 c.Error(apierror.Internal("Could not get provider consumers count: "+err.Error(), contract.ErrorCodeProviderConsumersCount)) 269 return 270 } 271 272 utils.WriteAsJSON(contract.ProviderConsumersCountResponse{Count: res.Count}, c.Writer) 273 } 274 275 // GetProviderEarningsSeries A time series metrics of earnings during a period of time 276 // swagger:operation GET /node/provider/series/earnings provider GetProviderEarningsSeries 277 // 278 // --- 279 // summary: Provides Node time series metrics of earnings during a period of time 280 // description: Node time series metrics of earnings during a period of time. 281 // parameters: 282 // - in: query 283 // name: range 284 // description: period of time ("1d", "7d", "30d") 285 // type: string 286 // responses: 287 // 200: 288 // description: Provider time series metrics of MYSTT earnings 289 // schema: 290 // "$ref": "#/definitions/ProviderEarningsSeriesResponse" 291 // 400: 292 // description: Failed to parse or request validation failed 293 // schema: 294 // "$ref": "#/definitions/APIError" 295 // 500: 296 // description: Internal server error 297 // schema: 298 // "$ref": "#/definitions/APIError" 299 func (ne *NodeEndpoint) GetProviderEarningsSeries(c *gin.Context) { 300 rangeTime := c.Query("range") 301 302 switch rangeTime { 303 case "1d", "7d", "30d": 304 default: 305 c.Error(apierror.BadRequest("Invalid time range", contract.ErrorCodeProviderEarningsSeries)) 306 return 307 } 308 309 res, err := ne.nodeMonitoringAgent.EarningsSeries(rangeTime) 310 if err != nil { 311 c.Error(apierror.Internal("Could not get provider earnings series: "+err.Error(), contract.ErrorCodeProviderEarningsSeries)) 312 return 313 } 314 315 utils.WriteAsJSON(res, c.Writer) 316 } 317 318 // GetProviderSessionsSeries A time series metrics of sessions started during a period of time 319 // swagger:operation GET /node/provider/series/sessions provider GetProviderSessionsSeries 320 // 321 // --- 322 // summary: Provides Node data series metrics of sessions started during a period of time 323 // description: Node time series metrics of sessions started during a period of time. 324 // parameters: 325 // - in: query 326 // name: range 327 // description: period of time ("1d", "7d", "30d") 328 // type: string 329 // responses: 330 // 200: 331 // description: Provider time series metrics of started sessions 332 // schema: 333 // "$ref": "#/definitions/ProviderSessionsSeriesResponse" 334 // 400: 335 // description: Failed to parse or request validation failed 336 // schema: 337 // "$ref": "#/definitions/APIError" 338 // 500: 339 // description: Internal server error 340 // schema: 341 // "$ref": "#/definitions/APIError" 342 func (ne *NodeEndpoint) GetProviderSessionsSeries(c *gin.Context) { 343 rangeTime := c.Query("range") 344 345 switch rangeTime { 346 case "1d", "7d", "30d": 347 default: 348 c.Error(apierror.BadRequest("Invalid time range", contract.ErrorCodeProviderSessionsSeries)) 349 return 350 } 351 352 res, err := ne.nodeMonitoringAgent.SessionsSeries(rangeTime) 353 if err != nil { 354 c.Error(apierror.Internal("Could not get provider sessions series: "+err.Error(), contract.ErrorCodeProviderSessionsSeries)) 355 return 356 } 357 358 utils.WriteAsJSON(res, c.Writer) 359 } 360 361 // GetProviderTransferredDataSeries A time series metrics of transferred bytes during a period of time 362 // swagger:operation GET /node/provider/series/data provider GetProviderTransferredDataSeries 363 // 364 // --- 365 // summary: Provides Node data series metrics of transferred bytes 366 // description: Node data series metrics of transferred bytes during a period of time. 367 // parameters: 368 // - in: query 369 // name: range 370 // description: period of time ("1d", "7d", "30d") 371 // type: string 372 // responses: 373 // 200: 374 // description: Provider time series metrics of transferred bytes 375 // schema: 376 // "$ref": "#/definitions/ProviderTransferredDataSeriesResponse" 377 // 400: 378 // description: Failed to parse or request validation failed 379 // schema: 380 // "$ref": "#/definitions/APIError" 381 // 500: 382 // description: Internal server error 383 // schema: 384 // "$ref": "#/definitions/APIError" 385 func (ne *NodeEndpoint) GetProviderTransferredDataSeries(c *gin.Context) { 386 rangeTime := c.Query("range") 387 388 switch rangeTime { 389 case "1d", "7d", "30d": 390 default: 391 c.Error(apierror.BadRequest("Invalid time range", contract.ErrorCodeProviderTransferredDataSeries)) 392 return 393 } 394 395 res, err := ne.nodeMonitoringAgent.TransferredDataSeries(rangeTime) 396 if err != nil { 397 c.Error(apierror.Internal("Could not get provider transferred data series: "+err.Error(), contract.ErrorCodeProviderTransferredDataSeries)) 398 return 399 } 400 401 utils.WriteAsJSON(res, c.Writer) 402 } 403 404 // GetProviderQuality a quality of provider 405 // swagger:operation GET /node/provider/quality provider GetProviderQuality 406 // 407 // --- 408 // summary: Provides Node quality 409 // description: Node connectivity quality 410 // responses: 411 // 200: 412 // description: Provider quality 413 // schema: 414 // "$ref": "#/definitions/QualityInfoResponse" 415 // 400: 416 // description: Failed to parse or request validation failed 417 // schema: 418 // "$ref": "#/definitions/APIError" 419 // 500: 420 // description: Internal server error 421 // schema: 422 // "$ref": "#/definitions/APIError" 423 func (ne *NodeEndpoint) GetProviderQuality(c *gin.Context) { 424 res, err := ne.nodeMonitoringAgent.ProviderQuality() 425 if err != nil { 426 c.Error(apierror.Internal("Could not get provider quality: "+err.Error(), contract.ErrorCodeProviderQuality)) 427 return 428 } 429 430 utils.WriteAsJSON(res, c.Writer) 431 } 432 433 // GetProviderActivityStats is an activity stats of provider 434 // swagger:operation GET /node/provider/activity-stats provider GetProviderActivityStats 435 // 436 // --- 437 // summary: Provides Node activity stats 438 // description: Node activity stats 439 // responses: 440 // 200: 441 // description: Provider activity stats 442 // schema: 443 // "$ref": "#/definitions/ActivityStatsResponse" 444 // 400: 445 // description: Failed to parse or request validation failed 446 // schema: 447 // "$ref": "#/definitions/APIError" 448 // 500: 449 // description: Internal server error 450 // schema: 451 // "$ref": "#/definitions/APIError" 452 func (ne *NodeEndpoint) GetProviderActivityStats(c *gin.Context) { 453 454 res, err := ne.nodeMonitoringAgent.ProviderActivityStats() 455 if err != nil { 456 c.Error(apierror.Internal("Could not get provider activity stats: "+err.Error(), contract.ErrorCodeProviderActivityStats)) 457 return 458 } 459 460 utils.WriteAsJSON(res, c.Writer) 461 } 462 463 // GetLatestRelease retrieves information about the latest node release 464 // swagger:operation GET /node/latest-release node GetLatestRelease 465 // 466 // --- 467 // summary: Latest Node release information 468 // description: Checks for latest Node release package and retrieves its information 469 // responses: 470 // 200: 471 // description: Latest Node release information 472 // schema: 473 // "$ref": "#/definitions/LatestReleaseResponse" 474 // 500: 475 // description: Failed to retrieve latest Node release information 476 // schema: 477 // "$ref": "#/definitions/APIError" 478 func (ne *NodeEndpoint) GetLatestRelease(c *gin.Context) { 479 version, err := ne.launchpadAPI.LatestPublishedReleaseVersion() 480 if err != nil { 481 c.Error(apierror.Internal("Could not fetch latest release information", contract.ErrorCodeLatestReleaseInformation)) 482 log.Error().Err(err).Msg("Could not fetch latest release information") 483 return 484 } 485 486 utils.WriteAsJSON(contract.LatestReleaseResponse{Version: version}, c.Writer) 487 } 488 489 // GetProviderServiceEarnings Node earnings per service and total earnings in the all network 490 // swagger:operation GET /node/provider/service-earnings provider GetProviderServiceEarnings 491 // 492 // --- 493 // summary: Provides Node earnings per service and total earnings in the all network 494 // description: Node earnings per service and total earnings in the all network. 495 // responses: 496 // 200: 497 // description: earnings per service and total earnings 498 // schema: 499 // "$ref": "#/definitions/EarningsPerServiceResponse" 500 // 400: 501 // description: Failed to parse or request validation failed 502 // schema: 503 // "$ref": "#/definitions/APIError" 504 // 500: 505 // description: Internal server error 506 // schema: 507 // "$ref": "#/definitions/APIError" 508 func (ne *NodeEndpoint) GetProviderServiceEarnings(c *gin.Context) { 509 res, err := ne.nodeMonitoringAgent.EarningsPerService() 510 if err != nil { 511 c.Error(apierror.Internal("Could not get provider service earnings: "+err.Error(), contract.ErrorCodeProviderServiceEarnings)) 512 return 513 } 514 public, _ := strconv.ParseFloat(res.EarningsPublic, 64) 515 vpn, _ := strconv.ParseFloat(res.EarningsVPN, 64) 516 scraping, _ := strconv.ParseFloat(res.EarningsScraping, 64) 517 dvpn, _ := strconv.ParseFloat(res.EarningsDVPN, 64) 518 519 totalPublic, _ := strconv.ParseFloat(res.TotalEarningsPublic, 64) 520 totalVPN, _ := strconv.ParseFloat(res.TotalEarningsVPN, 64) 521 totalScraping, _ := strconv.ParseFloat(res.TotalEarningsScraping, 64) 522 totalDVPN, _ := strconv.ParseFloat(res.TotalEarningsDVPN, 64) 523 524 publicTokens := units.FloatEthToBigIntWei(public) 525 vpnTokens := units.FloatEthToBigIntWei(vpn) 526 scrapingTokens := units.FloatEthToBigIntWei(scraping) 527 dvpnTokens := units.FloatEthToBigIntWei(dvpn) 528 529 totalPublicTokens := units.FloatEthToBigIntWei(totalPublic) 530 totalVPNTokens := units.FloatEthToBigIntWei(totalVPN) 531 totalScrapingTokens := units.FloatEthToBigIntWei(totalScraping) 532 totalDVPNTokens := units.FloatEthToBigIntWei(totalDVPN) 533 534 totalTokens := new(big.Int) 535 totalTokens.Add(publicTokens, vpnTokens) 536 totalTokens.Add(totalTokens, scrapingTokens) 537 totalTokens.Add(totalTokens, dvpnTokens) 538 539 data := contract.EarningsPerServiceResponse{ 540 EarningsPublic: contract.NewTokens(publicTokens), 541 EarningsVPN: contract.NewTokens(vpnTokens), 542 EarningsScraping: contract.NewTokens(scrapingTokens), 543 EarningsDVPN: contract.NewTokens(dvpnTokens), 544 EarningsTotal: contract.NewTokens(totalTokens), 545 TotalEarningsPublic: contract.NewTokens(totalPublicTokens), 546 TotalEarningsVPN: contract.NewTokens(totalVPNTokens), 547 TotalEarningsScraping: contract.NewTokens(totalScrapingTokens), 548 TotalEarningsDVPN: contract.NewTokens(totalDVPNTokens), 549 } 550 551 utils.WriteAsJSON(data, c.Writer) 552 } 553 554 // AddRoutesForNode adds nat routes to given router 555 func AddRoutesForNode(nodeStatusProvider nodeStatusProvider, nodeMonitoringAgent nodeMonitoringAgent) func(*gin.Engine) error { 556 nodeEndpoints := NewNodeEndpoint(nodeStatusProvider, nodeMonitoringAgent) 557 558 return func(e *gin.Engine) error { 559 nodeGroup := e.Group("/node") 560 { 561 nodeGroup.GET("/monitoring-status", nodeEndpoints.NodeStatus) 562 nodeGroup.GET("/monitoring-agent-statuses", nodeEndpoints.MonitoringAgentStatuses) 563 nodeGroup.GET("/provider/sessions", nodeEndpoints.GetProviderSessions) 564 nodeGroup.GET("/provider/transferred-data", nodeEndpoints.GetProviderTransferredData) 565 nodeGroup.GET("/provider/sessions-count", nodeEndpoints.GetProviderSessionsCount) 566 nodeGroup.GET("/provider/consumers-count", nodeEndpoints.GetProviderConsumersCount) 567 nodeGroup.GET("/provider/series/earnings", nodeEndpoints.GetProviderEarningsSeries) 568 nodeGroup.GET("/provider/series/sessions", nodeEndpoints.GetProviderSessionsSeries) 569 nodeGroup.GET("/provider/series/data", nodeEndpoints.GetProviderTransferredDataSeries) 570 nodeGroup.GET("/provider/service-earnings", nodeEndpoints.GetProviderServiceEarnings) 571 nodeGroup.GET("/latest-release", nodeEndpoints.GetLatestRelease) 572 nodeGroup.GET("/provider/quality", nodeEndpoints.GetProviderQuality) 573 nodeGroup.GET("/provider/activity-stats", nodeEndpoints.GetProviderActivityStats) 574 } 575 return nil 576 } 577 }