update_data.go 9.5 KB

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