Esempio n. 1
0
        public void ProcessChainWithdrawals()
        {
            if (!_tripwire.WithdrawalsEnabled())
            {
                _logger.LogError("Tripwire tripped, exiting ProcessChainWithdrawls()");
                return;
            }
            lock (lockObj)
            {
                // if lockfile exists exit early
                var lockFile = new LockFile(_logger, "chain_withdrawals");
                if (lockFile.IsPresent())
                {
                    _logger.LogError($"lockfile ('{lockFile.MkPath()}) exists");
                    return;
                }

                using (var scope = _services.CreateScope())
                {
                    var settings       = scope.ServiceProvider.GetRequiredService <IOptions <WalletSettings> >().Value;
                    var walletProvider = scope.ServiceProvider.GetRequiredService <IWalletProvider>();
                    var userManager    = scope.ServiceProvider.GetRequiredService <UserManager <ApplicationUser> >();
                    var emailSender    = scope.ServiceProvider.GetRequiredService <IEmailSender>();

                    foreach (var asset in settings.ChainAssetSettings.Keys)
                    {
                        // get wallet
                        var wallet        = walletProvider.GetChain(asset);
                        var assetSettings = walletProvider.ChainAssetSettings(asset);
                        // get pending spends
                        var spends = wallet.PendingSpendsGet(null, new PendingSpendState[] { PendingSpendState.Pending, PendingSpendState.Error }).ToList();
                        foreach (var spend in spends)
                        {
                            // recheck tripwire
                            if (!_tripwire.WithdrawalsEnabled())
                            {
                                _logger.LogError("Tripwire tripped, exiting ProcessChainWithdrawls()");
                                return;
                            }

                            // check and create lockfile to make sure we cant send withdrawals twice
                            if (lockFile.IsPresent())
                            {
                                _logger.LogError($"lockfile ('{lockFile.MkPath()}) exists");
                                return;
                            }
                            var contents = $"Pending spend: {spend.SpendCode}, {spend.State}, {spend.Date}, {spend.Amount} {asset} cents";
                            if (!lockFile.CreateIfNotPresent(contents))
                            {
                                _logger.LogError($"failed to create lockfile ('{lockFile.MkPath()})");
                                return;
                            }

                            _logger.LogInformation($"SpendCode: {spend.SpendCode}, Date: {spend.Date}, Amount: {spend.Amount}, To: {spend.To}, State: {spend.State}");
                            // process withdrawal
                            _logger.LogInformation($"Actioning pending spend: {spend.SpendCode}, asset: {asset}");
                            var err = wallet.PendingSpendAction(spend.SpendCode, assetSettings.FeeMax, assetSettings.FeeUnit, out IEnumerable <WalletTx> wtxs);
                            _logger.LogInformation($"Result: {err}");

                            // save wallet
                            wallet.Save();
                            _logger.LogInformation($"Saved {asset} wallet");

                            // remove lock file now that we have saved wallet status
                            if (!lockFile.RemoveIfPresent())
                            {
                                _logger.LogError($"Failed to remove lockfile ({lockFile.MkPath()})");
                            }

                            if (err == WalletError.Success)
                            {
                                foreach (var wtx in wtxs)
                                {
                                    // get user
                                    System.Diagnostics.Debug.Assert(spend.TagFor != null);
                                    var user = userManager.FindByIdAsync(spend.TagFor.Tag).GetAwaiter().GetResult();
                                    System.Diagnostics.Debug.Assert(user != null);

                                    // send email
                                    emailSender.SendEmailChainWithdrawalConfirmedAsync(user.Email, asset, wallet.AmountToString(wtx.AmountInputs() - wtx.ChainTx.Fee), wtx.ChainTx.TxId).GetAwaiter().GetResult();
                                    _logger.LogInformation($"Sent email to {user.Email}");
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        public void ProcessFiatWithdrawals()
        {
            if (!_tripwire.WithdrawalsEnabled())
            {
                _logger.LogError("Tripwire tripped, exiting ProcessFiatWithdrawls()");
                return;
            }
            lock (lockObj)
            {
                // if lockfile exists exit early
                var lockFile = new LockFile(_logger, "fiat_withdrawals");
                if (lockFile.IsPresent())
                {
                    _logger.LogError($"lockfile ('{lockFile.MkPath()}) exists");
                    return;
                }

                using (var scope = _services.CreateScope())
                {
                    var settings         = scope.ServiceProvider.GetRequiredService <IOptions <WalletSettings> >().Value;
                    var fiatSettings     = scope.ServiceProvider.GetRequiredService <IOptions <FiatProcessorSettings> >().Value;
                    var exchangeSettings = scope.ServiceProvider.GetRequiredService <IOptions <ExchangeSettings> >().Value;
                    var apiSettings      = scope.ServiceProvider.GetRequiredService <IOptions <ApiSettings> >().Value;
                    var walletProvider   = scope.ServiceProvider.GetRequiredService <IWalletProvider>();
                    var userManager      = scope.ServiceProvider.GetRequiredService <UserManager <ApplicationUser> >();
                    var emailSender      = scope.ServiceProvider.GetRequiredService <IEmailSender>();
                    var context          = scope.ServiceProvider.GetRequiredService <ApplicationDbContext>();

                    foreach (var asset in settings.BankAccounts.Keys)
                    {
                        if (!fiatSettings.PayoutsEnabled || !fiatSettings.PayoutsAssets.Contains(asset))
                        {
                            // exit as there is no fiat payment server
                            continue;
                        }

                        // get wallet
                        var wallet = walletProvider.GetFiat(asset);
                        // get pending withdrawals
                        var withdrawals = wallet.GetPendingWithdrawals().ToList();
                        foreach (var withdrawal in withdrawals)
                        {
                            // recheck tripwire
                            if (!_tripwire.WithdrawalsEnabled())
                            {
                                _logger.LogError("Tripwire tripped, exiting ProcessFiatWithdrawls()");
                                return;
                            }

                            // check and create lockfile to make sure we cant send withdrawals twice
                            if (lockFile.IsPresent())
                            {
                                _logger.LogError($"lockfile ('{lockFile.MkPath()}) exists");
                                return;
                            }
                            var contents = $"Pending fiat withdrawal: {withdrawal.DepositCode}, {withdrawal.Date}, {withdrawal.Amount} {asset} cents";
                            if (!lockFile.CreateIfNotPresent(contents))
                            {
                                _logger.LogError($"failed to create lockfile ('{lockFile.MkPath()})");
                                return;
                            }

                            _logger.LogInformation($"Pending Fiat Withdrawal: {withdrawal.DepositCode}, Date: {withdrawal.Date}, Amount: {withdrawal.Amount}, To: {withdrawal.AccountNumber}");
                            // process withdrawal

                            var payoutReq = RestUtils.GetFiatPayoutRequest(fiatSettings, withdrawal.DepositCode);
                            if (payoutReq == null)
                            {
                                var user = userManager.FindByIdAsync(withdrawal.Tag.Tag).GetAwaiter().GetResult();
                                if (user != null && user.UserName == apiSettings.Broker.BrokerTag)
                                {
                                    user = null;
                                    var bow = context.BrokerOrderFiatWithdrawals.SingleOrDefault(o => o.DepositCode == withdrawal.DepositCode);
                                    if (bow != null)
                                    {
                                        var order = context.BrokerOrders.SingleOrDefault(o => o.Id == bow.BrokerOrderId);
                                        if (order != null)
                                        {
                                            user = userManager.FindByIdAsync(order.ApplicationUserId).GetAwaiter().GetResult();
                                        }
                                    }
                                }
                                if (user == null)
                                {
                                    _logger.LogError($"failed to find user for withdrawal ('{withdrawal.DepositCode})");
                                    continue;
                                }
                                payoutReq = RestUtils.CreateFiatPayoutRequest(_logger, exchangeSettings, fiatSettings, withdrawal.DepositCode, asset, wallet.AmountToDecimal(withdrawal.Amount), withdrawal.AccountNumber, user.Email);
                                if (payoutReq == null)
                                {
                                    _logger.LogError($"fiat payout request creation failed ({withdrawal.DepositCode})");
                                }
                            }
                            else if (payoutReq.Status.ToLower() == viafront3.Models.ApiViewModels.ApiRequestStatus.Completed.ToString().ToLower())
                            {
                                wallet.UpdateWithdrawal(payoutReq.Token, DateTimeOffset.UtcNow.ToUnixTimeSeconds(), Convert.ToInt64(payoutReq.Amount), "");
                                _logger.LogInformation($"Payout confirmed for withdrawal {withdrawal.DepositCode}");
                            }

                            // save wallet
                            wallet.Save();
                            _logger.LogInformation($"Saved {asset} wallet");

                            // remove lock file now that we have saved wallet status
                            if (!lockFile.RemoveIfPresent())
                            {
                                _logger.LogError($"Failed to remove lockfile ({lockFile.MkPath()})");
                            }

                            // send email if withdrawal completed
                            if (wallet.GetTx(withdrawal.DepositCode).BankTx != null)
                            {
                                // get user
                                System.Diagnostics.Debug.Assert(withdrawal.Tag != null);
                                var user = userManager.FindByIdAsync(withdrawal.Tag.Tag).GetAwaiter().GetResult();
                                System.Diagnostics.Debug.Assert(user != null);

                                // send email
                                emailSender.SendEmailFiatWithdrawalConfirmedAsync(user.Email, asset, wallet.AmountToString(withdrawal.Amount), withdrawal.DepositCode).GetAwaiter().GetResult();
                                _logger.LogInformation($"Sent email to {user.Email}");
                            }
                        }
                    }
                }
            }
        }