/// <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);
        }