public async Task <ActionResult <TxReceipt[]> > Rain([FromBody] RainRequest rainRequest) { try { if (rainRequest == null) { throw new ArgumentNullException(); } if (rainRequest.From == null) { throw new ArgumentNullException(); } if (rainRequest.To == null) { throw new ArgumentNullException(); } if (rainRequest.Amount <= 0) { return(StatusCode((int)HttpStatusCode.BadRequest)); } var processInfo = await TxUtils.ProcessRequest(rainRequest, _dbContext); var transactions = processInfo.Transactions; if (transactions != null && transactions.Length > 0) { StringBuilder sql = new StringBuilder(); if (processInfo.WriteTransactionOutput(sql)) { string pk = nameof(UserStat.UserId); string table = nameof(UserStat); var recipients = processInfo.ValidRecipients; var fromId = transactions[0].From.UserId; var recipientStats = new List <ColumnValuePair>(); recipientStats.Add(new ColumnValuePair(nameof(UserStat.RainedOn), 1)); recipientStats.Add(new ColumnValuePair(nameof(UserStat.RainedOnTotal), rainRequest.Amount)); sql.Append(TxUtils.ModifyNumbers(table, recipientStats, '+', pk, recipients)); sql.Append(TxUtils.UpdateNumberIfTop(table, nameof(UserStat.TopRainedOn), rainRequest.Amount, pk, recipients)); var senderStats = new List <ColumnValuePair>(); senderStats.Add(new ColumnValuePair(nameof(UserStat.Rained), 1)); senderStats.Add(new ColumnValuePair(nameof(UserStat.RainTotal), processInfo.TotalAmount)); sql.Append(TxUtils.ModifyNumbers(table, senderStats, '+', pk, fromId)); sql.Append(TxUtils.UpdateNumberIfTop(table, nameof(UserStat.TopRain), processInfo.TotalAmount, pk, fromId)); await _dbContext.Database.ExecuteSqlRawAsync(sql.ToString()); await _dbContext.SaveAsync(IsolationLevel.RepeatableRead); } await TxUtils.AppendTxs(transactions, _dbContext, rainRequest.Columns); } return(processInfo.Transactions); } catch (Exception e) { await BITCORNLogger.LogError(_dbContext, e); throw e; } }
private static async Task <SubscriptionResponse> ProcessSubscription(BitcornContext dbContext, SubscriptionResponse output, SubRequest subRequest, Subscription subInfo, SubscriptionTier requestedTierInfo, User user) { decimal cost = 0; //if tier usdt cost has been initialized, the corn cost has to be calculated if (requestedTierInfo.CostUsdt != null && requestedTierInfo.CostUsdt > 0) { cost = await CalculateUsdtToCornCost(dbContext, requestedTierInfo); } // check if cost is initialized properly else if (requestedTierInfo.CostCorn != null && requestedTierInfo.CostCorn > 0) { cost = requestedTierInfo.CostCorn.Value; } else { throw new ArgumentException($"Invalid cost setting on subscription tier id:{requestedTierInfo.SubscriptionId}"); } //set the amount that will be removed from subscriber to the response object output.Cost = cost; //initialize array of existing subscriptions UserSubcriptionTierInfo[] existingSubscriptions = new UserSubcriptionTierInfo[0]; if (user != null) { //set data to existing subscriptions array existingSubscriptions = await GetUserSubscriptions(dbContext, user) .Where(t => t.SubscriptionTier.SubscriptionId == subInfo.SubscriptionId).ToArrayAsync(); } //initialize reference to existing subtierinfo UserSubcriptionTierInfo existingSubscription = null; //initialize current substate var subState = SubscriptionState.None; //if any subscriptions were found if (existingSubscriptions.Any()) { //set existing subtierinfo existingSubscription = existingSubscriptions[0]; //if sub has expired, set substate to expired if (subInfo.HasExpired(existingSubscription.UserSubscription)) { subState = SubscriptionState.Expired; } //if existing sub has not expired, but the tier is below, set subState to TierDown else if (existingSubscription.SubscriptionTier.Tier < requestedTierInfo.Tier) { subState = SubscriptionState.TierDown; } //else, the user is subscribed else { subState = SubscriptionState.Subscribed; } } //initialize reference to usersubscription & tx request UserSubscription sub = null; TxRequest txRequest = null; //if current user sub state is not subscribed & the client confirmed the cost to be equal to the cost amount, attempt to subscribe var costDiff = Math.Abs(subRequest.Amount - cost); if (subState != SubscriptionState.Subscribed && costDiff <= 100000)//subRequest.Amount == cost) { //initialize recipient of the transaction string[] to = new string[1]; //default to bitcornhub if no subscription owner has been set int recipientId = TxUtils.BitcornHubPK; //if subscription owner is set, overwrite bitcornhub if (subInfo.OwnerUserId != null && subInfo.OwnerUserId > 0) { recipientId = subInfo.OwnerUserId.Value; } to[0] = $"userid|{recipientId}"; //initialize tx request txRequest = new TxRequest(user, cost, subRequest.Platform, "$sub", to); //prepare transaction for saving var processInfo = await TxUtils.ProcessRequest(txRequest, dbContext); var transactions = processInfo.Transactions; if (transactions != null && transactions.Length > 0) { StringBuilder sql = new StringBuilder(); //check if transaction can be executed if (processInfo.WriteTransactionOutput(sql)) { //transaction is ready to be saved switch (subState) { case SubscriptionState.None: //user was previously not subscribed, create instance of usersubscription and point it to the user sub = new UserSubscription(); sub.SubscriptionId = subInfo.SubscriptionId; sub.SubscriptionTierId = requestedTierInfo.SubscriptionTierId; sub.UserId = user.UserId; sub.FirstSubDate = DateTime.Now; sub.SubCount = 1; dbContext.UserSubscription.Add(sub); break; case SubscriptionState.TierDown: case SubscriptionState.Expired: //previous subscription was found, update subscription tier existingSubscription.UserSubscription.SubscriptionTierId = requestedTierInfo.SubscriptionTierId; existingSubscription.UserSubscription.SubCount += 1; sub = existingSubscription.UserSubscription; break; default: break; } //set subscription date to now sub.LastSubDate = DateTime.Now; await DbOperations.ExecuteSqlRawAsync(dbContext, sql.ToString()); await dbContext.SaveAsync(IsolationLevel.RepeatableRead); //create subtx that will link user, corntx and usersubscription together var subTx = new SubTx(); subTx.UserId = user.UserId; subTx.SubTxId = transactions[0].TxId.Value; subTx.UserSubscriptionId = sub.UserSubscriptionId; dbContext.SubTx.Add(subTx); //if user was not subscribed before, attempt to share the payment with a referrer if (!await TrySharePaymentWithReferrer(dbContext, output, subRequest, subInfo, requestedTierInfo, user, recipientId, cost, subState, subTx)) { await dbContext.SaveAsync(); } subState = SubscriptionState.Subscribed; } //append receipt object with what client requested await TxUtils.AppendTxs(transactions, dbContext, subRequest.Columns); var tx = transactions[0]; output.TxId = tx.TxId; output.User = tx.From; } } //couldn't process transaction if (txRequest == null) { //fill out response object await PopuplateUserResponse(dbContext, subRequest, output, user); if (existingSubscription != null) { sub = existingSubscription.UserSubscription; } } if (subState == SubscriptionState.Subscribed && sub != null) { var end = output.SubscriptionEndTime = sub.LastSubDate.Value.AddDays(subInfo.Duration); //calculate days left output.DaysLeft = Math.Ceiling((end.Value - DateTime.Now).TotalDays); //setup sub info output.UserSubscriptionInfo = await GetUserSubscriptions(dbContext, user) .Where(t => t.SubscriptionTier.SubscriptionId == subInfo.SubscriptionId).FirstOrDefaultAsync(); } return(output); }
public async Task <ActionResult <TxReceipt[]> > Tipcorn([FromBody] TipRequest tipRequest) { if (tipRequest == null) { throw new ArgumentNullException(); } if (tipRequest.From == null) { throw new ArgumentNullException(); } if (tipRequest.To == null) { throw new ArgumentNullException(); } if (tipRequest.To == tipRequest.From) { return(StatusCode((int)HttpStatusCode.BadRequest)); } if (tipRequest.Amount <= 0) { return(StatusCode((int)HttpStatusCode.BadRequest)); } try { var processInfo = await TxUtils.ProcessRequest(tipRequest, _dbContext); var transactions = processInfo.Transactions; if (transactions != null && transactions.Length > 0) { StringBuilder sql = new StringBuilder(); if (processInfo.WriteTransactionOutput(sql)) { var receipt = transactions[0]; if (receipt.Tx != null) { var to = receipt.To.User.UserStat; var from = receipt.From.User.UserStat; var amount = tipRequest.Amount; string table = nameof(UserStat); var pk = nameof(UserStat.UserId); var fromStats = new List <ColumnValuePair>(); fromStats.Add(new ColumnValuePair(nameof(UserStat.Tip), 1)); fromStats.Add(new ColumnValuePair(nameof(UserStat.TipTotal), amount)); sql.Append(TxUtils.ModifyNumbers(table, fromStats, '+', pk, from.UserId)); var toStats = new List <ColumnValuePair>(); toStats.Add(new ColumnValuePair(nameof(UserStat.Tipped), 1)); toStats.Add(new ColumnValuePair(nameof(UserStat.TippedTotal), amount)); sql.Append(TxUtils.ModifyNumbers(table, toStats, '+', pk, to.UserId)); sql.Append(TxUtils.UpdateNumberIfTop(table, nameof(UserStat.TopTip), amount, pk, from.UserId)); sql.Append(TxUtils.UpdateNumberIfTop(table, nameof(UserStat.TopTipped), amount, pk, to.UserId)); await _dbContext.Database.ExecuteSqlRawAsync(sql.ToString()); await _dbContext.SaveAsync(IsolationLevel.RepeatableRead); } } else { if (processInfo.From != null && !processInfo.From.IsBanned && processInfo.Transactions[0].To == null) { if (processInfo.From.UserWallet.Balance >= tipRequest.Amount) { var unclaimed = new UnclaimedTx(); unclaimed.TxType = ((ITxRequest)tipRequest).TxType; unclaimed.Platform = tipRequest.Platform; unclaimed.ReceiverPlatformId = BitcornUtils.GetPlatformId(tipRequest.To).Id; unclaimed.Amount = tipRequest.Amount; unclaimed.Timestamp = DateTime.Now; unclaimed.SenderUserId = processInfo.From.UserId; unclaimed.Expiration = DateTime.Now.AddMinutes(TimeToClaimTipMinutes); unclaimed.Claimed = false; unclaimed.Refunded = false; _dbContext.UnclaimedTx.Add(unclaimed); await _dbContext.Database.ExecuteSqlRawAsync(TxUtils.ModifyNumber(nameof(UserWallet), nameof(UserWallet.Balance), tipRequest.Amount, '-', nameof(UserWallet.UserId), processInfo.From.UserId)); await _dbContext.SaveAsync(); } } } await TxUtils.AppendTxs(transactions, _dbContext, tipRequest.Columns); } return(transactions); } catch (Exception e) { await BITCORNLogger.LogError(_dbContext, e); throw e; } }