|
@@ -0,0 +1,327 @@
|
|
|
|
+package main
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "fmt"
|
|
|
|
+ "math"
|
|
|
|
+ "strings"
|
|
|
|
+
|
|
|
|
+ tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+func (c *Connection) UpdateData() {
|
|
|
|
+ LogInfo.Println("Updating data!")
|
|
|
|
+ // Getting list of unique wallets in user table
|
|
|
|
+ var walletList []string
|
|
|
|
+ result := c.GormDb.Model(&User{}).
|
|
|
|
+ Not("wallet = ?", "").
|
|
|
|
+ Select("DISTINCT(wallet)").
|
|
|
|
+ Scan(&walletList)
|
|
|
|
+
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for _, wallet := range walletList {
|
|
|
|
+ c.UpdateWallet(wallet)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (c *Connection) UpdateWallet(wallet string) {
|
|
|
|
+ LogInfo.Printf(">> Getting data for wallet %s\n", wallet)
|
|
|
|
+
|
|
|
|
+ url := fmt.Sprintf("%s/miner/%s", appSettings.ApiUrl, wallet)
|
|
|
|
+ LogInfo.Print("From: " + url)
|
|
|
|
+
|
|
|
|
+ currentStats, err := MinerStats(url)
|
|
|
|
+
|
|
|
|
+ if err != nil {
|
|
|
|
+ if strings.Contains(err.Error(), "No data for miner") {
|
|
|
|
+ LogInfo.Println("No currentStats data for miner")
|
|
|
|
+ } else {
|
|
|
|
+ LogError.Println(err)
|
|
|
|
+ }
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if currentStats.Status == "OK" {
|
|
|
|
+ if currentStats.Data == (JsonCurrentStats{}).Data {
|
|
|
|
+ // if fmt.Sprintf("%T", currentStats.(map[string]interface{})["data"]) != "map[string]interface {}" {
|
|
|
|
+ LogInfo.Printf("data in response from %s for wallet %s not an interface!\n", appSettings.ApiUrl, wallet)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ // data := currentStats.(map[string]interface{})["data"].(map[string]interface{})
|
|
|
|
+ LogInfo.Printf("Creating new record for miner %s, time %d\n", wallet, currentStats.Data.Time)
|
|
|
|
+ // Line 28 of UpdateData.cs
|
|
|
|
+ // NOTE: No use for creating new record here
|
|
|
|
+ var newMinerRecord Miner
|
|
|
|
+ newMinerRecord.Wallet = wallet
|
|
|
|
+ newMinerRecord.Time = currentStats.Data.Time
|
|
|
|
+ newMinerRecord.ReportedHashrate = currentStats.Data.ReportedHashrate
|
|
|
|
+ newMinerRecord.CurrentHashrate = currentStats.Data.CurrentHashrate
|
|
|
|
+ newMinerRecord.ValidShares = currentStats.Data.ValidShares
|
|
|
|
+ newMinerRecord.StaleShares = currentStats.Data.StaleShares
|
|
|
|
+ newMinerRecord.InvalidShares = currentStats.Data.InvalidShares
|
|
|
|
+ newMinerRecord.Workers = currentStats.Data.ActiveWorkers
|
|
|
|
+ newMinerRecord.Unpaid = currentStats.Data.Unpaid
|
|
|
|
+ LogInfo.Printf("New miner record creating complete %s", newMinerRecord.Wallet)
|
|
|
|
+
|
|
|
|
+ // Line 42 of UpdateData.cs
|
|
|
|
+ // Search for latest record for miner
|
|
|
|
+ var lastMinerRecord Miner
|
|
|
|
+ result := c.GormDb.
|
|
|
|
+ Where("wallet = ?", newMinerRecord.Wallet).
|
|
|
|
+ Order("time desc").
|
|
|
|
+ Limit(1).
|
|
|
|
+ Find(&lastMinerRecord)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // No previous records for miner
|
|
|
|
+ // Or previous record from different time
|
|
|
|
+ if result.RowsAffected == 0 || lastMinerRecord.Time != newMinerRecord.Time {
|
|
|
|
+ result = c.GormDb.Create(&newMinerRecord)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogInfo.Println(result.Error)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ LogInfo.Printf("Added new row for miner %s\n", newMinerRecord.Wallet)
|
|
|
|
+
|
|
|
|
+ // Line 54 of UpdateData.cs
|
|
|
|
+ if lastMinerRecord != (Miner{}) && newMinerRecord.Unpaid < lastMinerRecord.Unpaid {
|
|
|
|
+ var walletChats []int64
|
|
|
|
+ result := c.GormDb.Model(&User{}).
|
|
|
|
+ Where("wallet = ?", newMinerRecord.Wallet).
|
|
|
|
+ Select("chat_id").
|
|
|
|
+ Scan(&walletChats)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for _, chat := range walletChats {
|
|
|
|
+ LogInfo.Println("Sended 'Payout detected!' message to chat ", chat)
|
|
|
|
+ go myBotClient.Send(tgbotapi.NewMessage(chat, "Payout detected!"))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Line 64 of UpdateData.cs
|
|
|
|
+ LogInfo.Printf("Getting workers data for wallet %s\n", wallet)
|
|
|
|
+ url = fmt.Sprintf("%s/miner/%s/workers", appSettings.ApiUrl, wallet)
|
|
|
|
+
|
|
|
|
+ LogInfo.Print("From: " + url)
|
|
|
|
+ var currentWorker JsonWorker
|
|
|
|
+ // currentWorker := ethermine_api.WorkersStats("") url to miner
|
|
|
|
+ err := UnmasrshalFromUrl(url, ¤tWorker)
|
|
|
|
+ if err != nil {
|
|
|
|
+ LogError.Println(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if currentWorker.Status == "OK" {
|
|
|
|
+ if len(currentWorker.Data) == 0 {
|
|
|
|
+ LogInfo.Printf("data in response from %s for workers of wallet %s not an interface!\n", appSettings.ApiUrl, wallet)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for i := range currentWorker.Data {
|
|
|
|
+ workerData := currentWorker.Data[i]
|
|
|
|
+ LogInfo.Printf("Creating new worker record for %s, time %d\n", workerData.Worker, workerData.Time)
|
|
|
|
+
|
|
|
|
+ var newWorkerRecord Worker
|
|
|
|
+ newWorkerRecord.Wallet = newMinerRecord.Wallet
|
|
|
|
+ newWorkerRecord.Time = workerData.Time
|
|
|
|
+ newWorkerRecord.Worker = workerData.Worker
|
|
|
|
+ newWorkerRecord.ReportedHashrate = workerData.ReportedHashrate
|
|
|
|
+ newWorkerRecord.CurrentHashrate = workerData.CurrentHashrate
|
|
|
|
+ newWorkerRecord.ValidShares = workerData.ValidShares
|
|
|
|
+ newWorkerRecord.StaleShares = workerData.StaleShares
|
|
|
|
+ newWorkerRecord.InvalidShares = workerData.InvalidShares
|
|
|
|
+
|
|
|
|
+ LogInfo.Printf("New worker record creating complete %s", newWorkerRecord.Worker)
|
|
|
|
+
|
|
|
|
+ //Search for latest record for worker
|
|
|
|
+ var lastWorkerRecord Worker
|
|
|
|
+ result = c.GormDb.
|
|
|
|
+ Where("worker = ?", workerData.Worker).
|
|
|
|
+ Order("time desc").
|
|
|
|
+ Limit(1).
|
|
|
|
+ Find(&lastWorkerRecord)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Line 85 of UpdateData.cs
|
|
|
|
+ if lastWorkerRecord != (Worker{}) {
|
|
|
|
+ // Search for latest miner record... again?
|
|
|
|
+ var lastMinerRecord1 Miner
|
|
|
|
+ result = c.GormDb.
|
|
|
|
+ Where("wallet = ?", newMinerRecord.Wallet).
|
|
|
|
+ Order("time desc").
|
|
|
|
+ Limit(1).
|
|
|
|
+ Find(&lastMinerRecord1)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //Line 91 of UpdateData.cs
|
|
|
|
+ if lastMinerRecord1 != (Miner{}) {
|
|
|
|
+ //check for payout
|
|
|
|
+ if newMinerRecord.Unpaid < lastMinerRecord1.Unpaid {
|
|
|
|
+ // Adding new payout field to db
|
|
|
|
+ url := fmt.Sprintf("%s/miner/%s/payouts", appSettings.ApiUrl, wallet)
|
|
|
|
+ var payouts JsonPayouts
|
|
|
|
+ err := UnmasrshalFromUrl(url, &payouts)
|
|
|
|
+ if err != nil {
|
|
|
|
+ LogError.Println(err)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ lastPayout := payouts.Data[0]
|
|
|
|
+
|
|
|
|
+ LogInfo.Println("Last payout time =", lastPayout.PaidOn)
|
|
|
|
+
|
|
|
|
+ var newPayoutRecord Payout
|
|
|
|
+ newPayoutRecord.Wallet = wallet
|
|
|
|
+ newPayoutRecord.Time = lastPayout.PaidOn
|
|
|
|
+ newPayoutRecord.Amount = lastPayout.Amount
|
|
|
|
+ newPayoutRecord.Worker = workerData.Worker
|
|
|
|
+
|
|
|
|
+ workerAmount := float64(lastWorkerRecord.WorkerUnpaid+
|
|
|
|
+ (float64(lastPayout.Amount-lastMinerRecord.Unpaid))) *
|
|
|
|
+ (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
|
|
|
|
+ if math.IsNaN(workerAmount) || math.IsInf(workerAmount, 0) {
|
|
|
|
+ workerAmount = lastWorkerRecord.WorkerUnpaid
|
|
|
|
+ }
|
|
|
|
+ newPayoutRecord.WorkerAmount = workerAmount
|
|
|
|
+
|
|
|
|
+ workerUnpaid := float64(newMinerRecord.Unpaid) *
|
|
|
|
+ (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
|
|
|
|
+ LogDebug.Println("newMinerRecord.Unpaid:", newMinerRecord.Unpaid)
|
|
|
|
+ LogDebug.Println("lastMinerRecord.Unpaid:", lastMinerRecord.Unpaid)
|
|
|
|
+ LogDebug.Println("workerData.ReportedHashrate:", workerData.ReportedHashrate)
|
|
|
|
+ LogDebug.Println("newMinerRecord.ReportedHashrate:", newMinerRecord.ReportedHashrate)
|
|
|
|
+ LogDebug.Println("workerUnpaid:", workerUnpaid)
|
|
|
|
+ if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
|
|
|
|
+ LogDebug.Println("workerUnpaid is NaN or Inf")
|
|
|
|
+ workerUnpaid = 0
|
|
|
|
+ }
|
|
|
|
+ newWorkerRecord.WorkerUnpaid = workerUnpaid
|
|
|
|
+
|
|
|
|
+ result = c.GormDb.Create(&newPayoutRecord)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ LogInfo.Println("Add newPayoutRecord, time =", newPayoutRecord.Time)
|
|
|
|
+
|
|
|
|
+ //removing old records
|
|
|
|
+ result = c.GormDb.
|
|
|
|
+ Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
|
|
|
|
+ Delete(Worker{})
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ result = c.GormDb.
|
|
|
|
+ Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
|
|
|
|
+ Delete(Miner{})
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ result = c.GormDb.
|
|
|
|
+ Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
|
|
|
|
+ Delete(Payout{})
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ }
|
|
|
|
+ //Line 135 of UpdateData.cs
|
|
|
|
+ } else {
|
|
|
|
+ //no check that last balance and prev balance are the same
|
|
|
|
+ //don't sure > or >=
|
|
|
|
+ //TODO rewrite this
|
|
|
|
+ var max int64
|
|
|
|
+ result := c.GormDb.Model(&Payout{}).
|
|
|
|
+ Where("wallet = ?", lastWorkerRecord.Wallet).
|
|
|
|
+ Order("time desc").
|
|
|
|
+ Limit(1).
|
|
|
|
+ Select("time").
|
|
|
|
+ Scan(&max)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogWarn.Printf("No payouts data for %s! Time is set to 0!\n", lastWorkerRecord.Wallet)
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ max = 0
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if lastWorkerRecord.Time > max {
|
|
|
|
+ workerUnpaid := float64(lastWorkerRecord.WorkerUnpaid+
|
|
|
|
+ float64(newMinerRecord.Unpaid-lastMinerRecord.Unpaid)) *
|
|
|
|
+ (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
|
|
|
|
+ if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
|
|
|
|
+ workerUnpaid = lastWorkerRecord.WorkerUnpaid
|
|
|
|
+ }
|
|
|
|
+ newWorkerRecord.WorkerUnpaid = workerUnpaid
|
|
|
|
+ // Line 169 of UpdateData.cs
|
|
|
|
+ } else {
|
|
|
|
+ workerUnpaid := float64((newMinerRecord.Unpaid - lastMinerRecord.Unpaid)) *
|
|
|
|
+ (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
|
|
|
|
+ if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
|
|
|
|
+ workerUnpaid = lastWorkerRecord.WorkerUnpaid
|
|
|
|
+ }
|
|
|
|
+ newWorkerRecord.WorkerUnpaid = workerUnpaid
|
|
|
|
+
|
|
|
|
+ var targetedChats []int64
|
|
|
|
+ result = c.GormDb.
|
|
|
|
+ Where(&User{Wallet: newMinerRecord.Wallet}).
|
|
|
|
+ Select("DISTINCT(chat_id)").
|
|
|
|
+ Scan(&targetedChats)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ } else {
|
|
|
|
+ msg := fmt.Sprintf("Debug info: Your worker %s hasn't been zeroed on payout!", workerData.Worker)
|
|
|
|
+ for _, chatId := range targetedChats {
|
|
|
|
+ go myBotClient.Send(tgbotapi.NewMessage(int64(chatId), msg))
|
|
|
|
+ }
|
|
|
|
+ LogDebug.Printf("Worker %s on address %s hasn't been zeroed on payout!\n", workerData.Worker, wallet)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Line 196 of UpdateData.cs
|
|
|
|
+ } else {
|
|
|
|
+ LogDebug.Println("Setting WorkerUnpaid to 0")
|
|
|
|
+ newWorkerRecord.WorkerUnpaid = 0
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var rowsCount int64
|
|
|
|
+ result = c.GormDb.Model(&Worker{}).
|
|
|
|
+ Where("worker = ? and time = ?", newWorkerRecord.Worker, newWorkerRecord.Time).
|
|
|
|
+ Count(&rowsCount)
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if rowsCount != 0 {
|
|
|
|
+ LogInfo.Printf("Error adding new row: row with worker: %s, time: %d already exists!\n", newWorkerRecord.Worker, newWorkerRecord.Time)
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ result = c.GormDb.Create(&newWorkerRecord)
|
|
|
|
+
|
|
|
|
+ if result.Error != nil {
|
|
|
|
+ LogError.Println(result.Error)
|
|
|
|
+ } else {
|
|
|
|
+ LogInfo.Printf("Added new row for worker %s\n", newWorkerRecord.Worker)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Line 222 of UpdateData.cs
|
|
|
|
+ } else {
|
|
|
|
+ LogInfo.Printf("Row with wallet: %s and time: %d already exists!", wallet, currentStats.Data.Time)
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ LogError.Printf("Error response from pool for %s!\n", wallet)
|
|
|
|
+ }
|
|
|
|
+}
|