Ejemplo n.º 1
0
        public bool FiatWithdrawToCustomer(ApplicationUser brokerUser, BrokerOrder order)
        {
            var asset  = order.AssetReceive;
            var amount = order.AmountReceive;

            var wallet = _walletProvider.GetFiat(asset);

            if (wallet == null)
            {
                _logger.LogError($"No fiat wallet for {asset}");
                return(false);
            }

            var via     = new ViaJsonRpc(_settings.AccessHttpUrl);
            var balance = via.BalanceQuery(brokerUser.Exchange.Id, asset);

            // validate amount
            var amountInt    = wallet.AmountToLong(amount);
            var availableInt = wallet.StringToAmount(balance.Available);

            if (amountInt > availableInt)
            {
                _logger.LogError("broker available balance is too small");
                return(false);
            }
            if (amountInt <= 0)
            {
                _logger.LogError("amount must be greather then or equal to 0");
                return(false);
            }

            using (var dbtx = wallet.BeginDbTransaction())
            {
                // register withdrawal with wallet
                var acct = new BankAccount {
                    AccountNumber = order.Recipient
                };
                var tx = wallet.RegisterPendingWithdrawal(brokerUser.Id, amountInt, acct);
                if (tx == null)
                {
                    _logger.LogError($"Failed to create fiat withdrawal ('{order.Token}')");
                    return(false);
                }
                wallet.Save();
                var businessId = tx.Id;

                try
                {
                    // link pending withdrawal to broker order
                    var bow = new BrokerOrderFiatWithdrawal {
                        BrokerOrderId = order.Id, DepositCode = tx.DepositCode
                    };
                    _context.BrokerOrderFiatWithdrawals.Add(bow);
                    // we save changes here so that we a broker order cannot be processed twice(BrokerOrderChainWithdrawal.BrokerOrderId is unique)
                    _context.SaveChanges();
                }
                catch
                {
                    _logger.LogError($"unable to create BrokerOrderChainWithdrawal object ({order.Id}, {tx.DepositCode}");
                    throw;
                }

                // register withdrawal with the exchange backend
                var negativeAmount = -amount;
                try
                {
                    via.BalanceUpdateQuery(brokerUser.Exchange.Id, asset, "withdraw", businessId, negativeAmount.ToString(), null);
                }
                catch (ViaJsonException ex)
                {
                    _logger.LogError(ex, "Failed to update (withdraw) user balance (xch id: {0}, asset: {1}, businessId: {2}, amount {3}",
                                     brokerUser.Exchange.Id, asset, businessId, negativeAmount);
                    if (ex.Err == ViaError.BALANCE_UPDATE__BALANCE_NOT_ENOUGH)
                    {
                        dbtx.Rollback();
                        _logger.LogError("balance not enough");
                        return(false);
                    }
                    throw;
                }

                dbtx.Commit();
            }

            return(true);
        }