public static async Task <bool> ExecuteTransaction(this TxProcessInfo processInfo, BitcornContext dbContext) { var sql = new StringBuilder(); if (processInfo.WriteTransactionOutput(sql)) { var rows = await DbOperations.ExecuteSqlRawAsync(dbContext, sql.ToString()); if (rows > 0) { await dbContext.SaveAsync(); try { await OnPostTransaction(processInfo, dbContext); } catch (Exception ex) { await BITCORNLogger.LogError(dbContext, ex, "failed to handle tx callback"); } } return(rows > 0); } return(false); }
public static async Task OnPostTransaction(TxProcessInfo processInfo, BitcornContext dbContext) { if (processInfo.Transactions != null) { decimal subtract = 0; int txCount = 0; var balanceUpdates = new List <object>(); foreach (var txInfo in processInfo.Transactions) { if (txInfo.To != null && txInfo.To.User != null && txInfo.Tx != null) { txCount++; if (txInfo.To.User.IsSocketConnected) { var newBalance = txInfo.To.User.UserWallet.Balance + txInfo.Tx.Amount; balanceUpdates.Add(new { auth0Id = txInfo.To.User.UserIdentity.Auth0Id, balance = newBalance }); } subtract += txInfo.Tx.Amount.Value; } } if (txCount > 0) { if (processInfo.From != null && processInfo.From.IsSocketConnected) { balanceUpdates.Add(new { auth0Id = processInfo.From.UserIdentity.Auth0Id, balance = processInfo.From.UserWallet.Balance - subtract }); } } if (balanceUpdates.Count > 0) { await WebSocketsController.TryBroadcastToBitcornfarms(dbContext, "update-balances", balanceUpdates); } } }
/// <summary> /// method to prepare a transaction, calling this method will not move fund immediately /// </summary> /// <param name="req">transaction request</param> /// <returns>transaction tracker output</returns> public static async Task <TxProcessInfo> ProcessRequest(ITxRequest req, BitcornContext dbContext) { if (req.Amount <= 0) { throw new ArgumentException("Amount"); } //create tx process info that will be tracking this transaction var info = new TxProcessInfo(); //create hashset of receivers var platformIds = new HashSet <PlatformId>(); //set sender user info.From = req.FromUser; //array of recipient ids var toArray = req.To.ToArray(); //calculate total amount of corn being sent var totalAmountRequired = toArray.Length * req.Amount; bool canExecuteAll = false; //check if sender has enough corn to execute all transactions if (info.From != null && info.From.UserWallet.Balance >= totalAmountRequired) { if (info.From.UserWallet.IsLocked != null && info.From.UserWallet.IsLocked == true) { canExecuteAll = false; } else { if (!(await ShouldLockWallet(dbContext, info.From, totalAmountRequired))) { canExecuteAll = true; } } } //get platform ids of recipients foreach (var to in toArray) { var toPlatformId = BitcornUtils.GetPlatformId(to); if (!platformIds.Contains(toPlatformId)) { platformIds.Add(toPlatformId); } } var platformIdArray = platformIds.ToArray(); //get recipients query var userQuery = BitcornUtils.GetUsersForPlatform(platformIdArray, dbContext).AsNoTracking(); //convert into dictionary mapped by their platformid var users = await BitcornUtils.ToPlatformDictionary(platformIdArray, userQuery, dbContext); //create list for receipts var output = new List <TxReceipt>(); //create group transaction id var txid = Guid.NewGuid().ToString(); var sql = new StringBuilder(); //get corn usdt price at this time var cornUsdtPrice = (await ProbitApi.GetCornPriceAsync(dbContext)); foreach (var to in platformIdArray) { var receipt = new TxReceipt(); //if sender is registered, assign it to the receipt if (info.From != null) { receipt.From = new SelectableUser(info.From); } //if recipient is registered, assign it to the receipt if (users.TryGetValue(to.Id, out User user)) { receipt.To = new SelectableUser(user); //if all transactions can be executed, attempt to validate this transaction if (canExecuteAll) { //verifytx returns corntx if this transaction will be made receipt.Tx = VerifyTx(info.From, user, cornUsdtPrice, req.Amount, req.Platform, req.TxType, txid); } //if this transaction will be made, log it into corntx table if (receipt.Tx != null) { dbContext.CornTx.Add(receipt.Tx); } } //add receipt to the output output.Add(receipt); } //set receipts to the transaction tracker info.Transactions = output.ToArray(); return(info); }
public static async Task <TxProcessInfo> ProcessRequest(ITxRequest req, BitcornContext dbContext) { if (req.Amount <= 0) { throw new ArgumentException("Amount"); } var info = new TxProcessInfo(); var platformIds = new HashSet <PlatformId>(); var fromPlatformId = BitcornUtils.GetPlatformId(req.From); var fromUser = await BitcornUtils.GetUserForPlatform(fromPlatformId, dbContext).AsNoTracking().FirstOrDefaultAsync(); info.From = fromUser; var toArray = req.To.ToArray(); var totalAmountRequired = toArray.Length * req.Amount; bool canExecuteAll = false; if (fromUser != null && fromUser.UserWallet.Balance >= totalAmountRequired) { canExecuteAll = true; } foreach (var to in toArray) { var toPlatformId = BitcornUtils.GetPlatformId(to); if (!platformIds.Contains(toPlatformId)) { platformIds.Add(toPlatformId); } } var platformIdArray = platformIds.ToArray(); var userQuery = BitcornUtils.GetUsersForPlatform(platformIdArray, dbContext).AsNoTracking(); var users = await BitcornUtils.ToPlatformDictionary(platformIdArray, userQuery, dbContext); var output = new List <TxReceipt>(); var txid = Guid.NewGuid().ToString(); var sql = new StringBuilder(); foreach (var to in platformIdArray) { var receipt = new TxReceipt(); if (fromUser != null) { receipt.From = new SelectableUser(fromUser); } if (users.TryGetValue(to.Id, out User user)) { receipt.To = new SelectableUser(user); if (canExecuteAll) { receipt.Tx = VerifyTx(fromUser, user, req.Amount, req.Platform, req.TxType, txid); } if (receipt.Tx != null) { dbContext.CornTx.Add(receipt.Tx); } } output.Add(receipt); } info.Transactions = output.ToArray(); return(info); }