update_data.go 9.5 KB

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