コード例 #1
0
        public SwapManager(
            IAccount account,
            ISwapClient swapClient,
            ICurrencyQuotesProvider quotesProvider,
            IMarketDataRepository marketDataRepository)
        {
            _account              = account ?? throw new ArgumentNullException(nameof(account));
            _swapClient           = swapClient ?? throw new ArgumentNullException(nameof(swapClient));
            _quotesProvider       = quotesProvider;
            _marketDataRepository = marketDataRepository ?? throw new ArgumentNullException(nameof(marketDataRepository));

            var currencySwaps = _account.Currencies
                                .Select(c =>
            {
                var currencySwap = CurrencySwapCreator.Create(
                    currency: c,
                    account: _account);

                currencySwap.InitiatorPaymentConfirmed += InitiatorPaymentConfirmed;
                currencySwap.AcceptorPaymentConfirmed  += AcceptorPaymentConfirmed;
                currencySwap.AcceptorPaymentSpent      += AcceptorPaymentSpent;
                currencySwap.SwapUpdated += SwapUpdatedHandler;

                return(currencySwap);
            });

            _currencySwaps = currencySwaps.ToDictionary(cs => cs.Currency);
        }
コード例 #2
0
        public static async Task <decimal> EstimateAsync(
            IAccount account,
            ICurrencyQuotesProvider quotesProvider,
            Func <string, Quote> feeCurrencyQuotesProvider,
            CurrencyConfig redeemableCurrency,
            WalletAddress redeemFromAddress     = null,
            CancellationToken cancellationToken = default)
        {
            if (redeemableCurrency is BitcoinBasedConfig)
            {
                return(0m);
            }

            var feeCurrency = redeemableCurrency.FeeCurrencyName;

            var feeCurrencyAddress = redeemFromAddress != null
                ? await account
                                     .GetAddressAsync(feeCurrency, redeemFromAddress.Address, cancellationToken)
                                     .ConfigureAwait(false)
                : null;

            var redeemFee = await redeemableCurrency
                            .GetRedeemFeeAsync(redeemFromAddress, cancellationToken)
                            .ConfigureAwait(false);

            if (feeCurrencyAddress != null && feeCurrencyAddress.AvailableBalance() >= redeemFee)
            {
                return(0m);
            }

            var feeCurrencyToBaseQuote = redeemableCurrency.FeeCurrencyToBaseSymbol != null
                ? quotesProvider?.GetQuote(redeemableCurrency.FeeCurrencyToBaseSymbol)
                : null;

            var feeCurrencyToBasePrice = feeCurrencyToBaseQuote != null
                ? feeCurrencyToBaseQuote.GetMiddlePrice()
                : 0m;

            var feeCurrencyQuote = redeemableCurrency.FeeCurrencySymbol != null
                ? feeCurrencyQuotesProvider.Invoke(redeemableCurrency.FeeCurrencySymbol)
                : null;

            var feeCurrencyPrice = feeCurrencyQuote != null
                ? feeCurrencyQuote.GetMiddlePrice()
                : 0m;

            return(await redeemableCurrency
                   .GetRewardForRedeemAsync(
                       maxRewardPercent : redeemableCurrency.MaxRewardPercent,
                       maxRewardPercentInBase : redeemableCurrency.MaxRewardPercentInBase,
                       feeCurrencyToBaseSymbol : redeemableCurrency.FeeCurrencyToBaseSymbol,
                       feeCurrencyToBasePrice : feeCurrencyToBasePrice,
                       feeCurrencySymbol : redeemableCurrency.FeeCurrencySymbol,
                       feeCurrencyPrice : feeCurrencyPrice,
                       cancellationToken : cancellationToken)
                   .ConfigureAwait(false));
        }
コード例 #3
0
        public WebSocketAtomexClient(
            IConfiguration configuration,
            IAccount account,
            ISymbolsProvider symbolsProvider,
            ICurrencyQuotesProvider quotesProvider = null)
        {
            Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));

            Account = account ?? throw new ArgumentNullException(nameof(account));
            Account.UnconfirmedTransactionAdded += OnUnconfirmedTransactionAddedEventHandler;

            SymbolsProvider = symbolsProvider ?? throw new ArgumentNullException(nameof(symbolsProvider));
            QuotesProvider  = quotesProvider;

            _cts = new CancellationTokenSource();
        }
コード例 #4
0
 public IAtomexApp UseQuotesProvider(ICurrencyQuotesProvider quotesProvider)
 {
     QuotesProvider = quotesProvider;
     return(this);
 }
コード例 #5
0
        public static Task <SwapParams> EstimateSwapParamsAsync(
            IFromSource from,
            decimal fromAmount,
            string redeemFromAddress,
            CurrencyConfig fromCurrency,
            CurrencyConfig toCurrency,
            IAccount account,
            IAtomexClient atomexClient,
            ISymbolsProvider symbolsProvider,
            ICurrencyQuotesProvider quotesProvider,
            CancellationToken cancellationToken = default)
        {
            return(Task.Run(async() =>
            {
                if (fromCurrency == null)
                {
                    return null;
                }

                if (toCurrency == null)
                {
                    return null;
                }

                var redeemFromWalletAddress = redeemFromAddress != null
                    ? await account
                                              .GetAddressAsync(toCurrency.Name, redeemFromAddress, cancellationToken)
                                              .ConfigureAwait(false)
                    : null;

                // estimate redeem fee
                var estimatedRedeemFee = await toCurrency
                                         .GetEstimatedRedeemFeeAsync(redeemFromWalletAddress, withRewardForRedeem: false)
                                         .ConfigureAwait(false);

                // estimate reward for redeem
                var rewardForRedeem = await RewardForRedeemHelper.EstimateAsync(
                    account: account,
                    quotesProvider: quotesProvider,
                    feeCurrencyQuotesProvider: symbol => atomexClient?.GetOrderBook(symbol)?.TopOfBook(),
                    redeemableCurrency: toCurrency,
                    redeemFromAddress: redeemFromWalletAddress,
                    cancellationToken: cancellationToken);

                // get amount reserved for active swaps
                var reservedForSwapsAmount = await GetAmountReservedForSwapsAsync(
                    from: from,
                    account: account,
                    currency: fromCurrency)
                                             .ConfigureAwait(false);

                // estimate maker network fee
                var estimatedMakerNetworkFee = await EstimateMakerNetworkFeeAsync(
                    fromCurrency: fromCurrency,
                    toCurrency: toCurrency,
                    account: account,
                    atomexClient: atomexClient,
                    symbolsProvider: symbolsProvider,
                    cancellationToken: cancellationToken)
                                               .ConfigureAwait(false);

                var fromCurrencyAccount = account
                                          .GetCurrencyAccount(fromCurrency.Name) as IEstimatable;

                // estimate payment fee
                var estimatedPaymentFee = await fromCurrencyAccount
                                          .EstimateSwapPaymentFeeAsync(
                    from: from,
                    amount: fromAmount,
                    cancellationToken: cancellationToken)
                                          .ConfigureAwait(false);

                // estimate max amount and max fee
                var maxAmountEstimation = await fromCurrencyAccount
                                          .EstimateMaxSwapPaymentAmountAsync(
                    from: from,
                    reserve: true,
                    cancellationToken: cancellationToken)
                                          .ConfigureAwait(false);

                if (maxAmountEstimation.Error != null)
                {
                    return new SwapParams
                    {
                        Amount = 0m,
                        PaymentFee = estimatedPaymentFee.Value,
                        RedeemFee = estimatedRedeemFee,
                        RewardForRedeem = rewardForRedeem,
                        MakerNetworkFee = estimatedMakerNetworkFee,
                        ReservedForSwaps = reservedForSwapsAmount,
                        Error = maxAmountEstimation.Error
                    };
                }

                var maxNetAmount = Math.Max(maxAmountEstimation.Amount - reservedForSwapsAmount - estimatedMakerNetworkFee, 0m);

                if (maxNetAmount == 0m) // insufficient funds
                {
                    return new SwapParams
                    {
                        Amount = 0m,
                        PaymentFee = maxAmountEstimation.Fee,
                        RedeemFee = estimatedRedeemFee,
                        RewardForRedeem = rewardForRedeem,
                        MakerNetworkFee = estimatedMakerNetworkFee,
                        ReservedForSwaps = reservedForSwapsAmount,
                        Error = new Error(
                            code: Errors.InsufficientFunds,
                            description: Resources.InsufficientFundsToCoverMakerNetworkFee,
                            details: string.Format(Resources.InsufficientFundsToCoverMakerNetworkFeeDetails,
                                                   estimatedMakerNetworkFee,                             // required
                                                   fromCurrency.Name,                                    // currency code
                                                   maxAmountEstimation.Amount - reservedForSwapsAmount)) // available
                    };
                }

                if (fromAmount > maxNetAmount) // amount greater than max net amount => use max amount params
                {
                    return new SwapParams
                    {
                        Amount = Math.Max(maxNetAmount, 0m),
                        PaymentFee = maxAmountEstimation.Fee,
                        RedeemFee = estimatedRedeemFee,
                        RewardForRedeem = rewardForRedeem,
                        MakerNetworkFee = estimatedMakerNetworkFee,
                        ReservedForSwaps = reservedForSwapsAmount,
                        Error = new Error(
                            code: Errors.InsufficientFunds,
                            description: Resources.InsufficientFunds,
                            details: string.Format(Resources.InsufficientFundsToSendAmountDetails,
                                                   fromAmount,        // required
                                                   fromCurrency.Name, // currency code
                                                   maxNetAmount))     // available
                    };
                }

                return new SwapParams
                {
                    Amount = fromAmount,
                    PaymentFee = estimatedPaymentFee.Value,
                    RedeemFee = estimatedRedeemFee,
                    RewardForRedeem = rewardForRedeem,
                    MakerNetworkFee = estimatedMakerNetworkFee,
                    ReservedForSwaps = reservedForSwapsAmount,
                    Error = null
                };
            }, cancellationToken));
        }