private async Task HandleBuyReceiptAsync(KyubeyContext db, ActionDataWrap data, DateTime time) { try { var token = data.data.ask.Split(' ')[1]; var order = await db.DexBuyOrders.SingleOrDefaultAsync(x => x.Id == data.data.id && x.TokenId == token); if (order != null) { db.DexBuyOrders.Remove(order); await db.SaveChangesAsync(); } order = new DexBuyOrder { Id = data.data.id, Account = data.data.account, Ask = Convert.ToDouble(data.data.ask.Split(' ')[0]), Bid = Convert.ToDouble(data.data.bid.Split(' ')[0]), UnitPrice = data.data.unit_price / 10000.0, Time = time, TokenId = token }; db.DexBuyOrders.Add(order); await db.SaveChangesAsync(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }
private async Task CalculateOTCAsync(IConfiguration config, KyubeyContext db) { using (var txClient = new HttpClient { BaseAddress = new Uri(config["TransactionNodeBackup"]) }) { foreach (var x in await db.Otcs.ToListAsync()) { try { var last = await db.MatchReceipts .Where(y => y.TokenId == x.Id) .LastOrDefaultAsync(); var last24 = await db.MatchReceipts .Where(y => y.TokenId == x.Id) .Where(y => y.Time < DateTime.UtcNow.AddDays(-1)) .LastOrDefaultAsync(); if (last == null) { continue; } var price = last.UnitPrice; var price24 = last24?.UnitPrice; try { using (var kClient = new HttpClient { BaseAddress = new Uri(config["Kdata"]) }) { Console.WriteLine($"Uploading {x.Id} data..."); using (await kClient.PostAsJsonAsync($"/api/Candlestick", new { values = new[] { new { catalog = "kyubey-dex-" + x.Id, price = price, utcTime = DateTime.UtcNow } } })) { } } } catch { } x.Price = price; x.Change = price / (price24 ?? 1.0) - 1.0; await db.SaveChangesAsync(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } }
private async Task <IEnumerable <EosAction <ActionDataWrap> > > LookupDexActionAsync(IConfiguration config, KyubeyContext db) { var row = await db.Constants.SingleAsync(x => x.Id == "action_pos"); var position = Convert.ToInt64(row.Value); using (var client = new HttpClient { BaseAddress = new Uri(config["TransactionNodeBackup"]) }) using (var response = await client.PostAsJsonAsync("/v1/history/get_actions", new { account_name = "kyubeydex.bp", pos = position, offset = 100 })) { var txt = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject <EosActionWrap <ActionDataWrap> >(txt, new JsonSerializerSettings { Error = HandleDeserializationError }); if (result.actions.Count() == 0) { return(null); } if (result.actions.Count() > 0) { row.Value = result.actions.Last().account_action_seq.ToString(); await db.SaveChangesAsync(); } return(result.actions); } }
async Task HandleRaiseCountAsync(KyubeyContext db, string token, DateTime startTime, DateTime endTime) { var currentRaisedSum = db.RaiseLogs.Where(x => x.TokenId == token && x.Timestamp >= startTime && x.Timestamp <= endTime).Select(x => x.Amount).Sum(); var row = db.Tokens.FirstOrDefault(x => x.Id == token); if (row != null) { row.Raised = (decimal)currentRaisedSum; await db.SaveChangesAsync(); } }
private async Task CalculateOTCAsync(IConfiguration config, KyubeyContext db) { using (var txClient = new HttpClient { BaseAddress = new Uri(config["TransactionNode"]) }) { foreach (var x in await db.Otcs.ToListAsync()) { try { using (var tableResponse1 = await txClient.PostAsJsonAsync("/v1/chain/get_table_rows", new { code = "eosotcbackup", scope = "eosio.token", table = "order", json = true, limit = 65535 })) using (var tableResponse2 = await txClient.PostAsJsonAsync("/v1/chain/get_table_rows", new { code = "eosotcbackup", scope = x.Token.Contract, table = "order", json = true, limit = 65535 })) { var rows1 = JsonConvert.DeserializeObject <OrderTable>((await tableResponse1.Content.ReadAsStringAsync())) .rows .Where(y => y.bid.quantity.EndsWith(x.Id) && y.bid.contract == x.Token.Contract) .Where(y => y.ask.quantity.EndsWith("EOS") && y.ask.quantity == "eosio.token"); var rows2 = JsonConvert.DeserializeObject <OrderTable>((await tableResponse2.Content.ReadAsStringAsync())) .rows .Where(y => y.ask.quantity.EndsWith(x.Id) && y.ask.contract == x.Token.Contract) .Where(y => y.bid.quantity.EndsWith("EOS") && y.bid.contract == "eosio.token"); x.Transactions = rows1.Count() + rows2.Count(); if (rows1.Count() > 0) { x.PriceMin = rows1.Min(y => Convert.ToDouble(y.ask.quantity.Split(' ')[0]) / Convert.ToDouble(y.bid.quantity.Split(' ')[0])); x.PriceMax = rows1.Max(y => Convert.ToDouble(y.ask.quantity.Split(' ')[0]) / Convert.ToDouble(y.bid.quantity.Split(' ')[0])); } await db.SaveChangesAsync(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } } }
private async Task HandleBuyMatchAsync(KyubeyContext db, ActionDataWrap data, DateTime time) { try { var token = data.data.ask.Split(' ')[1]; var bid = Convert.ToDouble(data.data.bid.Split(' ')[0]); var ask = Convert.ToDouble(data.data.ask.Split(' ')[0]); var order = await db.DexSellOrders.SingleOrDefaultAsync(x => x.Id == data.data.id && x.TokenId == token); if (order != null) { order.Bid -= bid; order.Ask -= ask; if (order.Ask <= 0 || order.Bid <= 0) { db.DexSellOrders.Remove(order); } await db.SaveChangesAsync(); } db.MatchReceipts.Add(new MatchReceipt { Ask = ask, Bid = bid, Asker = data.data.asker, Bidder = data.data.bidder, Time = time, TokenId = token, UnitPrice = data.data.unit_price / 10000.0 }); await db.SaveChangesAsync(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }
async Task HandleRaiseLogAsync(KyubeyContext db, int seq, string token, string account, string from, string to, decimal quantity, DateTime time) { var row = db.RaiseLogs.Where(x => x.TokenId == token && x.Seq == seq).FirstOrDefault(); if (row == null && from != account && to == account) { db.RaiseLogs.Add(new RaiseLog { Account = from, Amount = (double)quantity, Timestamp = time, TokenId = token, Seq = seq }); await db.SaveChangesAsync(); } }
private async Task HandleCancelBuyAsync(KyubeyContext db, ActionDataWrap data, DateTime time) { try { var order = await db.DexBuyOrders.SingleOrDefaultAsync(x => x.Id == data.id && x.TokenId == data.symbol); if (order != null) { db.DexBuyOrders.Remove(order); await db.SaveChangesAsync(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }
public async Task <IActionResult> PostFavorite([FromServices] KyubeyContext db, string account, string symbol, CancellationToken cancellationToken) { var userFavs = await db.Favorites.Where(x => x.Account == account && x.TokenId == symbol).ToListAsync(cancellationToken); if (userFavs.Count > 0) { db.Favorites.RemoveRange(userFavs); } else { db.Favorites.Add(new Favorite() { Account = account, TokenId = symbol }); } await db.SaveChangesAsync(); return(Ok()); }
private async Task HandleRaiseLogAsync(KyubeyContext db, TransferActionData data, DateTime time, string tokenId, string transferContractAccount) { try { if (data.from != transferContractAccount && data.to == transferContractAccount) { db.RaiseLogs.Add(new RaiseLog { Account = data.from, Amount = Convert.ToDouble(data.quantity.Split(' ')[0]), Timestamp = time, TokenId = tokenId }); await db.SaveChangesAsync(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } }
private async Task <IEnumerable <EosAction <TransferActionData> > > LookupIboActionAsync( IConfiguration config, KyubeyContext db, string tokenId, ITokenRepository tokenRepository) { var tokenInDb = await db.Tokens.SingleAsync(x => x.Id == tokenId); var position = tokenInDb.ActionPosition; var token = tokenRepository.GetOne(tokenId); using (var client = new HttpClient { BaseAddress = new Uri(config["TransactionNodeBackup"]) }) using (var response = await client.PostAsJsonAsync("/v1/history/get_actions", new { account_name = token.Basic.Contract.Transfer, pos = position, offset = 100 })) { var txt = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject <EosActionWrap <TransferActionData> >(txt, new JsonSerializerSettings { Error = HandleDeserializationError }); if (result.actions.Count() == 0) { return(null); } if (result.actions.Count() > 0) { tokenInDb.ActionPosition = result.actions.Last().account_action_seq; await db.SaveChangesAsync(); } return(result.actions); } }
private async Task CalculateBancorAsync(IConfiguration config, KyubeyContext db, INodeServices node) { var tokens = db.Bancors .Where(x => !string.IsNullOrEmpty(x.Token.Contract)) .Include(x => x.Token) .ToList(); var upload = new List <object>(); var time = DateTime.UtcNow; using (var txClient = new HttpClient { BaseAddress = new Uri(config["TransactionNode"]) }) using (var kClient = new HttpClient { BaseAddress = new Uri(config["Kdata"]) }) { foreach (var x in tokens) { try { using (var tableResponse = await txClient.PostAsJsonAsync("/v1/chain/get_table_rows", new { code = x.Token.Contract, scope = x.Scope, table = x.Table, json = true })) using (var k24hResponse = await kClient.GetAsync($"/api/Candlestick/kyubey-{x.Id}/24h")) { var text = await tableResponse.Content.ReadAsStringAsync(); var text2 = await k24hResponse.Content.ReadAsStringAsync(); var rows = JsonConvert.DeserializeObject <Table>(text).rows; var k24h = 0.0; try { k24h = JsonConvert.DeserializeObject <K24HResponse>(text2).data; } catch { } var buy = await node.InvokeExportAsync <string>("./price", "buyPrice", rows, x.CurrentBuyPriceJavascript); var sell = await node.InvokeExportAsync <string>("./price", "sellPrice", rows, x.CurrentSellPriceJavascript); x.BuyPrice = Convert.ToDouble(buy.Contains(".") ? buy.TrimEnd('0') : buy); x.SellPrice = Convert.ToDouble(sell.Contains(".") ? sell.TrimEnd('0') : sell); if (k24h != 0.0) { x.Change = (x.BuyPrice - k24h) / k24h; } else { x.Change = 0.0; } upload.Add(new { catalog = "kyubey-" + x.Id, price = x.BuyPrice, utcTime = time }); await db.SaveChangesAsync(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } Console.WriteLine($"Uploading {upload.Count} data..."); using (await kClient.PostAsJsonAsync($"/api/Candlestick", new { values = upload })) { } } await db.SaveChangesAsync(); }
private async Task CalculateBancorAsync(IConfiguration config, KyubeyContext db, INodeServices node, ITokenRepository tokenRepository) { var tokenInfoList = tokenRepository.GetAll(); var tokenHasContractList = tokenInfoList.Select(x => new { Id = x.Id, HasContract = !string.IsNullOrWhiteSpace(x?.Basic?.Contract?.Transfer) }).ToList(); var tokens = db.Bancors .Include(x => x.Token) .ToList() .Where(x => tokenHasContractList.FirstOrDefault(t => t.Id == x.Id).HasContract); var time = DateTime.UtcNow; using (var txClient = new HttpClient { BaseAddress = new Uri(config["TransactionNode"]) }) using (var kClient = new HttpClient { BaseAddress = new Uri(config["Kdata"]) }) { foreach (var x in tokens) { try { var currentTokenInfo = tokenInfoList.FirstOrDefault(t => t.Id == x.Id); var currentPriceJavascript = tokenRepository.GetPriceJsText(x.Id); using (var tableResponse = await txClient.PostAsJsonAsync("/v1/chain/get_table_rows", new { code = currentTokenInfo.Basic.Contract.Transfer, scope = currentTokenInfo.Basic.Price_Scope, table = currentTokenInfo.Basic.Price_Table, json = true })) using (var k24hResponse = await kClient.GetAsync($"/api/Candlestick/kyubey-{x.Id}/24h")) { var text = await tableResponse.Content.ReadAsStringAsync(); var text2 = await k24hResponse.Content.ReadAsStringAsync(); var rows = JsonConvert.DeserializeObject <Table>(text).rows; var k24h = 0.0; try { k24h = JsonConvert.DeserializeObject <K24HResponse>(text2).data; } catch { } var buy = await node.InvokeExportAsync <string>("./price", "buyPrice", rows, currentPriceJavascript); var sell = await node.InvokeExportAsync <string>("./price", "sellPrice", rows, currentPriceJavascript); x.BuyPrice = Convert.ToDouble(buy.Contains(".") ? buy.TrimEnd('0') : buy); x.SellPrice = Convert.ToDouble(sell.Contains(".") ? sell.TrimEnd('0') : sell); if (k24h != 0.0) { x.Change = x.BuyPrice / k24h - 1.0; } else { x.Change = 0.0; } Console.WriteLine($"Uploading {x.Id} data..."); using (await kClient.PostAsJsonAsync($"/api/Candlestick", new { values = new[] { new { catalog = "kyubey-" + x.Id, price = x.BuyPrice, utcTime = time } } })) { } await db.SaveChangesAsync(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } { } } await db.SaveChangesAsync(); }
static async Task Main(string[] args) { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json"); var configuration = builder.Build(); var optionsBuilder = new DbContextOptionsBuilder <KyubeyContext>(); optionsBuilder.UseMySql(configuration["MySQL"]); db = new KyubeyContext(optionsBuilder.Options); tronCliClient = new TronCliClient(configuration["WalletWorkPath"], configuration["WalletFilePath"]); Console.WriteLine("Matching bot is starting..."); //await tronCliClient.ImportWalletAsync(cliWalletPwd, "7b81cd82b28dbf9a6efb21de40fb263d83e286644ca04f910f486cb90a7a8357"); await tronCliClient.LoginAsync(cliWalletPwd); while (true) { var posItem = await db.Constants.FirstOrDefaultAsync(x => x.Id == "exchange_pos"); var pos = Convert.ToInt64(posItem.Value); var result = await api.GetContractTransactionsAsync(dexContractAddress); foreach (var x in result.Data.OrderBy(x => x.Block)) { if (x.Block <= pos) { continue; } var tx = await api.GetTransactionAsync(x.TxHash); if (tx.SmartCalls == null) { Thread.Sleep(1000); tx = await api.GetTransactionAsync(x.TxHash); } if (tx.SmartCalls == null) { Thread.Sleep(3000); tx = await api.GetTransactionAsync(x.TxHash); } if (tx.SmartCalls == null) { Thread.Sleep(5000); tx = await api.GetTransactionAsync(x.TxHash); } var owner = tx.SmartCalls.First().Owner; var call = tx.SmartCalls.First().Calls.FirstOrDefault(y => y.Name == "exchange"); if (call == null) { continue; } var bidSymbol = call.Parameters.First(y => y.Name == "bid").Value; var bidAmount = Convert.ToInt64(call.Parameters.First(y => y.Name == "bidamount").Value); var askSymbol = call.Parameters.First(y => y.Name == "ask").Value; var askAmount = Convert.ToInt64(call.Parameters.First(y => y.Name == "askamount").Value); var transferHash = await GetTransferHashAsync(owner, bidAmount, bidSymbol); if (transferHash == null) { if (!db.TronTrades.Any(t => t.Id == x.TxHash)) { db.TronTrades.Add(new TronTrade { Id = x.TxHash, Status = TronTradeStatus.ValidateFailed, Account = owner, AskAmount = askAmount, AskSymbol = askSymbol, BidAmount = bidAmount, BidSymbol = bidSymbol, Time = new DateTime(x.Timestamp), TransferHash = null }); await db.SaveChangesAsync(); } continue; } var dbInstance = db.TronTrades.FirstOrDefault(t => t.Id == x.TxHash); if (dbInstance == null) { db.TronTrades.Add(new TronTrade { Id = x.TxHash, Status = TronTradeStatus.ValidateFailed, Account = owner, AskAmount = askAmount, AskSymbol = askSymbol, BidAmount = bidAmount, BidSymbol = bidSymbol, Time = new DateTime(x.Timestamp), TransferHash = transferHash }); } else { dbInstance.TransferHash = transferHash; } posItem.Value = x.Block.ToString(); await db.SaveChangesAsync(); await DoMatchAsync(transferHash, owner, askSymbol, askAmount, bidSymbol, bidAmount); } await Task.Delay(2000); } }
static async Task DoMatchAsync(string transferHash, string account, string askSymbol, double askAmount, string bidSymbol, double bidAmount) { askAmount /= 1000000; bidAmount /= 1000000; //sell if (askSymbol == "TRX") { var price = askAmount / bidAmount; var order = new DexSellOrder { Account = account, Ask = askAmount, Bid = bidAmount, TokenId = bidSymbol, Time = DateTime.Now, UnitPrice = price }; var orders = await db.DexBuyOrders.Where(x => x.TokenId == bidSymbol) .Where(x => x.UnitPrice >= price) .ToListAsync(); var remianAmount = bidAmount; foreach (var x in orders) { if (remianAmount <= 0) { break; } //token amount var amount = x.Ask < remianAmount ? x.Ask : remianAmount; x.Ask -= amount; // 2元 x.Bid -= amount * x.UnitPrice; // 1个苹果 order.Bid -= amount; order.Ask -= amount * price; remianAmount -= amount; await TransferAsync(x.Account, amount, bidSymbol); await TransferAsync(account, amount *price, askSymbol); db.MatchReceipts.Add(new MatchReceipt { IsSellMatch = true, Asker = account, Ask = amount * x.UnitPrice, Bidder = x.Account, Bid = amount, Time = DateTime.Now, TokenId = bidSymbol, UnitPrice = x.UnitPrice }); if (x.Ask == 0 || x.Bid == 0) { db.Remove(x); } } if (order.Ask != 0 && order.Bid != 0) { db.DexSellOrders.Add(order); } await db.SaveChangesAsync(); } //buy else { double price = bidAmount / askAmount; var order = new DexBuyOrder { TransferHash = transferHash, Account = account, Ask = askAmount, Bid = bidAmount, TokenId = askSymbol, Time = DateTime.Now, UnitPrice = price }; var orders = await db.DexSellOrders.Where(x => x.TokenId == askSymbol) .Where(x => x.UnitPrice <= price) .ToListAsync(); var remianAmount = askAmount; foreach (var x in orders) { if (remianAmount <= 0) { break; } var amount = x.Bid < remianAmount ? x.Bid : remianAmount; x.Bid -= amount; // 1个苹果 x.Ask -= amount * x.UnitPrice; // 2元 order.Ask -= amount; order.Bid -= amount * x.UnitPrice; remianAmount -= amount; await TransferAsync(x.Account, amount *x.UnitPrice, bidSymbol); await TransferAsync(account, amount, askSymbol); db.MatchReceipts.Add(new MatchReceipt { IsSellMatch = false, Asker = account, Ask = amount, Bidder = x.Account, Bid = amount * x.UnitPrice, UnitPrice = price, TokenId = askSymbol, Time = DateTime.Now }); if (x.Ask == 0 || x.Bid == 0) { db.Remove(x); } } if (order.Ask != 0 && order.Bid != 0) { db.DexBuyOrders.Add(order); } await db.SaveChangesAsync(); } }