update_data.go 10 KB

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