예제 #1
0
        private async Task <Error> SendSwapAsync()
        {
            try
            {
                var account = App.Account;

                var requiredAmount = Amount + EstimatedPaymentFee;

                var fromWallets = (await account
                                   .GetUnspentAddressesAsync(
                                       currency: FromCurrency,
                                       amount: requiredAmount,
                                       fee: 0,
                                       feePrice: 0,
                                       isFeePerTransaction: false,
                                       addressUsagePolicy: AddressUsagePolicy.UseMinimalBalanceFirst))
                                  .ToList();

                if (requiredAmount > 0 && !fromWallets.Any())
                {
                    return(new Error(Errors.SwapError, Resources.CvInsufficientFunds));
                }

                var symbol    = App.Account.Symbols.SymbolByCurrencies(FromCurrency, ToCurrency);
                var side      = symbol.OrderSideForBuyCurrency(ToCurrency);
                var terminal  = App.Terminal;
                var orderBook = terminal.GetOrderBook(symbol);
                var price     = orderBook.EstimatedDealPrice(side, Amount);

                if (price == 0)
                {
                    return(new Error(Errors.NoLiquidity, Resources.CvNoLiquidity));
                }

                var qty = Math.Round(AmountHelper.AmountToQty(side, Amount, price), symbol.Base.Digits);

                var order = new Order
                {
                    Symbol      = symbol,
                    TimeStamp   = DateTime.UtcNow,
                    Price       = price,
                    Qty         = qty,
                    Side        = side,
                    Type        = OrderType.FillOrKill,
                    FromWallets = fromWallets.ToList(),
                };

                await order.CreateProofOfPossessionAsync(account);

                terminal.OrderSendAsync(order);
            }
            catch (Exception e)
            {
                Log.Error(e, "Conversion error");

                return(new Error(Errors.SwapError, Resources.CvConversionError));
            }

            return(null);
        }
        private async Task <Error> SendSwapAsync()
        {
            try
            {
                var account = App.Account;

                var requiredAmount = Amount + Fee;

                var fromWallets = (await account
                                   .GetUnspentAddressesAsync(
                                       currency: FromCurrency,
                                       requiredAmount: requiredAmount))
                                  .ToList();

                var refundWallet = await account
                                   .GetRefundAddressAsync(FromCurrency, fromWallets);

                var toWallet = await account
                               .GetRedeemAddressAsync(ToCurrency);

                var symbol    = Symbols.SymbolByCurrencies(FromCurrency, ToCurrency);
                var side      = symbol.OrderSideForBuyCurrency(ToCurrency);
                var terminal  = App.Terminal;
                var orderBook = terminal.GetOrderBook(symbol);
                var price     = orderBook.EstimatedDealPrice(side, Amount);

                if (price == 0)
                {
                    return(new Error(Errors.NoLiquidity, Resources.CvNoLiquidity));
                }

                var qty = Math.Round(AmountHelper.AmountToQty(side, Amount, price), symbol.QtyDigits);

                var order = new Order
                {
                    Symbol       = symbol,
                    TimeStamp    = DateTime.UtcNow,
                    Price        = price,
                    Qty          = qty,
                    Fee          = Fee,
                    Side         = side,
                    Type         = OrderType.FillOrKill,
                    FromWallets  = fromWallets.ToList(),
                    ToWallet     = toWallet,
                    RefundWallet = refundWallet
                };

                await order.CreateProofOfPossessionAsync(account);

                terminal.OrderSendAsync(order);
            }
            catch (Exception e)
            {
                Log.Error(e, "Conversion error");

                return(new Error(Errors.SwapError, Resources.CvConversionError));
            }

            return(null);
        }
예제 #3
0
        public (decimal, decimal) EstimateOrderPrices(
            Side side,
            decimal amount,
            decimal amountDigitsMultiplier,
            decimal qtyDigitsMultiplier)
        {
            var requiredAmount = amount;

            lock (SyncRoot)
            {
                var book = side == Side.Buy
                    ? Sells
                    : Buys;

                if (amount == 0)
                {
                    return(book.Any()
                        ? (book.First().Key, book.First().Key)
                        : (0m, 0m));
                }

                var totalUsedQuoteAmount = 0m;
                var totalUsedQty         = 0m;

                foreach (var entryPair in book)
                {
                    var qty   = entryPair.Value.Qty();
                    var price = entryPair.Key;

                    var availableAmount = AmountHelper.QtyToAmount(side, qty, price, amountDigitsMultiplier);

                    var usedAmount = Math.Min(requiredAmount, availableAmount);
                    var usedQty    = AmountHelper.AmountToQty(side, usedAmount, price, qtyDigitsMultiplier);

                    totalUsedQuoteAmount += usedQty * price;
                    totalUsedQty         += usedQty;

                    requiredAmount -= usedAmount;

                    if (requiredAmount <= 0)
                    {
                        return(price, totalUsedQuoteAmount / totalUsedQty);
                    }
                }
            }

            return(0m, 0m);
        }
예제 #4
0
        private async Task <Error> ConvertAsync()
        {
            try
            {
                var account         = App.Account;
                var currencyAccount = account
                                      .GetCurrencyAccount <ILegacyCurrencyAccount>(FromCurrency.Name);

                var fromWallets = (await currencyAccount
                                   .GetUnspentAddressesAsync(
                                       toAddress: null,
                                       amount: Amount,
                                       fee: 0,
                                       feePrice: await FromCurrency.GetDefaultFeePriceAsync(),
                                       feeUsagePolicy: FeeUsagePolicy.EstimatedFee,
                                       addressUsagePolicy: AddressUsagePolicy.UseMinimalBalanceFirst,
                                       transactionType: BlockchainTransactionType.SwapPayment))
                                  .ToList();

                foreach (var fromWallet in fromWallets)
                {
                    if (fromWallet.Currency != FromCurrency.Name)
                    {
                        fromWallet.Currency = FromCurrency.Name;
                    }
                }

                // check balances
                var errors = await BalanceChecker.CheckBalancesAsync(App.Account, fromWallets);

                if (errors.Any())
                {
                    return(new Error(Errors.SwapError, GetErrorsDescription(errors)));
                }

                if (Amount == 0)
                {
                    return(new Error(Errors.SwapError, Resources.CvZeroAmount));
                }

                if (Amount > 0 && !fromWallets.Any())
                {
                    return(new Error(Errors.SwapError, Resources.CvInsufficientFunds));
                }

                var symbol = App.SymbolsProvider
                             .GetSymbols(App.Account.Network)
                             .SymbolByCurrencies(FromCurrency, ToCurrency);

                var baseCurrency = App.Account.Currencies.GetByName(symbol.Base);
                var side         = symbol.OrderSideForBuyCurrency(ToCurrency);
                var terminal     = App.Terminal;
                var price        = EstimatedPrice;
                var orderPrice   = EstimatedOrderPrice;

                if (price == 0)
                {
                    return(new Error(Errors.NoLiquidity, Resources.CvNoLiquidity));
                }

                var qty = AmountHelper.AmountToQty(side, Amount, price, baseCurrency.DigitsMultiplier);

                if (qty < symbol.MinimumQty)
                {
                    var minimumAmount = AmountHelper.QtyToAmount(side, symbol.MinimumQty, price, FromCurrency.DigitsMultiplier);
                    var message       = string.Format(CultureInfo.InvariantCulture, Resources.CvMinimumAllowedQtyWarning, minimumAmount, FromCurrency.Name);

                    return(new Error(Errors.SwapError, message));
                }

                var order = new Order
                {
                    Symbol          = symbol.Name,
                    TimeStamp       = DateTime.UtcNow,
                    Price           = orderPrice,
                    Qty             = qty,
                    Side            = side,
                    Type            = OrderType.FillOrKill,
                    FromWallets     = fromWallets.ToList(),
                    MakerNetworkFee = EstimatedMakerNetworkFee
                };

                await order.CreateProofOfPossessionAsync(account);

                terminal.OrderSendAsync(order);

                // wait for swap confirmation
                var timeStamp = DateTime.UtcNow;

                while (DateTime.UtcNow < timeStamp + SwapTimeout)
                {
                    await Task.Delay(SwapCheckInterval);

                    var currentOrder = terminal.Account.GetOrderById(order.ClientOrderId);

                    if (currentOrder == null)
                    {
                        continue;
                    }

                    if (currentOrder.Status == OrderStatus.Pending)
                    {
                        continue;
                    }

                    if (currentOrder.Status == OrderStatus.PartiallyFilled || currentOrder.Status == OrderStatus.Filled)
                    {
                        var swap = (await terminal.Account
                                    .GetSwapsAsync())
                                   .FirstOrDefault(s => s.OrderId == currentOrder.Id);

                        if (swap == null)
                        {
                            continue;
                        }

                        return(null);
                    }

                    if (currentOrder.Status == OrderStatus.Canceled)
                    {
                        return(new Error(Errors.PriceHasChanged, Resources.SvPriceHasChanged));
                    }

                    if (currentOrder.Status == OrderStatus.Rejected)
                    {
                        return(new Error(Errors.OrderRejected, Resources.SvOrderRejected));
                    }
                }

                return(new Error(Errors.TimeoutReached, Resources.SvTimeoutReached));
            }
            catch (Exception e)
            {
                Log.Error(e, "Conversion error");

                return(new Error(Errors.SwapError, Resources.CvConversionError));
            }
        }