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) } }