Program.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. using System;
  2. using System.Linq;
  3. using System.Threading.Tasks;
  4. using Telegram.Bot;
  5. using Telegram.Bot.Args;
  6. using Telegram.Bot.Types;
  7. using Telegram.Bot.Types.Enums;
  8. using System.Net.Http;
  9. using System.Threading;
  10. using EFDatabase;
  11. using MySql.Data.MySqlClient;
  12. using Quartz;
  13. using Quartz.Impl;
  14. namespace EthermineBotTelegram
  15. {
  16. class Program
  17. {
  18. static ITelegramBotClient botClient;
  19. static EFDatabase.botdb Botdb;
  20. static async Task Main(string[] args)
  21. {
  22. botClient = new TelegramBotClient("1785154817:AAGhXD9yQVn9HPdWTcmGJUBeZ8nA50SzHbY");
  23. var me = botClient.GetMeAsync().Result;
  24. Console.WriteLine(
  25. $"Hello, World! I am user {me.Id} and my name is {me.FirstName}."
  26. );
  27. //creating connection to DB
  28. string user;
  29. string pass;
  30. if (args[0] != null && args[1] != null)
  31. {
  32. user = args[0];
  33. pass = args[1];
  34. }
  35. else
  36. {
  37. Console.Out.Write("User:");
  38. user = Console.ReadLine();
  39. Console.Out.Write("Password:");
  40. pass = Console.ReadLine();
  41. }
  42. Botdb =
  43. new botdb("server=" + AppSettings.dbIp + ";port=3306;database=botdb;uid=" + user + "; pwd=" + pass);
  44. try
  45. {
  46. Botdb.Database.Connection.Open();
  47. Botdb.Database.Connection.Close();
  48. // Grab the Scheduler instance from the Factory
  49. StdSchedulerFactory factory = new StdSchedulerFactory();
  50. IScheduler scheduler = await factory.GetScheduler();
  51. // and start it off
  52. await scheduler.Start();
  53. // define the job and tie it to our HelloJob class
  54. IJobDetail job = JobBuilder.Create<DataUpdater>()
  55. .WithIdentity("job1", "group1")
  56. .UsingJobData("connectionString", "server=" + AppSettings.dbIp + ";port=3306;database=botdb;uid=" + user + "; pwd=" + pass)
  57. .Build();
  58. // Trigger the job to run now, and then repeat it
  59. ITrigger trigger = TriggerBuilder.Create()
  60. .WithIdentity("trigger1", "group1")
  61. .StartNow()
  62. .WithSimpleSchedule(x => x
  63. .WithIntervalInSeconds(240)
  64. .RepeatForever())
  65. .Build();
  66. // Tell quartz to schedule the job using our trigger
  67. await scheduler.ScheduleJob(job, trigger);
  68. Console.WriteLine(("Scheduler started!"));
  69. Thread.Sleep(5000);
  70. //start receive messages
  71. botClient.OnMessage += BotOnMessage;
  72. botClient.StartReceiving();
  73. Console.WriteLine("Press any key to exit");
  74. Console.ReadKey();
  75. await scheduler.Shutdown();
  76. botClient.StopReceiving();
  77. }
  78. catch (MySqlException)
  79. {
  80. Console.WriteLine("Don't connected! Check auth data and restart!");
  81. }
  82. }
  83. static async void BotOnMessage(object sender, MessageEventArgs e) {
  84. if (e.Message.Text != null)
  85. {
  86. Console.WriteLine($"Received a text message in chat {e.Message.Chat.Id}.");
  87. char[] delimeters = { ' ', '@' };
  88. var message = e.Message;
  89. if (message == null || message.Type != MessageType.Text)
  90. return;
  91. switch (message.Text.Split(delimeters).First())
  92. {
  93. // add user into database
  94. case "/start":
  95. AddUser(e.Message.Chat);
  96. break;
  97. // add user into database
  98. case "/stop":
  99. DeleteUser(e.Message.Chat);
  100. break;
  101. // connect wallet to user
  102. case "/setwallet":
  103. SetWallet(e);
  104. break;
  105. // get actual data from ethermine
  106. case "/actual":
  107. if (message.Text.Split(' ').Length > 1)
  108. GetActualData(e);
  109. else
  110. GetActualDataFromDatabase(e.Message.Chat);
  111. break;
  112. // get actual data from ethermine
  113. case "/rate":
  114. GetActualRate(e);
  115. break;
  116. // send help
  117. case "/help":
  118. //await SendHelp();
  119. break;
  120. default:
  121. //await Usage(message);
  122. if (e.Message.Chat.Id > 0)
  123. await botClient.SendTextMessageAsync(
  124. chatId: e.Message.Chat,
  125. text: "Incorrect message");
  126. break;
  127. }
  128. }
  129. }
  130. //send reauest to pool api and gets back json than parse it and send message with data from it
  131. static async void GetActualData(MessageEventArgs e)
  132. {
  133. try
  134. {
  135. var url = AppSettings.poolApiUrl + "/miner/" + e.Message.Text.Split(' ')[1] + "/currentStats";
  136. var currnentStats = JsonDownloader._download_serialized_json_data<JsonCurrentStats>(url);
  137. await botClient.SendTextMessageAsync(
  138. chatId: e.Message.Chat,
  139. text: "Updated: " + DateTimeOffset.FromUnixTimeSeconds(currnentStats.data.time).LocalDateTime
  140. .ToString("f") + "\n"
  141. + "Reported Hashrate: " + Math.Round(currnentStats.data.reportedHashrate / 1000000D, 3) +
  142. " MH/s\n"
  143. + "Current Hashrate: " + Math.Round(currnentStats.data.currentHashrate / 1000000D, 3) +
  144. " MH/s\n"
  145. + "Valid Shares: " + currnentStats.data.validShares + "\n"
  146. + "Stale Shares: " + currnentStats.data.staleShares + "\n"
  147. + "Workers: " + currnentStats.data.activeWorkers + "\n"
  148. + "Unpaid Balance: " + Math.Round(currnentStats.data.unpaid / Math.Pow(10, 18), 5) + " ETH\n");
  149. }
  150. catch (Exception exception)
  151. {
  152. await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace);
  153. await botClient.SendTextMessageAsync(
  154. chatId: e.Message.Chat,
  155. text: "An exception occurred while executing this command.");
  156. }
  157. }
  158. //get last data from tables miners and workers from DB and send message to user
  159. static async void GetActualDataFromDatabase(Chat e)
  160. {
  161. //try
  162. //{
  163. var wallet = Botdb.users.Where(u => u.chat_id == e.Id).Select(u => u.wallet).FirstOrDefault();
  164. if (wallet != null)
  165. {
  166. var lastMinerRecord = Botdb.miners.Where(w => w.wallet == wallet)
  167. .OrderByDescending(w => w.time)
  168. .FirstOrDefault();
  169. if (lastMinerRecord != null)
  170. {
  171. //var lastWorkerRecord = new workers();
  172. long lastTime = Botdb.workers.Where(w => w.wallet == wallet)
  173. .Max(w => w.time);
  174. var lastWorkerRecord = Botdb.workers.Where(w => w.wallet == wallet && w.time == lastTime)
  175. .OrderByDescending(w => w.time).ToList();
  176. if (lastWorkerRecord != null)
  177. {
  178. await botClient.SendTextMessageAsync(
  179. chatId: e,
  180. text: $"Miner {lastMinerRecord.wallet} stats:\n" +
  181. "Updated: " + DateTimeOffset.FromUnixTimeSeconds(lastMinerRecord.time)
  182. .LocalDateTime
  183. .ToString("f") + "\n"
  184. + "Reported Hashrate: " +
  185. Math.Round(lastMinerRecord.reported_hashrate / 1000000D, 3) + " MH/s\n"
  186. + "Current Hashrate: " +
  187. Math.Round(lastMinerRecord.current_hashrate / 1000000D, 3) + " MH/s\n"
  188. + "Valid Shares: " + lastMinerRecord.valid_shares + "\n"
  189. + "Stale Shares: " + lastMinerRecord.stale_shares + "\n"
  190. + "Workers: " + lastMinerRecord.workers + "\n"
  191. + "Unpaid Balance: " + Math.Round(lastMinerRecord.unpaid / Math.Pow(10, 18), 5) +
  192. " ETH\n");
  193. for (int i = 0; i < lastWorkerRecord.Count; i++)
  194. {
  195. Thread.Sleep(1000);
  196. if (i!=0 && i%20 == 0) //TODO SOMETIHNG BETTER THAN USUAL TIMER
  197. Thread.Sleep(30000);
  198. try
  199. {
  200. await botClient.SendTextMessageAsync(
  201. chatId: e,
  202. text: $"Worker {lastWorkerRecord[i].worker} stats:\n" +
  203. "Updated: " + DateTimeOffset.FromUnixTimeSeconds(lastWorkerRecord[i].time)
  204. .LocalDateTime
  205. .ToString("f") + "\n"
  206. + "Reported Hashrate: " +
  207. Math.Round(lastWorkerRecord[i].reported_hashrate / 1000000D, 3) + " MH/s\n"
  208. + "Current Hashrate: " +
  209. Math.Round(lastWorkerRecord[i].current_hashrate / 1000000D, 3) + " MH/s\n"
  210. + "Valid Shares: " + lastWorkerRecord[i].valid_shares + "\n"
  211. + "Stale Shares: " + lastWorkerRecord[i].stale_shares + "\n"
  212. + "Unpaid Balance: " +
  213. Math.Round(lastWorkerRecord[i].worker_unpaid / Math.Pow(10, 18), 5) +
  214. " ETH\n");
  215. }
  216. catch (HttpRequestException exception)
  217. {
  218. await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace);
  219. }
  220. }
  221. }
  222. else
  223. {
  224. await botClient.SendTextMessageAsync(
  225. chatId: e,
  226. text: "No workers data for now!");
  227. }
  228. }
  229. else
  230. {
  231. await botClient.SendTextMessageAsync(
  232. chatId: e,
  233. text: "No miner data for now!");
  234. }
  235. }
  236. else
  237. {
  238. await botClient.SendTextMessageAsync(
  239. chatId: e,
  240. text: "Set wallet at first! Use /setwallet");
  241. }
  242. //}
  243. //catch (Exception exception)
  244. //{
  245. // await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace);
  246. // await botClient.SendTextMessageAsync(
  247. // chatId: e,
  248. // text: "Something got wrong! Check entered wallet or try later.");
  249. //}
  250. }
  251. static async void GetActualRate(MessageEventArgs e)
  252. {
  253. try
  254. {
  255. var url = AppSettings.poolApiUrl + "/networkStats";
  256. var networkStats = JsonDownloader._download_serialized_json_data<NetworkStats>(url);
  257. await botClient.SendTextMessageAsync(
  258. chatId: e.Message.Chat,
  259. text: "ETH: " + Math.Round(networkStats.data.usd, 2) + "\n"
  260. + "BTC: " + Math.Round(networkStats.data.usd / networkStats.data.btc, 2)
  261. );
  262. }
  263. catch (Exception)
  264. {
  265. await botClient.SendTextMessageAsync(
  266. chatId: e.Message.Chat,
  267. text: "An exception occurred while executing this command.");
  268. }
  269. }
  270. static async void AddUser(Chat e)
  271. {
  272. try
  273. {
  274. if (Botdb.users.Where(users => users.chat_id == e.Id).FirstOrDefault() == null)
  275. {
  276. var newuser = new users();
  277. newuser.chat_id = e.Id;
  278. Botdb.users.Add(newuser);
  279. Botdb.SaveChanges();
  280. await botClient.SendTextMessageAsync(
  281. chatId: e,
  282. text: "Added new user to database. Now you can connect your miner wallet using command /setwallet <address>");
  283. }
  284. else
  285. {
  286. await botClient.SendTextMessageAsync(
  287. chatId: e,
  288. text: "Already registered");
  289. }
  290. }
  291. catch (Exception exception)
  292. {
  293. await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace);
  294. }
  295. }
  296. static async void SetWallet(MessageEventArgs e)
  297. {
  298. try
  299. {
  300. if (Botdb.users.Where(u => u.chat_id == e.Message.Chat.Id).FirstOrDefault() != null)
  301. {
  302. if (e.Message.Text.Split(' ')[1].Length > 2)
  303. {
  304. if (e.Message.Text.Split(' ')[1].Contains("0x"))
  305. {
  306. Botdb.users.Where(u => u.chat_id == e.Message.Chat.Id).FirstOrDefault().wallet =
  307. e.Message.Text.Split(' ')[1];
  308. }
  309. else
  310. {
  311. Botdb.users.Where(u => u.chat_id == e.Message.Chat.Id).FirstOrDefault().wallet =
  312. "0x" + e.Message.Text.Split(' ')[1];
  313. }
  314. await Botdb.SaveChangesAsync();
  315. await botClient.SendTextMessageAsync(
  316. chatId: e.Message.Chat,
  317. text: $"Wallet {"0x" + e.Message.Text.Split(' ')[1]} set!");
  318. }
  319. else
  320. {
  321. await botClient.SendTextMessageAsync(
  322. chatId: e.Message.Chat,
  323. text: "Too short!");
  324. }
  325. //Botdb.SaveChanges();
  326. }
  327. else
  328. {
  329. await botClient.SendTextMessageAsync(
  330. chatId: e.Message.Chat,
  331. text: "You not registered! Type /start first!");
  332. }
  333. }
  334. catch (Exception exception)
  335. {
  336. await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace);
  337. await botClient.SendTextMessageAsync(
  338. chatId: e.Message.Chat,
  339. text: "An exception occurred while executing this command.");
  340. }
  341. }
  342. static async void DeleteUser(Chat e)
  343. {
  344. try
  345. {
  346. if (Botdb.users.Where(users => users.chat_id == e.Id).FirstOrDefault() != null)
  347. {
  348. var deletableWallet = Botdb.users.Where(u => u.chat_id == e.Id).First().wallet;
  349. if (Botdb.users.Where(u => u.wallet == deletableWallet).Count() > 1)
  350. {
  351. Botdb.users.RemoveRange(Botdb.users.Where(u=> u.chat_id == e.Id));
  352. }
  353. else
  354. {
  355. Botdb.workers.RemoveRange(Botdb.workers.Where(w=> w.wallet == deletableWallet));
  356. Botdb.miners.RemoveRange(Botdb.miners.Where(m=> m.wallet == deletableWallet));
  357. Botdb.users.RemoveRange(Botdb.users.Where(u=> u.chat_id == e.Id));
  358. }
  359. await Botdb.SaveChangesAsync();
  360. await botClient.SendTextMessageAsync(
  361. chatId: e,
  362. text: "Done!");
  363. }
  364. else
  365. {
  366. await botClient.SendTextMessageAsync(
  367. chatId: e,
  368. text: "Already deleted");
  369. }
  370. }
  371. catch (Exception exception)
  372. {
  373. await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace);
  374. await botClient.SendTextMessageAsync(
  375. chatId: e,
  376. text: "An exception occurred while executing this command.");
  377. }
  378. }
  379. //gets data from pool API in json, calculates unpaid for each worker and adds it to DB
  380. public static async Task UpdateData()
  381. {
  382. var walletList = Botdb.users.Where(u=>u.wallet != null).Select(u=> u.wallet).Distinct().ToList();
  383. foreach (string wallet in walletList)
  384. {
  385. try
  386. {
  387. var url = AppSettings.poolApiUrl + "/miner/" + wallet + "/currentStats";
  388. var currnentStats = JsonDownloader._download_serialized_json_data<JsonCurrentStats>(url);
  389. if (currnentStats.status == "OK")
  390. {
  391. await Console.Out.WriteLineAsync($"Create new record for {wallet}");
  392. miners newMinerRecord = new miners();
  393. newMinerRecord.wallet = wallet;
  394. newMinerRecord.time = currnentStats.data.time;
  395. newMinerRecord.reported_hashrate = currnentStats.data.reportedHashrate;
  396. newMinerRecord.current_hashrate = currnentStats.data.currentHashrate;
  397. newMinerRecord.valid_shares = currnentStats.data.validShares;
  398. newMinerRecord.stale_shares = currnentStats.data.staleShares;
  399. newMinerRecord.invalid_shares = currnentStats.data.invalidShares;
  400. newMinerRecord.workers = currnentStats.data.activeWorkers;
  401. newMinerRecord.unpaid = currnentStats.data.unpaid;
  402. await Console.Out.WriteLineAsync($"New record creating complete {newMinerRecord.wallet}");
  403. long lastTime = 0;
  404. if (Botdb.miners.Where(m => m.wallet == newMinerRecord.wallet).FirstOrDefault() != null)
  405. lastTime = Botdb.miners.Where(m => m.wallet == newMinerRecord.wallet).Max(m => m.time);
  406. var lastMinerRecord = Botdb.miners.Where(m => m.wallet == newMinerRecord.wallet && m.time == lastTime).FirstOrDefault();
  407. if (lastMinerRecord == null || lastMinerRecord.time !=
  408. newMinerRecord.time)
  409. {
  410. Botdb.miners.Add(newMinerRecord);
  411. //await Botdb.SaveChangesAsync();
  412. await Console.Out.WriteLineAsync($"Added new row for {newMinerRecord.wallet}");
  413. if (lastMinerRecord != null && newMinerRecord.unpaid < lastMinerRecord.unpaid)
  414. {
  415. await botClient.SendTextMessageAsync(
  416. chatId: Botdb.users.Where(user => user.wallet == newMinerRecord.wallet)
  417. .FirstOrDefault().chat_id,
  418. text: "Payout detected!");
  419. }
  420. url = AppSettings.poolApiUrl + "/miner/" + wallet + "/workers";
  421. var currentWorker = JsonDownloader._download_serialized_json_data<JsonWorker>(url);
  422. if (currentWorker.status == "OK")
  423. {
  424. for (int i = 0; i < currentWorker.data.Count(); i++)
  425. {
  426. await Console.Out.WriteLineAsync($"Create new record for {currentWorker.data[i].worker}");
  427. var newWorkerRecord = new workers();
  428. newWorkerRecord.wallet = newMinerRecord.wallet;
  429. newWorkerRecord.time = currentWorker.data[i].time;
  430. newWorkerRecord.worker = currentWorker.data[i].worker;
  431. newWorkerRecord.reported_hashrate = currentWorker.data[i].reportedHashrate;
  432. newWorkerRecord.current_hashrate = currentWorker.data[i].currentHashrate;
  433. newWorkerRecord.valid_shares = currentWorker.data[i].validShares;
  434. newWorkerRecord.stale_shares = currentWorker.data[i].staleShares;
  435. newWorkerRecord.invalid_shares = currentWorker.data[i].invalidShares;
  436. var lastWorkerRecord = Botdb.workers.Where(w => w.worker == newWorkerRecord.worker)
  437. .OrderByDescending(w => w.time)
  438. .FirstOrDefault();
  439. if (lastWorkerRecord != null)
  440. {
  441. await Console.Out.WriteLineAsync($"lastWorkerRecord time = {lastWorkerRecord.time}");
  442. lastMinerRecord = Botdb.miners.Where(w => w.wallet == newMinerRecord.wallet)
  443. .OrderByDescending(w => w.time)
  444. .FirstOrDefault();
  445. if (lastMinerRecord != null)
  446. {
  447. await Console.Out.WriteLineAsync($"lastMinerRecord time = {lastMinerRecord.time}");
  448. //check for payout
  449. if (newMinerRecord.unpaid < lastMinerRecord.unpaid)
  450. {
  451. url = AppSettings.poolApiUrl + "/miner/" + wallet + "/payouts";
  452. var payouts = JsonDownloader._download_serialized_json_data<JsonPayouts>(url);
  453. await Console.Out.WriteLineAsync($"Last payout time = {DateTimeOffset.FromUnixTimeSeconds(payouts.data[0].paidOn).LocalDateTime.ToString("f")}");
  454. var newPayoutRecord = new payouts();
  455. newPayoutRecord.wallet = wallet;
  456. newPayoutRecord.time = payouts.data[0].paidOn;
  457. newPayoutRecord.amount = payouts.data[0].amount;
  458. newPayoutRecord.worker = newWorkerRecord.worker;
  459. //calculating payout for worker
  460. newPayoutRecord.worker_amount = lastWorkerRecord.worker_unpaid +
  461. (payouts.data[0].amount -
  462. lastMinerRecord.unpaid) *
  463. (newWorkerRecord.reported_hashrate /
  464. ((double) newMinerRecord.reported_hashrate));
  465. if (Double.IsNaN(newWorkerRecord.worker_unpaid) ||
  466. Double.IsInfinity(newWorkerRecord.worker_unpaid))
  467. newPayoutRecord.worker_amount = lastWorkerRecord.worker_unpaid;
  468. //calculating unpaid for worker
  469. newWorkerRecord.worker_unpaid = 0 +
  470. (newMinerRecord.unpaid) *
  471. (newWorkerRecord.reported_hashrate /
  472. ((double) newMinerRecord.reported_hashrate));
  473. if (Double.IsNaN(newWorkerRecord.worker_unpaid) ||
  474. Double.IsInfinity(newWorkerRecord.worker_unpaid))
  475. newWorkerRecord.worker_unpaid = 0;
  476. }
  477. else
  478. {
  479. //no check that last balance and prev balance are the same
  480. newWorkerRecord.worker_unpaid = lastWorkerRecord.worker_unpaid +
  481. (newMinerRecord.unpaid -
  482. lastMinerRecord.unpaid) *
  483. (newWorkerRecord.reported_hashrate /
  484. ((double) newMinerRecord.reported_hashrate));
  485. if (Double.IsNaN(newWorkerRecord.worker_unpaid) ||
  486. Double.IsInfinity(newWorkerRecord.worker_unpaid))
  487. newWorkerRecord.worker_unpaid = lastWorkerRecord.worker_unpaid;
  488. await Console.Out.WriteLineAsync($"newWorkerRecord unpaid change = {newMinerRecord.unpaid - lastMinerRecord.unpaid}");
  489. }
  490. }
  491. else
  492. {
  493. newWorkerRecord.worker_unpaid = 0;
  494. }
  495. }
  496. else
  497. {
  498. newWorkerRecord.worker_unpaid = 0;
  499. }
  500. await Console.Out.WriteLineAsync($"newWorkerRecord worker unpaid = {newWorkerRecord.worker_unpaid}");
  501. //this if does nothing
  502. if (lastWorkerRecord == null || newWorkerRecord.time != lastWorkerRecord.time)
  503. {
  504. Botdb.workers.Add(newWorkerRecord);
  505. //await Botdb.SaveChangesAsync();
  506. }
  507. //Botdb.SaveChanges();
  508. else
  509. {
  510. Botdb.workers.Add(newWorkerRecord);
  511. }
  512. }
  513. }
  514. }
  515. else
  516. {
  517. await Console.Out.WriteLineAsync($"Row with wallet: {newMinerRecord.wallet} and time: {newMinerRecord.time} already exists!");
  518. }
  519. try
  520. {
  521. await Botdb.SaveChangesAsync();
  522. await Console.Out.WriteLineAsync($"Saved");
  523. }
  524. catch (Exception exception)
  525. {
  526. await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace);
  527. }
  528. }
  529. else
  530. {
  531. await Console.Out.WriteLineAsync($"Error response from pool for {wallet}!");
  532. }
  533. }
  534. catch (Exception exception)
  535. {
  536. await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace + " " + exception.StackTrace);
  537. }
  538. }
  539. }
  540. }
  541. }