public bool WriteTransactionOutput(StringBuilder sql)
        {
            if (From == null)
            {
                return(false);
            }

            decimal    totalAmount = 0;
            decimal    singleTx    = 0;
            List <int> recipients  = new List <int>();

            for (int i = 0; i < Transactions.Length; i++)
            {
                if (Transactions[i].Tx != null)
                {
                    totalAmount += Transactions[i].Tx.Amount.Value;
                    recipients.Add(Transactions[i].To.UserId);
                    singleTx = Transactions[i].Tx.Amount.Value;
                }
            }
            TotalAmount     = totalAmount;
            ValidRecipients = recipients.ToArray();
            if (ValidRecipients.Length > 0)
            {
                sql.Append(TxUtils.ModifyNumber(nameof(UserWallet), nameof(UserWallet.Balance), singleTx, '+', nameof(UserWallet.UserId), ValidRecipients));
                sql.Append(TxUtils.ModifyNumber(nameof(UserWallet), nameof(UserWallet.Balance), totalAmount, '-', nameof(UserWallet.UserId), From.UserId));
                return(true);
            }
            return(false);
        }
        public static async Task <CornTx> DebitWithdrawTx(string cornaddy, string txId, User user, WalletServer server, decimal amount, BitcornContext dbContext, string platform, int emptyUser)
        {
            if (user.UserWallet.Balance >= amount)
            {
                var sql = new StringBuilder();
                sql.Append(TxUtils.ModifyNumber(nameof(UserWallet), nameof(UserWallet.Balance), amount, '-', nameof(UserWallet.UserId), user.UserId));
                sql.Append(TxUtils.ModifyNumber(nameof(WalletServer), nameof(WalletServer.ServerBalance), amount, '-', nameof(WalletServer.Id), server.Id));
                await DbOperations.ExecuteSqlRawAsync(dbContext, sql.ToString());

                var log = new CornTx();
                log.BlockchainTxId = txId;
                log.Amount         = amount;
                log.Timestamp      = DateTime.Now;
                log.TxType         = "$withdraw";
                log.TxGroupId      = Guid.NewGuid().ToString();
                log.Platform       = platform;
                log.ReceiverId     = emptyUser;
                log.SenderId       = user.UserId;
                log.CornAddy       = cornaddy;

                var price = log.UsdtPrice = await ProbitApi.GetCornPriceAsync(dbContext);

                log.TotalUsdtValue = price * amount;
                dbContext.CornTx.Add(log);
                await dbContext.SaveAsync();

                return(log);
            }
            return(null);
        }
        public async Task <int> Payout([FromBody] HashSet <string> chatters)
        {
            try
            {
                var grouping = (await _dbContext.JoinUserModels().Where(u => chatters.Contains(u.UserIdentity.TwitchId))
                                .AsNoTracking()
                                .ToArrayAsync()).GroupBy(u => u.SubTier).ToArray();

                decimal       total       = 0;
                int           changedRows = 0;
                StringBuilder sql         = new StringBuilder();

                var pk = nameof(UserWallet.UserId);
                foreach (var group in grouping)
                {
                    decimal payout = 0;
                    var     level  = group.Key;
                    if (level == 0)
                    {
                        continue;
                    }
                    var ids = group.Select(u => u.UserId).ToArray();
                    if (level == 1)
                    {
                        payout = 0.25m;
                    }
                    else if (level == 2)
                    {
                        payout = .5m;
                    }
                    else
                    {
                        payout = 1;
                    }
                    sql.Append(TxUtils.ModifyNumber(nameof(UserWallet), nameof(UserWallet.Balance), payout, '+', pk, ids));
                    sql.Append(TxUtils.ModifyNumber(nameof(UserStat), nameof(UserStat.EarnedIdle), payout, '+', pk, ids));

                    int count = await _dbContext.Database.ExecuteSqlRawAsync(sql.ToString());

                    total       += payout * count;
                    changedRows += count;
                }
                if (changedRows > 0)
                {
                    await _dbContext.Database.ExecuteSqlRawAsync(TxUtils.ModifyNumber(nameof(UserWallet), nameof(UserWallet.Balance), total, '-', pk, BitcornHubPK));
                }
                //this endpoint is called frequently so can use this to check if there are tx's that need to be refunded
                await TxUtils.RefundUnclaimed(_dbContext);

                return(changedRows / 2);
            }
            catch (Exception e)
            {
                await BITCORNLogger.LogError(_dbContext, e);

                throw e;
            }
        }
Example #4
0
        public static async Task BonusPayout(BitcornContext dbContext, UserReferral userReferral, Referrer referrer, User user, User referrerUser,
                                             UserStat referrerStat)
        {
            if (userReferral != null &&
                userReferral.SignupReward != null &&
                userReferral.MinimumBalanceDate != null &&
                userReferral.WalletDownloadDate != null &&
                userReferral.SyncDate != null &&
                userReferral.Bonus == null &&
                userReferral.ReferrerBonus == null &&
                userReferral.UserSubscriptionId == null &&
                referrer != null &&
                !user.IsBanned &&
                !referrerUser.IsBanned)
            {
                var subQuery = SubscriptionUtils.GetActiveSubscription(dbContext, user, "BITCORNFarms", 1);
                if (subQuery == null)
                {
                    return;
                }

                var userSubInfo = await subQuery.FirstOrDefaultAsync();

                if (userSubInfo == null)
                {
                    return;
                }

                userReferral.UserSubscriptionId = userSubInfo.UserSubcriptionTierInfo.UserSubscription.UserSubscriptionId;

                var amount      = BONUS_PAYOUT;
                var bonusReward = await TxUtils.SendFromBitcornhub(user, amount, "BITCORNFarms", "Referral bonus reward", dbContext);

                if (IsValidReferrer(referrer))
                {
                    if (bonusReward)
                    {
                        userReferral.Bonus = DateTime.Now;
                        await LogReferralTx(dbContext, user.UserId, amount, "Recruit bonus reward");

                        var referrerBonusReward = await TxUtils.SendFromBitcornhub(referrerUser, amount, "BITCORNFarms", "Referral bonus reward", dbContext);

                        if (referrerBonusReward)
                        {
                            await UpdateYtdTotal(dbContext, referrer, amount);
                            await LogReferralTx(dbContext, referrerUser.UserId, amount, "Referral bonus reward");

                            referrerStat.TotalReferralRewardsCorn += amount;
                            referrerStat.TotalReferralRewardsUsdt += (amount * await ProbitApi.GetCornPriceAsync(dbContext));
                            userReferral.ReferrerBonus             = DateTime.Now;
                        }
                    }
                }
            }
        }
        static async Task <bool> ShareSubscriptionPaymentWithReferrer(BitcornContext dbContext,
                                                                      Subscription subInfo,
                                                                      decimal cost,
                                                                      SubTx subTx,
                                                                      Referrer referrer,
                                                                      User referrerUser,
                                                                      User subscriptionPaymentRecipient)
        {
            if (referrer.EnableSubscriptionRewards)
            {
                //get referrer user info
                if (!subInfo.RestrictReferralRewards || (subInfo.RestrictReferralRewards && (referrerUser.Level == "BEST" ||
                                                                                             referrerUser.Level == "BAIT" ||
                                                                                             referrerUser.IsAdmin() ||
                                                                                             referrer.Tier >= 3)))
                {
                    //calculate amount that will be sent to the referrer
                    var referralShare = cost * subInfo.ReferrerPercentage.Value;
                    //prepare transaction to the referrer
                    var referralShareTx = await TxUtils.PrepareTransaction(subscriptionPaymentRecipient, referrerUser, referralShare, "BITCORNFarms", "$sub referral share", dbContext);

                    //make sure stat tracking values have been initialized
                    if (referrerUser.UserStat.TotalReferralRewardsCorn == null)
                    {
                        referrerUser.UserStat.TotalReferralRewardsCorn = 0;
                    }
                    //make sure stat tracking values have been initialized
                    if (referrerUser.UserStat.TotalReferralRewardsUsdt == null)
                    {
                        referrerUser.UserStat.TotalReferralRewardsUsdt = 0;
                    }
                    //increment total received corn rewards
                    referrerUser.UserStat.TotalReferralRewardsCorn += referralShare;
                    //inceremnt total received usdt rewards
                    referrerUser.UserStat.TotalReferralRewardsUsdt +=
                        ((referralShare) * (await ProbitApi.GetCornPriceAsync(dbContext)));
                    //execute transaction
                    if (await TxUtils.ExecuteTransaction(referralShareTx, dbContext))
                    {
                        //if transaction was made, log & update ytd total
                        await ReferralUtils.UpdateYtdTotal(dbContext, referrer, referralShare);

                        var referralTx = await ReferralUtils.LogReferralTx(dbContext, referrerUser.UserId, referralShare, "$sub referral share");

                        subTx.ReferralTxId = referralTx.ReferralTxId;
                        await dbContext.SaveAsync();

                        return(true);
                    }
                }
            }
            return(false);
        }
Example #6
0
        public static async Task ReferralRewards(BitcornContext dbContext, WalletDownload walletDownload, UserReferral userReferral, User referrerUser,
                                                 User user, string type)
        {
            if (user.IsBanned || referrerUser.IsBanned)
            {
                return;
            }

            var referrer = await dbContext.Referrer
                           .FirstOrDefaultAsync(w => w.UserId == walletDownload.ReferralUserId);

            userReferral.WalletDownloadDate = DateTime.Now;

            if (IsValidReferrer(referrer))
            {
                var referralPayoutTotal = await ReferralUtils.TotalReward(dbContext, referrer) + await ReferralUtils.WalletBonusReward(dbContext, referrer, 10);;
                var referrerReward      = await TxUtils.SendFromBitcornhub(referrerUser, referralPayoutTotal, "BITCORNFarms",
                                                                           type, dbContext);

                var referreeReward = await TxUtils.SendFromBitcornhub(user, referrer.Amount + 10, "BITCORNFarms",
                                                                      type, dbContext);

                if (referrerReward && referreeReward)
                {
                    await ReferralUtils.LogReferralTx(dbContext, referrerUser.UserId, referralPayoutTotal,
                                                      type);

                    await ReferralUtils.LogReferralTx(dbContext, user.UserId, referrer.Amount + 10,
                                                      $"Recruit {type}");

                    await ReferralUtils.UpdateYtdTotal(dbContext, referrer, referralPayoutTotal);

                    if (referrerUser.UserStat.TotalReferralRewardsCorn == null)
                    {
                        referrerUser.UserStat.TotalReferralRewardsCorn = 0;
                    }
                    if (referrerUser.UserStat.TotalReferralRewardsUsdt == null)
                    {
                        referrerUser.UserStat.TotalReferralRewardsUsdt = 0;
                    }
                    referrerUser.UserStat.TotalReferralRewardsCorn += referralPayoutTotal;
                    referrerUser.UserStat.TotalReferralRewardsUsdt +=
                        ((referralPayoutTotal) * (await ProbitApi.GetCornPriceAsync(dbContext)));
                    userReferral.WalletDownloadDate = DateTime.Now;
                    await ReferralUtils.BonusPayout(dbContext, userReferral, referrer, user, referrerUser,
                                                    referrerUser.UserStat);
                }
            }
        }
        public async Task <ActionResult <object> > GetSold24()
        {
            decimal sold24 = 0;

            try
            {
                sold24 = await TxUtils.GetSoldCorn24h(_dbContext);
            }
            catch
            {
            }

            return(new
            {
                sold24,
                available = Math.Abs(TxController.SELL_CORN_CAP_24H - sold24)
            });
        }
Example #8
0
        public virtual async Task OnSyncSuccess(DateTime?socialAccountCreationDate, PlatformId platformId)
        {
            await TxUtils.TryClaimTx(platformId, null, _dbContext);

            var key = $"{platformId.Platform}|{platformId.Id}";

            if (!(await _dbContext.SocialIdentity.AnyAsync(s => s.PlatformId == key)))
            {
                if (socialAccountCreationDate != null && DateTime.Now > socialAccountCreationDate.Value.AddDays(7))
                {
                    await ReferralUtils.UpdateReferralSync(_dbContext, platformId);
                }

                _dbContext.SocialIdentity.Add(new SocialIdentity()
                {
                    PlatformId = key,
                    Timestamp  = DateTime.Now
                });
                await _dbContext.SaveAsync();
            }
        }
        public static async Task <CornTx> DebitWithdrawTx(string txId, User user, WalletServer server, decimal amount, BitcornContext dbContext, string platform)
        {
            if (user.UserWallet.Balance >= amount)
            {
                var sql = new StringBuilder();
                sql.Append(TxUtils.ModifyNumber(nameof(UserWallet), nameof(UserWallet.Balance), amount, '-', nameof(UserWallet.UserId), user.UserId));
                sql.Append(TxUtils.ModifyNumber(nameof(WalletServer), nameof(WalletServer.ServerBalance), amount, '-', nameof(WalletServer.Id), server.Id));
                await dbContext.Database.ExecuteSqlRawAsync(sql.ToString());

                var log = new CornTx();
                log.BlockchainTxId = txId;
                log.Amount         = amount;
                log.Timestamp      = DateTime.Now;
                log.TxType         = "$withdraw";
                log.TxGroupId      = Guid.NewGuid().ToString();
                log.Platform       = platform;
                log.ReceiverId     = user.UserId;
                dbContext.CornTx.Add(log);
                await dbContext.SaveAsync();

                return(log);
            }
            return(null);
        }
        public async Task <UserWallet> Wallet([FromRoute] string id)
        {
            var platformId = BitcornUtils.GetPlatformId(id);
            var user       = await BitcornUtils.GetUserForPlatform(platformId, _dbContext).FirstOrDefaultAsync();

            if (user != null)
            {
                var userWallet = user.UserWallet;
                if (!UserLockCollection.Lock(userWallet.UserId))
                {
                    return(userWallet);
                }
                try
                {
                    var referralId = _dbContext.UserReferral.FirstOrDefault(r => r.UserId == userWallet.UserId)?.ReferralId;
                    if (referralId != 0 && referralId != null)
                    {
                        var userReferral = await _dbContext.UserReferral.FirstOrDefaultAsync(r => r.UserId == userWallet.UserId);

                        var referrer = await _dbContext.Referrer.FirstOrDefaultAsync(r => r.ReferralId == userReferral.ReferralId);

                        var referrerUser = await _dbContext.JoinUserModels().FirstOrDefaultAsync(w => w.UserId == referrer.UserId);

                        var referrerStat = await _dbContext.UserStat.FirstOrDefaultAsync(s => s.UserId == referrer.UserId);

                        await ReferralUtils.BonusPayout(_dbContext, userReferral, referrer, user, referrerUser, referrerStat);

                        if (referrer != null &&
                            userReferral != null &&
                            userReferral.MinimumBalanceDate == null &&
                            userWallet.Balance >= MIN_BALANCE_QUEST_AMOUNT)
                        {
                            if (referrer.YtdTotal < 600 || (referrer.ETag != null && referrer.Key != null))
                            {
                                var referralPayoutTotal = await ReferralUtils.TotalReward(_dbContext, referrer);

                                var miniumBalanceRewardUser = await TxUtils.SendFromBitcornhub(user, referrer.Amount, "BITCORNFarms", "Minium balance reward", _dbContext);

                                var miniumBalanceReward = await TxUtils.SendFromBitcornhub(referrerUser, referralPayoutTotal, "BITCORNFarms", "Minium balance reward", _dbContext);

                                if (miniumBalanceReward && miniumBalanceRewardUser)
                                {
                                    referrerStat.TotalReferralRewardsCorn += referralPayoutTotal;
                                    referrerStat.TotalReferralRewardsUsdt += (referralPayoutTotal * (await ProbitApi.GetCornPriceAsync(_dbContext)));
                                    userReferral.MinimumBalanceDate        = DateTime.Now;
                                    await ReferralUtils.UpdateYtdTotal(_dbContext, referrer, referralPayoutTotal);

                                    await ReferralUtils.LogReferralTx(_dbContext, user.UserId, referrer.Amount, "Recruit minimum balance Reward");

                                    await ReferralUtils.LogReferralTx(_dbContext, referrerUser.UserId, referralPayoutTotal, "Minimum balance Reward");

                                    await ReferralUtils.BonusPayout(_dbContext, userReferral, referrer, user, referrerUser, referrerStat);
                                }
                            }
                        }
                        await _dbContext.SaveAsync();
                    }
                }
                catch (Exception e)
                {
                    await BITCORNLogger.LogError(_dbContext, e, id);
                }
                finally
                {
                    UserLockCollection.Release(userWallet.UserId);
                }
                return(user.UserWallet);
            }
            else
            {
                return(null);
            }
        }
Example #11
0
        public static async Task <BitcornResponse> Withdraw(BitcornContext dbContext, IConfiguration configuration, User user, string cornAddy, decimal amount, string platform)
        {
            var cornResponse = new BitcornResponse();

            cornResponse.WalletAvailable = true;
            try
            {
                if (user.IsBanned)
                {
                    return(cornResponse);
                }
                if (user.UserWallet.Balance < amount)
                {
                    return(cornResponse);
                }

                if (user.UserWallet.IsLocked != null && user.UserWallet.IsLocked.Value)
                {
                    return(cornResponse);
                }

                if ((await TxUtils.ShouldLockWallet(dbContext, user, amount)))
                {
                    return(cornResponse);
                }


                var server = await dbContext.GetWalletServer(user.UserWallet);

                if (!server.Enabled || !server.WithdrawEnabled)
                {
                    cornResponse.WalletAvailable = false;
                    return(cornResponse);
                }

                string accessToken = await GetWalletServerAccessToken(configuration);

                //failed to fetch access token
                if (!CheckAccessTokenExists(accessToken))
                {
                    throw new UnauthorizedAccessException("Failed to fetch wallet server access token");
                }

                using (var client = new WalletClient(server.Endpoint, accessToken))
                {
                    var response = await client.SendToAddressAsync(cornAddy, amount);

                    if (!response.IsError)
                    {
                        string txId = response.GetParsedContent();
                        await DebitWithdrawTx(cornAddy, txId, user, server, amount, dbContext, platform, int.Parse(configuration["Config:EmptyUserId"]));

                        cornResponse.WalletObject = txId;
                    }
                    //we got an error, fetch the internal wallet error code and figure out what to do
                    else
                    {
                        //get wallet error response
                        var error = response.GetError();
                        cornResponse.ErrorCode      = error.Code;
                        cornResponse.DepositAddress = server.DepositAddress;
                        //invalid withdrawal address
                        if (error.Code == WalletErrorCodes.RPC_INVALID_ADDRESS_OR_KEY)
                        {
                            cornResponse.UserError = true;
                        }
                        //too much immature corn to complete this transaction at this time
                        else if (error.Code == WalletErrorCodes.RPC_WALLET_INSUFFICIENT_FUNDS)
                        {
                            cornResponse.WalletAvailable = false;
                        }
                        //wallet server was not reached
                        else if (error.Code == WalletErrorCodes.HTTP_ERROR)
                        {
                            cornResponse.WalletAvailable = false;
                        }
                        try
                        {
                            await BITCORNLogger.LogError(dbContext, new Exception("wallet withdraw failed"), JsonConvert.SerializeObject(new { error = error, amount, cornAddy }));
                        }
                        catch (Exception ex)
                        {
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }

            return(cornResponse);
        }
Example #12
0
        public static async Task UpdateReferralSync(BitcornContext dbContext, PlatformId platformId)
        {
            var user = BitcornUtils.GetUserForPlatform(platformId, dbContext).FirstOrDefault();

            try
            {
                if (user != null && user.UserId != 0)
                {
                    if (user.IsBanned)
                    {
                        return;
                    }
                    if (!UserLockCollection.Lock(user.UserId))
                    {
                        throw new Exception("User is locked");
                    }

                    var userReferral = await dbContext.UserReferral.FirstOrDefaultAsync(u => u.UserId == user.UserId);

                    if (userReferral != null && userReferral.SyncDate == null)
                    {
                        var referrer = await
                                       dbContext.Referrer.FirstOrDefaultAsync(r => r.ReferralId == userReferral.ReferralId);

                        if (referrer != null && (referrer.YtdTotal < 600 || (referrer.ETag != null && referrer.Key != null)))
                        {
                            var referralPayoutTotal = await ReferralUtils.TotalReward(dbContext, referrer);

                            var referrerUser = await dbContext.User.FirstOrDefaultAsync(u => u.UserId == referrer.UserId);

                            if (referrerUser.IsBanned)
                            {
                                if (user != null)
                                {
                                    UserLockCollection.Release(user.UserId);
                                }
                                return;
                            }
                            var referreeReward = await TxUtils.SendFromBitcornhub(user, referrer.Amount, "BITCORNfarms", "Recruit social sync", dbContext);

                            var referrerReward = await TxUtils.SendFromBitcornhub(referrerUser, referralPayoutTotal, "BITCORNfarms", "Social sync", dbContext);

                            if (referrerReward && referreeReward)
                            {
                                userReferral.SyncDate = DateTime.Now;
                                await UpdateYtdTotal(dbContext, referrer, referralPayoutTotal);
                                await LogReferralTx(dbContext, referrer.UserId, referralPayoutTotal, "Social Sync");
                                await LogReferralTx(dbContext, user.UserId, referralPayoutTotal, "Recruit social Sync");

                                var userStat = await dbContext.UserStat.FirstOrDefaultAsync(s => s.UserId == referrer.UserId);

                                userStat.TotalReferralRewardsCorn += referralPayoutTotal;
                                userStat.TotalReferralRewardsUsdt += (referralPayoutTotal * (await ProbitApi.GetCornPriceAsync(dbContext)));
                                await ReferralUtils.BonusPayout(dbContext, userReferral, referrer, user, referrerUser, userStat);
                            }
                        }
                    }

                    await dbContext.SaveAsync();
                }
            }
            catch (Exception e)
            {
                await BITCORNLogger.LogError(dbContext, e, null);

                throw;
            }
            finally
            {
                if (user != null)
                {
                    UserLockCollection.Release(user.UserId);
                }
            }
        }
Example #13
0
        public async Task <FullUser> Register([FromBody] RegistrationData registrationData)
        {
            if (registrationData == null)
            {
                throw new ArgumentNullException("registrationData");
            }
            if (registrationData.Auth0Id == null)
            {
                throw new ArgumentNullException("registrationData.Auth0Id");
            }
            if (registrationData.PlatformId == null)
            {
                throw new ArgumentNullException("registrationData.PlatformId");
            }

            try
            {
                string auth0Id     = registrationData.Auth0Id;
                var    auth0DbUser = await _dbContext.Auth0Query(auth0Id).FirstOrDefaultAsync();

                var platformId = BitcornUtils.GetPlatformId(registrationData.PlatformId);
                switch (platformId.Platform)
                {
                case "twitch":
                    var twitchUser = await TwitchKraken.GetTwitchUser(platformId.Id);

                    var twitchDbUser = await _dbContext.TwitchQuery(platformId.Id).FirstOrDefaultAsync();

                    if (twitchDbUser != null && twitchDbUser.UserIdentity.Auth0Id == null)
                    {
                        //   _dbContext.UserIdentity.Remove(auth0DbUser);
                        auth0DbUser.UserIdentity.TwitchId = twitchDbUser.UserIdentity.TwitchId;
                        CopyIdentity(auth0DbUser.UserIdentity, twitchDbUser.UserIdentity);
                        twitchDbUser.UserIdentity.TwitchUsername = twitchUser.name;
                        twitchDbUser.UserIdentity.Auth0Id        = auth0Id;
                        twitchDbUser.UserIdentity.Auth0Nickname  = auth0DbUser.UserIdentity.Auth0Nickname;

                        await MigrateUser(auth0DbUser, twitchDbUser);


                        await TxUtils.TryClaimTx(platformId, null, _dbContext);

                        return(GetFullUser(twitchDbUser));
                    }
                    else if (twitchDbUser == null && auth0DbUser != null)
                    {
                        auth0DbUser.UserIdentity.TwitchId       = platformId.Id;
                        auth0DbUser.UserIdentity.TwitchUsername = twitchUser.name;
                        await _dbContext.SaveAsync();

                        await TxUtils.TryClaimTx(platformId, null, _dbContext);

                        return(GetFullUser(auth0DbUser));
                    }
                    else if (twitchDbUser != null)
                    {
                        var e = new Exception($"A login id already exists for this twitch id {platformId.Id}");
                        await BITCORNLogger.LogError(_dbContext, e);

                        throw e;
                    }
                    else
                    {
                        var e = new Exception(
                            $"Failed to register twitch {platformId.Id} {auth0Id}");
                        await BITCORNLogger.LogError(_dbContext, e);

                        throw e;
                    }

                case "discord":
                    try
                    {
                        var discordToken = DiscordApi.GetDiscordBotToken(_configuration);
                        var discordUser  = await DiscordApi.GetDiscordUser(discordToken, platformId.Id);

                        var discordDbUser = await _dbContext.DiscordQuery(platformId.Id).FirstOrDefaultAsync();

                        if (discordDbUser != null && discordDbUser.UserIdentity.Auth0Id == null)
                        {
                            //_dbContext.UserIdentity.Remove(auth0DbUser);
                            //await _dbContext.SaveAsync();
                            auth0DbUser.UserIdentity.DiscordId = discordDbUser.UserIdentity.DiscordId;
                            CopyIdentity(auth0DbUser.UserIdentity, discordDbUser.UserIdentity);

                            discordDbUser.UserIdentity.DiscordUsername = DiscordApi.GetUsernameString(discordUser);
                            discordDbUser.UserIdentity.Auth0Id         = auth0Id;
                            discordDbUser.UserIdentity.Auth0Nickname   = auth0DbUser.UserIdentity.Auth0Nickname;
                            await MigrateUser(auth0DbUser, discordDbUser);

                            await TxUtils.TryClaimTx(platformId, null, _dbContext);

                            return(GetFullUser(discordDbUser));
                        }
                        else if (discordDbUser == null && auth0DbUser != null)
                        {
                            auth0DbUser.UserIdentity.DiscordId       = platformId.Id;
                            auth0DbUser.UserIdentity.DiscordUsername = DiscordApi.GetUsernameString(discordUser);

                            await _dbContext.SaveAsync();

                            await TxUtils.TryClaimTx(platformId, null, _dbContext);

                            return(GetFullUser(auth0DbUser));
                        }
                        else if (discordDbUser?.UserIdentity.Auth0Id != null)
                        {
                            var e = new Exception($"A login id already exists for this discord id");
                            await BITCORNLogger.LogError(_dbContext, e, $"Auth0Id already exists for user {platformId.Id}");

                            throw e;
                        }
                        else
                        {
                            var e = new Exception($"Failed to register discord");
                            await BITCORNLogger.LogError(_dbContext, e, $"Failed to register discord id for user {platformId.Id} {auth0Id}");

                            throw e;
                        }
                    }
                    catch (Exception e)
                    {
                        await BITCORNLogger.LogError(_dbContext, e);

                        throw new Exception($"Failed to add user's discord");
                    }

                    throw new Exception($"HOW THE F**K DID YOU GET HERE");

                case "twitter":
                    try
                    {
                        var twitterUser = await TwitterApi.GetTwitterUser(_configuration, platformId.Id);

                        var twitterDbUser = await _dbContext.TwitterQuery(platformId.Id).FirstOrDefaultAsync();

                        if (twitterDbUser != null && twitterDbUser.UserIdentity.Auth0Id == null)
                        {
                            auth0DbUser.UserIdentity.TwitterId = twitterDbUser.UserIdentity.TwitterId;
                            //_dbContext.UserIdentity.Remove(auth0DbUser);
                            CopyIdentity(auth0DbUser.UserIdentity, twitterDbUser.UserIdentity);
                            twitterDbUser.UserIdentity.Auth0Id         = auth0Id;
                            twitterDbUser.UserIdentity.TwitterUsername = twitterUser.Name;
                            twitterDbUser.UserIdentity.Auth0Nickname   = auth0DbUser.UserIdentity.Auth0Nickname;
                            await MigrateUser(auth0DbUser, twitterDbUser);

                            await TxUtils.TryClaimTx(platformId, null, _dbContext);

                            return(GetFullUser(twitterDbUser));
                        }
                        if (twitterDbUser == null && auth0DbUser != null)
                        {
                            auth0DbUser.UserIdentity.TwitterId       = platformId.Id;
                            auth0DbUser.UserIdentity.TwitterUsername = twitterUser.Name;
                            await _dbContext.SaveAsync();

                            await TxUtils.TryClaimTx(platformId, null, _dbContext);

                            return(GetFullUser(auth0DbUser));
                        }
                        if (twitterDbUser?.UserIdentity.Auth0Id != null)
                        {
                            var e = new Exception($"Auth0Id already exists for user {platformId.Id}");
                            await BITCORNLogger.LogError(_dbContext, e);

                            throw e;
                        }
                        var ex = new Exception($"Failed to register twitter id for user {platformId.Id} {auth0Id}");
                        await BITCORNLogger.LogError(_dbContext, ex);

                        throw ex;
                    }
                    catch (Exception e)
                    {
                        await BITCORNLogger.LogError(_dbContext, e);

                        throw e;
                    }
                    throw new Exception($"HOW THE F**K DID YOU GET HERE");

                case "reddit":
                    try
                    {
                        var redditDbUser = await _dbContext.RedditQuery(platformId.Id).FirstOrDefaultAsync();

                        if (redditDbUser != null && redditDbUser.UserIdentity.Auth0Id == null)
                        {
                            auth0DbUser.UserIdentity.RedditId = redditDbUser.UserIdentity.RedditId;
                            CopyIdentity(auth0DbUser.UserIdentity, redditDbUser.UserIdentity);
                            //_dbContext.UserIdentity.Remove(auth0DbUser);
                            redditDbUser.UserIdentity.Auth0Id       = auth0Id;
                            redditDbUser.UserIdentity.Auth0Nickname = auth0DbUser.UserIdentity.Auth0Nickname;
                            await MigrateUser(auth0DbUser, redditDbUser);

                            await TxUtils.TryClaimTx(platformId, null, _dbContext);

                            return(GetFullUser(redditDbUser));
                        }
                        else if (redditDbUser == null && auth0DbUser != null)
                        {
                            auth0DbUser.UserIdentity.RedditId = platformId.Id;
                            await _dbContext.SaveAsync();

                            await TxUtils.TryClaimTx(platformId, null, _dbContext);

                            return(GetFullUser(auth0DbUser));
                        }
                        else if (redditDbUser?.UserIdentity.Auth0Id != null)
                        {
                            var e = new Exception($"Auth0Id already exists for user {platformId.Id}");
                            await BITCORNLogger.LogError(_dbContext, e);

                            throw e;
                        }
                        else
                        {
                            var e = new Exception($"Failed to register reddit id for user {platformId.Id} {platformId.Id}");
                            await BITCORNLogger.LogError(_dbContext, e);

                            throw e;
                        }
                    }
                    catch (Exception e)
                    {
                        await BITCORNLogger.LogError(_dbContext, e);

                        throw e;
                    }

                    throw new Exception($"HOW THE F**K DID YOU GET HERE");

                default:
                    throw new Exception("Invalid platform provided in the Id");
                }
            }
            catch (Exception e)
            {
                throw new Exception($"registration failed for {registrationData}");
            }
            throw new Exception("HOW THE F**K DID YOU GET HERE");
        }
Example #14
0
        public async Task <ActionResult <FullUser> > RegisterNewUser([FromBody] Auth0User auth0User, [FromQuery] string referral = null)
        {
            if (this.GetCachedUser() != null)
            {
                throw new InvalidOperationException();
            }
            if (auth0User == null)
            {
                throw new ArgumentNullException();
            }
            if (!StaticLockCollection.Lock(auth0User.Auth0Id))
            {
                return(StatusCode(UserLockCollection.UserLockedReturnCode));
            }

            var existingUserIdentity = await _dbContext.Auth0Query(auth0User.Auth0Id).Select(u => u.UserIdentity).FirstOrDefaultAsync();

            if (existingUserIdentity?.Auth0Id == auth0User.Auth0Id)
            {
                var user       = _dbContext.User.FirstOrDefault(u => u.UserId == existingUserIdentity.UserId);
                var userWallet = _dbContext.UserWallet.FirstOrDefault(u => u.UserId == existingUserIdentity.UserId);
                var userStat   = _dbContext.UserStat.FirstOrDefault(u => u.UserId == existingUserIdentity.UserId);
                StaticLockCollection.Release(auth0User.Auth0Id);
                return(BitcornUtils.GetFullUser(user, existingUserIdentity, userWallet, userStat));
            }

            int referralId;

            try
            {
                referralId = Convert.ToInt32(referral);
            }
            catch (Exception e)
            {
                referralId = 0;
            }

            try
            {
                var user = CreateUser(auth0User, referralId);
                _dbContext.User.Add(user);
                if (referral != null && referralId != 0)
                {
                    var referrer = await _dbContext.Referrer.FirstOrDefaultAsync(r => r.ReferralId == referralId);

                    if (ReferralUtils.IsValidReferrer(referrer))
                    {
                        var referrerUser = await _dbContext.User.FirstOrDefaultAsync(u => u.UserId == referrer.UserId);

                        if (referrerUser != null && !referrerUser.IsBanned)
                        {
                            var referralPayoutTotal = await ReferralUtils.TotalReward(_dbContext, referrer);

                            var referrerRegistrationReward = await TxUtils.SendFromBitcornhub(referrerUser, referralPayoutTotal, "BITCORNFarms", "Registrations reward", _dbContext);

                            var userRegistrationReward = await TxUtils.SendFromBitcornhub(user, referrer.Amount, "BITCORNFarms", "Recruit registrations reward", _dbContext);

                            if (referrerRegistrationReward && userRegistrationReward)
                            {
                                await ReferralUtils.UpdateYtdTotal(_dbContext, referrer, referralPayoutTotal);

                                await ReferralUtils.LogReferralTx(_dbContext, referrer.UserId, referralPayoutTotal, "Registration reward");

                                await ReferralUtils.LogReferralTx(_dbContext, user.UserId, referrer.Amount, "Recruit registration reward");

                                var referrerStat = await _dbContext.UserStat.FirstOrDefaultAsync(s => s.UserId == referrer.UserId);

                                if (referrerStat != null)
                                {
                                    if (referrerStat.TotalReferrals == null)
                                    {
                                        referrerStat.TotalReferrals = 0;
                                    }
                                    referrerStat.TotalReferrals++;

                                    if (referrerStat.TotalReferralRewardsCorn == null)
                                    {
                                        referrerStat.TotalReferralRewardsCorn = 0;
                                    }
                                    referrerStat.TotalReferralRewardsCorn += referralPayoutTotal;

                                    if (referrerStat.TotalReferralRewardsUsdt == null)
                                    {
                                        referrerStat.TotalReferralRewardsUsdt = 0;
                                    }
                                    referrerStat.TotalReferralRewardsUsdt += (referralPayoutTotal * (await ProbitApi.GetCornPriceAsync(_dbContext)));
                                }
                                user.UserReferral.SignupReward = DateTime.Now;
                            }
                        }
                    }
                }

                await _dbContext.SaveAsync();

                return(BitcornUtils.GetFullUser(user, user.UserIdentity, user.UserWallet, user.UserStat));
            }
            catch (Exception e)
            {
                await BITCORNLogger.LogError(_dbContext, e, JsonConvert.SerializeObject(auth0User));

                throw e;
            }
            finally
            {
                StaticLockCollection.Release(auth0User.Auth0Id);
            }
        }
Example #15
0
        public static async Task <CornTx[]> Deposit(BitcornContext dbContext, WalletDepositRequest request)
        {
            var receipts = new List <CornTx>();

            try
            {
                var server      = dbContext.WalletServer.FirstOrDefault((s) => s.Index == request.Index);
                int newDeposits = 0;

                var sql = new StringBuilder();
                foreach (var payment in request.Payments)
                {
                    decimal amount  = payment.Amount;
                    string  address = payment.Address;
                    string  txid    = payment.TxId;

                    bool isLogged = await dbContext.IsDepositRegistered(txid);

                    if (!isLogged)
                    {
                        newDeposits++;
                        var wallet = await dbContext.WalletByAddress(address);

                        if (wallet != null)
                        {
                            var cornTx = new CornTx();
                            cornTx.Amount         = amount;
                            cornTx.BlockchainTxId = txid;
                            cornTx.ReceiverId     = wallet.UserId;
                            cornTx.SenderId       = null;
                            cornTx.Timestamp      = DateTime.Now;
                            cornTx.TxType         = TransactionType.receive.ToString();
                            cornTx.Platform       = "wallet-server";
                            cornTx.TxGroupId      = Guid.NewGuid().ToString();
                            var deposit = new CornDeposit();
                            deposit.TxId   = txid;
                            deposit.UserId = wallet.UserId;

                            sql.Append(TxUtils.ModifyNumber(nameof(UserWallet), nameof(UserWallet.Balance), amount, '+', nameof(UserWallet.UserId), wallet.UserId));
                            sql.Append(TxUtils.ModifyNumber(nameof(WalletServer), nameof(WalletServer.ServerBalance), amount, '+', nameof(WalletServer.Id), server.Id));

                            dbContext.CornTx.Add(cornTx);
                            dbContext.CornDeposit.Add(deposit);
                            receipts.Add(cornTx);
                        }
                    }
                }

                if (newDeposits > 0)
                {
                    server.LastBalanceUpdateBlock = request.Block;
                    int count = await dbContext.Database.ExecuteSqlRawAsync(sql.ToString());

                    await dbContext.SaveAsync();
                }
            }
            catch (Exception e)
            {
                await BITCORNLogger.LogError(dbContext, e);
            }
            return(receipts.ToArray());
        }
Example #16
0
        /// <summary>
        /// called from client server to create an order tht the user will authorize
        /// </summary>
        public async Task <ActionResult <object> > AuthorizeOrder([FromBody] AuthorizeOrderRequest orderRequest)
        {
            try
            {
                var user = (this.GetCachedUser());
                if (this.GetUserMode() != null && this.GetUserMode() == 1)
                {
                    throw new NotImplementedException();
                }

                if (user != null)
                {
                    if (user.IsBanned)
                    {
                        return(StatusCode(403));
                    }

                    var checkOrder = await GetOrder(orderRequest.OrderId);

                    if (checkOrder == null)
                    {
                        return(StatusCode(404));
                    }
                    var(order, client) = checkOrder.Value;

                    if (order.OrderState != 0)
                    {
                        return(StatusCode((int)HttpStatusCode.Gone));
                    }
                    if (order.ClientId != orderRequest.ClientId)
                    {
                        return(StatusCode((int)HttpStatusCode.BadRequest));
                    }
                    var orderItems = await _dbContext.OrderItem.Where(e => e.OrderId == order.OrderId).ToArrayAsync();

                    if (orderItems.Length > client.OrderMaxSize)
                    {
                        return(StatusCode((int)HttpStatusCode.NotAcceptable));
                    }

                    if (orderItems.Sum(e => e.CornAmount) > client.OrderMaxCost)
                    {
                        return(StatusCode((int)HttpStatusCode.NotAcceptable));
                    }

                    var recipientUser = await _dbContext.JoinUserModels()
                                        .FirstOrDefaultAsync((u) => u.UserId == client.RecipientUser);

                    var cornPrice = await ProbitApi.GetCornPriceAsync(_dbContext);

                    var cornOrderSum   = orderItems.Select(e => e.CornAmount).Sum();
                    var cornCurrentSum = orderItems.Select(e => e.UsdAmount / cornPrice).Sum();
                    var costDiff       = Math.Abs(cornCurrentSum - cornOrderSum);

                    if (costDiff <= client.AcceptedCostDiff)
                    {
                        if (recipientUser != null)
                        {
                            var processInfo = await TxUtils.PrepareTransaction(user,
                                                                               recipientUser,
                                                                               cornOrderSum,
                                                                               client.ClientId,
                                                                               "app:order",
                                                                               _dbContext);

                            var paymentSuccess = await processInfo.ExecuteTransaction(_dbContext);

                            if (paymentSuccess)
                            {
                                var jwt = CreateJwt(client, order, orderItems, cornOrderSum, processInfo.Transactions[0].TxId.Value);

                                order.TxId        = processInfo.Transactions[0].TxId;
                                order.OrderState  = 1;
                                order.CompletedAt = DateTime.Now;

                                await _dbContext.SaveAsync();

                                if (string.IsNullOrEmpty(client.Capture))
                                {
                                    return(new
                                    {
                                        jwt,
                                        txId = order.TxId.Value,
                                        amount = cornOrderSum
                                    });
                                }
                                else
                                {
                                    var restClient  = new RestClient();
                                    var url         = $"{client.Domain}/{client.Capture}";
                                    var redirectUrl = $"{client.Domain}/{client.Redirect}";

                                    var restRequest = new RestRequest(url, Method.POST);
                                    if (client.PostFormat == "application/x-www-form-urlencoded")
                                    {
                                        restRequest.AddHeader("Content-Type", "application/x-www-form-urlencoded");
                                        restRequest.AddObject(new { jwt });
                                    }
                                    else
                                    {
                                        restRequest.AddJsonBody(new { jwt });
                                    }

                                    var restResponse = restClient.Execute(restRequest);
                                    await BITCORNLogger.LogError(_dbContext, new Exception("Order hook callback"), restResponse.Content);

                                    return(new
                                    {
                                        redirect = redirectUrl,
                                        txId = order.TxId.Value,
                                        amount = cornOrderSum
                                    });
                                }
                            }
                            else
                            {
                                return(new
                                {
                                    txId = -1
                                });
                            }
                        }
                    }
                    else
                    {
                        return(StatusCode((int)HttpStatusCode.PaymentRequired));
                    }
                }

                return(StatusCode((int)HttpStatusCode.BadRequest));
            }
            catch (Exception e)
            {
                await BITCORNLogger.LogError(_dbContext, e, JsonConvert.SerializeObject(orderRequest));

                return(StatusCode(500));
            }
        }
        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 TestTipCornToUnregistered()
        {
            var dbContext = TestUtils.CreateDatabase();

            try
            {
                var startFromUser = dbContext.TwitchQuery(_configuration["Config:TestFromUserId"]).FirstOrDefault().UserWallet.Balance;
                var txController  = new TxController(dbContext);

                var request = new TipRequest();
                request.Columns = new string[] { };
                string toTwitchId = "123123";
                request.To       = "twitch|" + toTwitchId;
                request.From     = "twitch|" + _configuration["Config:TestFromUserId"];
                request.Platform = "twitch";
                request.Amount   = 100;

                var toUser = await dbContext.TwitchAsync(toTwitchId);

                dbContext.RemoveRange(dbContext.UnclaimedTx);
                TestUtils.RemoveUserIfExists(dbContext, toUser);

                var response = await txController.Tipcorn(request);

                var receipt = response.Value[0];
                Assert.Null(receipt.Tx);
                Assert.NotNull(receipt.From);
                Assert.Null(receipt.To);

                using (var dbContext2 = TestUtils.CreateDatabase())
                {
                    var endFromUser = dbContext2.TwitchQuery(_configuration["Config:TestFromUserId"]).FirstOrDefault().UserWallet.Balance;
                    Assert.Equal(startFromUser - request.Amount, endFromUser);

                    dbContext2.AddUser(new UserIdentity()
                    {
                        Auth0Id       = "temp",
                        Auth0Nickname = "temp",
                        TwitchId      = toTwitchId
                    }, new UserWallet());
                    var to = await dbContext2.TwitchAsync(toTwitchId);

                    await TxUtils.TryClaimTx(new PlatformId()
                    {
                        Platform = "twitch", Id = toTwitchId
                    }, to, dbContext2);
                }
                using (var dbContext2 = TestUtils.CreateDatabase())
                {
                    var to = await dbContext2.TwitchAsync(toTwitchId);

                    Assert.Equal(request.Amount, to.UserWallet.Balance);
                    var claim2 = await TxUtils.TryClaimTx(new PlatformId()
                    {
                        Platform = "twitch", Id = toTwitchId
                    }, to, dbContext2);;
                    Assert.Equal(0, claim2);
                }
            }
            finally
            {
                dbContext.Dispose();
            }
        }
        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;
            }
        }
        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;
            }
        }