update_data.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
  6. )
  7. func (c *Connection) UpdateData() {
  8. LogInfo.Println("Updating data!")
  9. // Getting list of unique wallets in user table
  10. var walletList []string
  11. result := c.GormDb.Model(&User{}).
  12. Not("wallet = ?", "").
  13. Select("DISTINCT(wallet)").
  14. Scan(&walletList)
  15. if result.Error != nil {
  16. LogError.Println(result.Error)
  17. return
  18. }
  19. for _, wallet := range walletList {
  20. LogInfo.Printf("Getting data for wallet %s\n", wallet)
  21. url := fmt.Sprintf("%s/miner/%s/currentStats", appSettings.ApiUrl, wallet)
  22. LogInfo.Print("From: " + url)
  23. var currentStats JsonCurrentStats
  24. err := UnmasrshalFromUrl(url, &currentStats)
  25. if err != nil {
  26. LogInfo.Println("Error with getting currentStats data")
  27. continue
  28. }
  29. if currentStats.Status == "OK" {
  30. if currentStats.Data == (JsonCurrentStats{}).Data {
  31. // if fmt.Sprintf("%T", currentStats.(map[string]interface{})["data"]) != "map[string]interface {}" {
  32. LogInfo.Printf("data in response from %s for wallet %s not an interface!\n", appSettings.ApiUrl, wallet)
  33. continue
  34. }
  35. // data := currentStats.(map[string]interface{})["data"].(map[string]interface{})
  36. LogInfo.Printf("Creating new record for miner %s, time %d\n", wallet, currentStats.Data.Time)
  37. // Line 28 of UpdateData.cs
  38. // NOTE: No use for creating new record here
  39. var newMinerRecord Miner
  40. newMinerRecord.Wallet = wallet
  41. newMinerRecord.Time = currentStats.Data.Time
  42. newMinerRecord.ReportedHashrate = currentStats.Data.ReportedHashrate
  43. newMinerRecord.CurrentHashrate = currentStats.Data.CurrentHashrate
  44. newMinerRecord.ValidShares = currentStats.Data.ValidShares
  45. newMinerRecord.StaleShares = currentStats.Data.StaleShares
  46. newMinerRecord.InvalidShares = currentStats.Data.InvalidShares
  47. newMinerRecord.Workers = currentStats.Data.ActiveWorkers
  48. newMinerRecord.Unpaid = currentStats.Data.Unpaid
  49. LogInfo.Printf("New miner record creating complete %s", newMinerRecord.Wallet)
  50. // Line 42 of UpdateData.cs
  51. // Search for latest record for miner
  52. var lastMinerRecord Miner
  53. result = c.GormDb.
  54. Where("wallet = ?", newMinerRecord.Wallet).
  55. Order("time desc").
  56. Limit(1).
  57. Find(&lastMinerRecord)
  58. if result.Error != nil {
  59. LogError.Println(result.Error)
  60. continue
  61. }
  62. // No previous records for miner
  63. // Or previous record from different time
  64. if result.RowsAffected == 0 || lastMinerRecord.Time != newMinerRecord.Time {
  65. result = c.GormDb.Create(&newMinerRecord)
  66. if result.Error != nil {
  67. LogInfo.Println(result.Error)
  68. continue
  69. }
  70. LogInfo.Printf("Added new row for miner %s\n", newMinerRecord.Wallet)
  71. // Line 54 of UpdateData.cs
  72. if lastMinerRecord != (Miner{}) && newMinerRecord.Unpaid < lastMinerRecord.Unpaid {
  73. var walletChats []int64
  74. result := c.GormDb.Model(&User{}).
  75. Where("wallet = ?", newMinerRecord.Wallet).
  76. Select("chat_id").
  77. Scan(&walletChats)
  78. if result.Error != nil {
  79. LogError.Println(result.Error)
  80. continue
  81. }
  82. for _, chat := range walletChats {
  83. LogInfo.Println("Sended 'Payout detected!' message to chat ", chat)
  84. go myBotClient.Send(tgbotapi.NewMessage(chat, "Payout detected!"))
  85. }
  86. }
  87. // Line 64 of UpdateData.cs
  88. LogInfo.Printf("Getting workers data for wallet %s\n", wallet)
  89. url = fmt.Sprintf("%s/miner/%s/workers", appSettings.ApiUrl, wallet)
  90. LogInfo.Print("From: " + url)
  91. var currentWorker JsonWorker
  92. err := UnmasrshalFromUrl(url, &currentWorker)
  93. if err != nil {
  94. LogError.Println(err)
  95. continue
  96. }
  97. if currentWorker.Status == "OK" {
  98. if len(currentWorker.Data) == 0 {
  99. LogInfo.Printf("data in response from %s for workers of wallet %s not an interface!\n", appSettings.ApiUrl, wallet)
  100. continue
  101. }
  102. for i := range currentWorker.Data {
  103. workerData := currentWorker.Data[i]
  104. LogInfo.Printf("Creating new worker record for %s, time %d\n", workerData.Worker, workerData.Time)
  105. var newWorkerRecord Worker
  106. newWorkerRecord.Wallet = newMinerRecord.Wallet
  107. newWorkerRecord.Time = workerData.Time
  108. newWorkerRecord.Worker = workerData.Worker
  109. newWorkerRecord.ReportedHashrate = workerData.ReportedHashrate
  110. newWorkerRecord.CurrentHashrate = workerData.CurrentHashrate
  111. newWorkerRecord.ValidShares = workerData.ValidShares
  112. newWorkerRecord.StaleShares = workerData.StaleShares
  113. newWorkerRecord.InvalidShares = workerData.InvalidShares
  114. LogInfo.Printf("New worker record creating complete %s", newWorkerRecord.Worker)
  115. //Search for latest record for worker
  116. var lastWorkerRecord Worker
  117. result = c.GormDb.
  118. Where("worker = ?", workerData.Worker).
  119. Order("time desc").
  120. Limit(1).
  121. Find(&lastWorkerRecord)
  122. if result.Error != nil {
  123. LogError.Println(result.Error)
  124. }
  125. // Line 85 of UpdateData.cs
  126. if lastWorkerRecord != (Worker{}) {
  127. // Search for latest miner record... again?
  128. var lastMinerRecord1 Miner
  129. result = c.GormDb.
  130. Where("wallet = ?", newMinerRecord.Wallet).
  131. Order("time desc").
  132. Limit(1).
  133. Find(&lastMinerRecord1)
  134. if result.Error != nil {
  135. LogError.Println(result.Error)
  136. }
  137. //Line 91 of UpdateData.cs
  138. if lastMinerRecord1 != (Miner{}) {
  139. //check for payout
  140. if newMinerRecord.Unpaid < lastMinerRecord1.Unpaid {
  141. // Adding new payout field to db
  142. url := fmt.Sprintf("%s/miner/%s/payouts", appSettings.ApiUrl, wallet)
  143. var payouts JsonPayouts
  144. err := UnmasrshalFromUrl(url, &payouts)
  145. if err != nil {
  146. LogError.Println(err)
  147. continue
  148. }
  149. lastPayout := payouts.Data[0]
  150. LogInfo.Println("Last payout time =", lastPayout.PaidOn)
  151. var newPayoutRecord Payout
  152. newPayoutRecord.Wallet = wallet
  153. newPayoutRecord.Time = lastPayout.PaidOn
  154. newPayoutRecord.Amount = lastPayout.Amount
  155. newPayoutRecord.Worker = workerData.Worker
  156. workerAmount := float64(lastWorkerRecord.WorkerUnpaid+
  157. (float64(lastPayout.Amount-lastMinerRecord.Unpaid))) *
  158. (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
  159. if math.IsNaN(workerAmount) || math.IsInf(workerAmount, 0) {
  160. workerAmount = lastWorkerRecord.WorkerUnpaid
  161. }
  162. newPayoutRecord.WorkerAmount = workerAmount
  163. workerUnpaid := float64(newMinerRecord.Unpaid) *
  164. (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
  165. LogDebug.Println("newMinerRecord.Unpaid:", newMinerRecord.Unpaid)
  166. LogDebug.Println("lastMinerRecord.Unpaid:", lastMinerRecord.Unpaid)
  167. LogDebug.Println("workerData.ReportedHashrate:", workerData.ReportedHashrate)
  168. LogDebug.Println("newMinerRecord.ReportedHashrate:", newMinerRecord.ReportedHashrate)
  169. LogDebug.Println("workerUnpaid:", workerUnpaid)
  170. if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
  171. LogDebug.Println("workerUnpaid is NaN or Inf")
  172. workerUnpaid = 0
  173. }
  174. newWorkerRecord.WorkerUnpaid = workerUnpaid
  175. result = c.GormDb.Create(&newPayoutRecord)
  176. if result.Error != nil {
  177. LogError.Println(result.Error)
  178. continue
  179. }
  180. LogInfo.Println("Add newPayoutRecord, time =", newPayoutRecord.Time)
  181. //removing old records
  182. result = c.GormDb.
  183. Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
  184. Delete(Worker{})
  185. if result.Error != nil {
  186. LogError.Println(result.Error)
  187. }
  188. result = c.GormDb.
  189. Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
  190. Delete(Miner{})
  191. if result.Error != nil {
  192. LogError.Println(result.Error)
  193. }
  194. result = c.GormDb.
  195. Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
  196. Delete(Payout{})
  197. if result.Error != nil {
  198. LogError.Println(result.Error)
  199. }
  200. //Line 135 of UpdateData.cs
  201. } else {
  202. //no check that last balance and prev balance are the same
  203. //don't sure > or >=
  204. //TODO rewrite this
  205. var max int64
  206. result := c.GormDb.Model(&Payout{}).
  207. Where("wallet = ?", lastWorkerRecord.Wallet).
  208. Order("time desc").
  209. Limit(1).
  210. Select("time").
  211. Scan(&max)
  212. if result.Error != nil {
  213. LogWarn.Printf("No payouts data for %s! Time is set to 0!\n", lastWorkerRecord.Wallet)
  214. LogError.Println(result.Error)
  215. max = 0
  216. }
  217. if lastWorkerRecord.Time > max {
  218. workerUnpaid := float64(lastWorkerRecord.WorkerUnpaid+
  219. float64(newMinerRecord.Unpaid-lastMinerRecord.Unpaid)) *
  220. (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
  221. if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
  222. workerUnpaid = lastWorkerRecord.WorkerUnpaid
  223. }
  224. newWorkerRecord.WorkerUnpaid = workerUnpaid
  225. // Line 169 of UpdateData.cs
  226. } else {
  227. workerUnpaid := float64((newMinerRecord.Unpaid - lastMinerRecord.Unpaid)) *
  228. (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
  229. if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
  230. workerUnpaid = lastWorkerRecord.WorkerUnpaid
  231. }
  232. newWorkerRecord.WorkerUnpaid = workerUnpaid
  233. var targetedChats []int64
  234. result = c.GormDb.
  235. Where(&User{Wallet: newMinerRecord.Wallet}).
  236. Select("DISTINCT(chat_id)").
  237. Scan(&targetedChats)
  238. if result.Error != nil {
  239. LogError.Println(result.Error)
  240. } else {
  241. msg := fmt.Sprintf("Debug info: Your worker %s hasn't been zeroed on payout!", workerData.Worker)
  242. for _, chatId := range targetedChats {
  243. go myBotClient.Send(tgbotapi.NewMessage(int64(chatId), msg))
  244. }
  245. LogDebug.Printf("Worker %s on address %s hasn't been zeroed on payout!\n", workerData.Worker, wallet)
  246. }
  247. }
  248. }
  249. }
  250. // Line 196 of UpdateData.cs
  251. } else {
  252. LogDebug.Println("Setting WorkerUnpaid to 0")
  253. newWorkerRecord.WorkerUnpaid = 0
  254. }
  255. var rowsCount int64
  256. result = c.GormDb.Model(&Worker{}).
  257. Where("worker = ? and time = ?", newWorkerRecord.Worker, newWorkerRecord.Time).
  258. Count(&rowsCount)
  259. if result.Error != nil {
  260. LogError.Println(result.Error)
  261. continue
  262. }
  263. if rowsCount != 0 {
  264. LogInfo.Printf("Error adding new row: row with worker: %s, time: %d already exists!\n", newWorkerRecord.Worker, newWorkerRecord.Time)
  265. continue
  266. }
  267. result = c.GormDb.Create(&newWorkerRecord)
  268. if result.Error != nil {
  269. LogError.Println(result.Error)
  270. } else {
  271. LogInfo.Printf("Added new row for worker %s\n", newWorkerRecord.Worker)
  272. }
  273. }
  274. }
  275. // Line 222 of UpdateData.cs
  276. } else {
  277. LogInfo.Printf("Row with wallet: %s and time: %d already exists!", wallet, currentStats.Data.Time)
  278. }
  279. } else {
  280. LogError.Printf("Error response from pool for %s!\n", wallet)
  281. }
  282. }
  283. }