예제 #1
0
        internal int PlaceBuyOrder(double price, double amount, int orderToCancel = -1)
        {
            long amountXrpDrops = (long) Math.Round(amount * Const.DROPS_IN_NATIVE);
            double amountFiat = price * amount;
            int feeDrops = _lastPaidActionHadLowFee ? _feeProvider.EscalatedFeeInDrops : _feeProvider.BaseFeeInDrops;

            var command = new CreateBuyOrderRequest
            {
                tx_json = new CrOR_TxJson(_walletAddress, feeDrops)
                {
                    TakerGets = new Take
                    {
                        currency = _fiatCurreny,
                        value = amountFiat.ToString("0.00000"),
                        issuer = _issuerAddress
                    },
                    TakerPays = amountXrpDrops.ToString()
                }
            };

            if (-1 < orderToCancel)
            {
                command.tx_json.OfferSequence = orderToCancel.ToString();
            }

            _txSigner.Sign(command);

            ErrorResponse error = null;
            var delay = RETRY_DELAY;
            for (int i = 1; i <= RETRY_COUNT; i++)
            {
                string data = sendToRippleNet(Helpers.SerializeJson(command));

                if (null == data)
                {
                    return -1;
                }

                error = Helpers.DeserializeJSON<ErrorResponse>(data);
                if (!String.IsNullOrEmpty(error.error))
                {
                    _logger.Error("Error creating BUY order. Mesage=" + error.error_message);
                    if (!error.IsCritical)
                    {
                        //The request might have been successfull even if server says there were problems
                        _logger.Warning("Retry in " + delay + " ms...");
                        delay *= 2;
                        Thread.Sleep(delay);
                        continue;
                    }
                    throw new Exception(error.error + " " + error.error_message);
                }

                var response = Helpers.DeserializeJSON<NewOrderResponse>(data);

                if (ResponseKind.FatalError == response.result.ResponseKind)        //TODO: this checking logic is to generic to be in 'PlaceBuyOrder'.
                {
                    var message = String.Format("Error creating BUY order. Response={0} {1}", response.result.engine_result, response.result.engine_result_message);
                    _logger.Warning(message);
                    throw new Exception(message);
                }
                if (ResponseKind.NonCriticalError == response.result.ResponseKind)
                {
                    _logger.Warning("Non-fatal error creating BUY order. Message=" + response.result.engine_result_message);
                    _logger.Warning("Retry in " + delay + " ms...");
                    delay *= 2;
                    Thread.Sleep(delay);
                    continue;
                }
                if (ResponseKind.OldSequenceNumber == response.result.ResponseKind)
                {
                    int expectedSeqNum = GetNextSequence();
                    _txSigner.UpdateSequenceNumber(expectedSeqNum);
                    _logger.Warning(String.Format("Response: {0}. Synchronizing to suggested SeqNum {1}", response.result.engine_result_message, expectedSeqNum));
                    return orderToCancel;
                }

                if (ResponseKind.QueuedForLaterExecution == response.result.ResponseKind)
                {
                    double feeXrp = (double)feeDrops / Const.DROPS_IN_NATIVE;
                    _logger.Warning("Buy order queued due to high server load: " + response.result.engine_result_message + " (Fee was " + feeXrp + " XRP)");
                    _lastPaidActionHadLowFee = true;
                }
                else
                {
                    _lastPaidActionHadLowFee = false;
                }

                return response.result.tx_json.Sequence;
            }

            throw new Exception(String.Format("Socket request failed {0} times in a row with error '{1}'. Giving up.", RETRY_COUNT, error.error_message));
        }
예제 #2
0
        /// <summary>
        /// Execute a market order to buy given amount of XRP. Used when XRP balance falls under reserver to get back
        /// to operational state
        /// </summary>
        /// <param name="xrpAmount">XRP amount to buy instantly</param>
        /// <returns>True for success, False in case of fail</returns>
        internal bool ExchangeXrp(double xrpAmount)
        {
            long amountXrpDrops = (long)Math.Round(xrpAmount * Const.DROPS_IN_NATIVE);

            var command = new CreateBuyOrderRequest
            {
                tx_json = new CrOR_TxJson(_walletAddress, _feeProvider.EscalatedFeeInDrops)
                {
                    Flags = 262144,                 //tfFillOrKill
                    TakerGets = new Take
                    {
                        currency = _fiatCurreny,
                        value = "999",              //No asset is so priceless to cost more that 999 XRP, right?
                        issuer = _issuerAddress
                    },
                    TakerPays = amountXrpDrops.ToString()
                }
            };

            _txSigner.Sign(command);

            string data = sendToRippleNet(Helpers.SerializeJson(command));

            if (null == data)
            {
                _logger.Warning("Server returned no data as a response to market buy order");
                return false;
            }

            var response = Helpers.DeserializeJSON<NewOrderResponse>(data);

            if (ResponseKind.OldSequenceNumber == response.result.ResponseKind)
            {
                int expectedSeqNum = GetNextSequence();
                _txSigner.UpdateSequenceNumber(expectedSeqNum);
                _logger.Warning(String.Format("Response: {0}. Synchronizing to suggested SeqNum {1}", response.result.engine_result_message, expectedSeqNum));
                return false;
            }

            if (ResponseKind.Success != response.result.ResponseKind)
            {
                var message = String.Format("Response for market order to buy {0:0.0000} XRP not OK. Message: {1}", xrpAmount, response.result.engine_result_message);
                _logger.Warning(message);
                return false;
            }

            return true;
        }