private async Task <Result <FeeResponse, ErrorResponse> > getFeeAsync(ECurrency currency) { var result = new Result <FeeResponse, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/{currency}/Fee"; try { using (HttpClient httpClient = new HttpClient()) using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { FeeResponse feeResponse = await response.Content.ReadAsAsync <FeeResponse>(); if (response.IsSuccessStatusCode) { result.IsSuccess = true; result.Data = feeResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Cancel an order. /// </summary> /// <param name="apiKey">Your apiKey.</param> /// <param name="apiSecret">Your apiSecretKey.</param> /// <param name="ID">Order ID.</param> /// <response code="200">Order is canceled.</response> /// <response code="400_InvalidUrlParameters">Invalid URL parameters.</response> /// <response code="400_MissingBody">Request body is missing.</response> /// <response code="400_InvalidBody">Request validation errors. See InnerErrors.</response> /// <response code="400_ValidationError">Request validation errors. See InnerErrors.</response> /// <response code="403">Not authorized to use this endpoint.</response> /// <response code="404">Order is not found.</response> /// <response code="409">Cannot be canceled.</response> /// <response code="500">Server error.</response> /// <returns></returns> public async Task <Result <bool, ErrorResponse> > CancelOrderAsync(string apiKey, string apiSecret, Guid?ID) { #region if (ID == null || ID == Guid.Empty) { throw new ArgumentNullException(nameof(ID)); } #endregion string token = getAuthToken(apiKey, apiSecret); var result = new Result <bool, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/Orders/{ID}"; CancelOrderRequest bodyParams = new CancelOrderRequest(); string json = bodyParams.ToJson(); StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); HttpRequestMessage request = new HttpRequestMessage { Method = new HttpMethod("PATCH"), RequestUri = new Uri(requestUri), Content = content }; try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(AUTHORIZATION, $"{BASIC} {token}"); using (HttpResponseMessage response = await httpClient.SendAsync(request)) { if (response.IsSuccessStatusCode) { result.IsSuccess = true; result.Data = true; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Get an accepted quote with ID. /// </summary> /// <param name="currency">The source currency of the quote.</param> /// <param name="privateKey">The privateKey of the sending address of the quote.</param> /// <param name="ID">ID of the accepted quote.</param> /// <response code="200">The quote with a specified ID.</response> /// <response code="400_InvalidUrlParameters">Invalid URL parameters.</response> /// <response code="403_SignatureMissing">X-REQUEST-SIGNATURE header is missing.</response> /// <response code="403_SignatureExpired">X-REQUEST-SIGNATURE has expired.</response> /// <response code="403_InvalidSignature">Invalid X-REQUEST-SIGNATURE.</response> /// <response code="404">Quote is not found.</response> /// <response code="500">Server error.</response> /// <returns></returns> public async Task <Result <GetQuoteResponse, ErrorResponse> > GetQuoteAsync(ECurrency currency, string privateKey, Guid?ID) { #region if (!currency.IsGluwaExchangeCurrency()) { throw new ArgumentOutOfRangeException($"Unsupported currency: {currency}"); } if (ID == null || ID == Guid.Empty) { throw new ArgumentNullException(nameof(ID)); } #endregion var result = new Result <GetQuoteResponse, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/Quotes/{ID}"; try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(X_REQUEST_SIGNATURE, GluwaService.GetAddressSignature(privateKey, currency, mEnv)); using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { if (response.IsSuccessStatusCode) { GetQuoteResponse quoteResponse = await response.Content.ReadAsAsync <GetQuoteResponse>(); result.IsSuccess = true; result.Data = quoteResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Get balance for specified currency. /// </summary> /// <param name="currency">Currency type.</param> /// <param name="address">Your public Address.</param> /// <param name="includeUnspentOutputs">(For BTC only) if "true", the response includes unspent outputs for the address. "false" by default.</param> /// <response code="200">Balance and associated currency.</response> /// <response code="400">Invalid address format.</response> /// <response code="500">Server error.</response> /// <response code="503">Service unavailable for the specified currency or temporarily.</response> public async Task <Result <BalanceResponse, ErrorResponse> > GetBalanceAsync(ECurrency currency, string address, bool includeUnspentOutputs = false) { if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException(nameof(address)); } var result = new Result <BalanceResponse, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/{currency}/Addresses/{address}"; List <string> queryParams = new List <string>(); queryParams.Add($"includeUnspentOutputs={includeUnspentOutputs}"); if (queryParams.Any()) { requestUri = $"{requestUri}?{string.Join("&", queryParams)}"; } try { using (HttpClient httpClient = new HttpClient()) using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { if (response.IsSuccessStatusCode) { BalanceResponse balanceResponse = await response.Content.ReadAsAsync <BalanceResponse>(); result.IsSuccess = true; result.Data = balanceResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Retrieve an order with specified ID. /// </summary> /// <param name="apiKey">Your apiKey.</param> /// <param name="apiSecret">Your apiSecretKey.</param> /// <param name="ID">The ID of an order.</param> /// <response code="200">The order with a specified ID.</response> /// <response code="400_InvalidUrlParameters">Invalid URL parameters.</response> /// <response code="403">Not authorized to use this endpoint.</response> /// <response code="404">Order is not found.</response> /// <response code="500">Server error.</response> /// <returns></returns> public async Task <Result <GetOrderResponse, ErrorResponse> > GetOrderAsync(string apiKey, string apiSecret, Guid?ID) { #region if (ID == null || ID == Guid.Empty) { throw new ArgumentNullException(nameof(ID)); } #endregion string token = getAuthToken(apiKey, apiSecret); var result = new Result <GetOrderResponse, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/Orders/{ID}"; try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(AUTHORIZATION, $"{BASIC} {token}"); using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { if (response.IsSuccessStatusCode) { GetOrderResponse orderResponse = await response.Content.ReadAsAsync <GetOrderResponse>(); result.IsSuccess = true; result.Data = orderResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Get bitcoin or gluwacoin transaction by hash. /// </summary> /// <param name="currency">Currency type</param> /// <param name="privateKey">Your Private Key.</param> /// <param name="txnHash">Hash of the transaction on the blockchain.</param> /// <response code="200">Transaction response.</response> /// <response code="400">Invalid transaction hash format.</response> /// <response code="403">Request signature header is not valid.</response> /// <response code="404">Tranasction not found.</response> /// <response code="500">Server error.</response> /// <response code="503">Service unavailable.</response> public async Task <Result <TransactionResponse, ErrorResponse> > GetTransactionDetailsAsync(ECurrency currency, string privateKey, string txnHash) { if (string.IsNullOrWhiteSpace(privateKey)) { throw new ArgumentNullException(nameof(privateKey)); } else if (string.IsNullOrWhiteSpace(txnHash)) { throw new ArgumentNullException(nameof(txnHash)); } var result = new Result <TransactionResponse, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/{currency}/Transactions/{txnHash}"; try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(X_REQUEST_SIGNATURE, GluwaService.GetAddressSignature(privateKey, currency, mEnv)); using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { if (response.IsSuccessStatusCode) { TransactionResponse transactionResponse = await response.Content.ReadAsAsync <TransactionResponse>(); result.IsSuccess = true; result.Data = transactionResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Get current order book. /// </summary> /// <param name="conversion">Conversion symbol.</param> /// <param name="limit">Number of orders to include in the result. Ordered by descending price (best price first). Defaults to 100, maximum of 1000.</param> /// <response code="200">List of active orders</response> /// <response code="400">Invalid request parameters.</response> /// <returns></returns> public async Task <Result <List <GetOrderBookResponse>, ErrorResponse> > GetOrderBook(EConversion conversion, uint limit = 100) { var result = new Result <List <GetOrderBookResponse>, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/OrderBook/{conversion}"; List <string> queryParams = new List <string>(); queryParams.Add($"limit={limit}"); if (queryParams.Any()) { requestUri = $"{requestUri}?{string.Join("&", queryParams)}"; } try { using (HttpClient httpClient = new HttpClient()) { using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { if (response.IsSuccessStatusCode) { List <GetOrderBookResponse> orderBookResponse = await response.Content.ReadAsAsync <List <GetOrderBookResponse> >(); result.IsSuccess = true; result.Data = orderBookResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Generates a one-time use QR code for merchants, used for making a payment transaction. Returns an image in a .jpg or .png format. /// </summary> /// <param name="apiKey">Your API Key.</param> /// <param name="secret">Your API Secret.</param> /// <param name="address">Your public address.</param> /// <param name="privateKey">Your private Key.</param> /// <param name="currency">Currency type.</param> /// <param name="amount">Payment amount. Fee will be deducted from this amount when payment request is made.</param> /// <param name="format">Desired image format, optional. Defaults to base64 string</param> /// <param name="note">Additional information, used by the merchant user. optional.</param> /// <param name="merchantOrderID">Identifier for the payment, used by the merchant user. optional.</param> /// <param name="expiry">Time of expiry for the QR code in seconds. Payment request must be made with this QR code before this time. optional. Defaults to 1800</param> /// <response code="200">QR code image in a .png by default or .jpg depending on the format query parameter.</response> /// <response code="400">Validation error. Please see inner errors for more details. or API Key and secret request header is missing or invalid.</response> /// <response code="403">Combination of Api Key and Api Secret was not found.</response> /// <response code="500">Server error.</response> /// <response code="503">Service unavailable for the provided currency.</response> public async Task <Result <string, ErrorResponse> > GetPaymentQRCodeAsync( string apiKey, string secret, string address, string privateKey, EPaymentCurrency currency, string amount, string format = null, string note = null, string merchantOrderID = null, int expiry = 1800 ) { if (string.IsNullOrWhiteSpace(apiKey)) { throw new ArgumentNullException(nameof(apiKey)); } else if (string.IsNullOrWhiteSpace(secret)) { throw new ArgumentNullException(nameof(secret)); } else if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException(nameof(address)); } else if (string.IsNullOrWhiteSpace(privateKey)) { throw new ArgumentNullException(nameof(privateKey)); } else if (string.IsNullOrWhiteSpace(amount)) { throw new ArgumentNullException(nameof(amount)); } var result = new Result <string, ErrorResponse>(); var requestUri = $"{mEnv.BaseUrl}/v1/QRCode"; var queryParams = new List <string>(); if (format != null) { queryParams.Add($"format={format}"); requestUri = $"{requestUri}?{string.Join("&", queryParams)}"; } QRCodeRequest bodyParams = new QRCodeRequest() { Signature = getTimestampSignature(privateKey), Currency = currency, Target = address, Amount = amount, Expiry = expiry, Note = note, MerchantOrderID = merchantOrderID }; string json = bodyParams.ToJson(); StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); byte[] authenticationBytes = Encoding.ASCII.GetBytes($"{apiKey}:{secret}"); try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", System.Convert.ToBase64String(authenticationBytes)); using (HttpResponseMessage response = await httpClient.PostAsync(requestUri, content)) { if (response.IsSuccessStatusCode) { result.IsSuccess = true; result.Data = await response.Content.ReadAsStringAsync(); return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Accept an exchange request. /// <param name="apiKey">Your apiKey.</param> /// <param name="apiSecret">Your apiSecretKey.</param> /// <param name="address"/>The address that funds the source amount.</parm> /// <param name="privateKey">The privateKey of the sending address.</param> /// </summary> /// <returns></returns> public async Task <Result <bool, ErrorResponse> > AcceptExchangeRequestAsync( string apiKey, string apiSecret, string address, string privateKey, AcceptExchangeRequest exchangeRequest) { #region IEnumerable <ValidationResult> validation = exchangeRequest.Validate(); if (validation.Any()) { foreach (var item in validation) { throw new ArgumentNullException(item.ErrorMessage); } } if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException(address); } else if (string.IsNullOrWhiteSpace(privateKey)) { throw new ArgumentNullException(nameof(privateKey)); } #endregion string token = getAuthToken(apiKey, apiSecret); var result = new Result <bool, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/ExchangeRequests/{exchangeRequest.ID}"; string reserveTxnSinatrue = null; string executeTxnSignature = null; string reclaimTxnSignature = null; BigInteger nonce = BigInteger.Parse(GluwaService.GetNonceString()); if (exchangeRequest.Conversion.Value.IsSourceCurrencyBtc()) { BtcTxnSignature txnSignature = await getBtcTxnSignaturesAsync( exchangeRequest.Conversion.Value.ToSourceCurrency(), address, exchangeRequest.SourceAmount, exchangeRequest.Fee, exchangeRequest.DestinationAddress, exchangeRequest.ReservedFundsAddress, exchangeRequest.ReservedFundsRedeemScript, privateKey); reserveTxnSinatrue = txnSignature.ReserveTxnSignature; executeTxnSignature = txnSignature.ExecuteTxnSignature; reclaimTxnSignature = txnSignature.ReclaimTxnSignature; } else { BigInteger convertExpiryBlockNumber = BigInteger.Parse(exchangeRequest.ExpiryBlockNumber.ToString()); reserveTxnSinatrue = getGluwacoinReserveTxnSignature( exchangeRequest.Conversion.Value.ToSourceCurrency(), address, exchangeRequest.SourceAmount, exchangeRequest.Fee, exchangeRequest.DestinationAddress, exchangeRequest.Executor, nonce, convertExpiryBlockNumber, privateKey); } PatchExchangeRequest bodyParams = new PatchExchangeRequest() { SendingAddress = address, ReserveTxnSignature = reserveTxnSinatrue, Nonce = nonce.ToString(), ExecuteTxnSignature = executeTxnSignature, ReclaimTxnSignature = reclaimTxnSignature }; string json = bodyParams.ToJson(); StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); HttpRequestMessage request = new HttpRequestMessage { Method = new HttpMethod("PATCH"), RequestUri = new Uri(requestUri), Content = content }; try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(AUTHORIZATION, $"{BASIC} {token}"); using (HttpResponseMessage response = await httpClient.SendAsync(request)) { if (response.IsSuccessStatusCode) { result.IsSuccess = true; result.Data = true; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Get Quote for currency exchange. /// </summary> /// <param name="sendingAddressPrivateKey">The privateKey of the sending address.</param> /// <param name="receivingAddressPrivateKey">The privateKey of the receiving address.</param> /// <param name="quoteRequest">Request body.</param> /// <response code="200">Newly generated quote.</response> /// <response code="400_InvalidUrlParameters">Invalid URL parameters.</response> /// <response code="400_MissingBody">Request body is missing.</response> /// <response code="400_InvalidBody">Request validation errors. See InnerErrors.</response> /// <response code="400_ValidationError">Request validation errors. See InnerErrors.</response> /// <response code="404">No matching orders available.</response> /// <response code="500">Server error.</response> /// <returns></returns> public async Task <Result <QuoteResponse, ErrorResponse> > GetPendingQuoteAsync( string sendingAddressPrivateKey, string receivingAddressPrivateKey, GetPendingQuoteRequest quoteRequest) { #region IEnumerable <ValidationResult> validation = quoteRequest.Validate(); if (validation.Any()) { foreach (var item in validation) { throw new ArgumentNullException(item.ErrorMessage); } } if (string.IsNullOrWhiteSpace(sendingAddressPrivateKey)) { throw new ArgumentNullException(nameof(sendingAddressPrivateKey)); } else if (string.IsNullOrWhiteSpace(receivingAddressPrivateKey)) { throw new ArgumentNullException(nameof(receivingAddressPrivateKey)); } #endregion var result = new Result <QuoteResponse, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/Quote"; string btcPublicKey = null; if (quoteRequest.Conversion.Value.IsSourceCurrencyBtc()) { btcPublicKey = Key.Parse(sendingAddressPrivateKey, mEnv.Network).PubKey.ToString(); } string sendingAddressSignature = GluwaService.GetAddressSignature(sendingAddressPrivateKey, quoteRequest.Conversion.Value.ToSourceCurrency(), mEnv); string receivingAddressSignature = GluwaService.GetAddressSignature(receivingAddressPrivateKey, quoteRequest.Conversion.Value.ToTargetCurrency(), mEnv); PostQuoteRequest bodyParams = new PostQuoteRequest() { Amount = quoteRequest.Amount, Conversion = quoteRequest.Conversion, SendingAddress = quoteRequest.SendingAddress, SendingAddressSignature = sendingAddressSignature, ReceivingAddress = quoteRequest.ReceivingAddress, ReceivingAddressSignature = receivingAddressSignature, BtcPublicKey = btcPublicKey }; string json = bodyParams.ToJson(); StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); try { using (HttpClient httpClient = new HttpClient()) using (HttpResponseMessage response = await httpClient.PostAsync(requestUri, content)) { if (response.IsSuccessStatusCode) { QuoteResponse quoteResponse = await response.Content.ReadAsAsync <QuoteResponse>(); result.IsSuccess = true; result.Data = quoteResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Create a new order. /// </summary> /// <param name="apiKey">Your apiKey.</param> /// <param name="apiSecret">Your apiSecretKey.</param> /// <param name="sendingAddressPrivateKey">The privateKey of the sending address.</param> /// <param name="receivingAddressPrivateKey">The privateKey of the receiving address.</param> /// <param name="orderRequest">Request body.</param> /// <response code="201">Newly created order.</response> /// <response code="400_InvalidUrlParameters">Invalid URL parameters.</response> /// <response code="400_MissingBody">Request body is missing.</response> /// <response code="400_InvalidBody">Request validation errors. See InnerErrors.</response> /// <response code="400_ValidationError">Request validation errors. See InnerErrors.</response> /// <response code="403_Forbidden">Not authorized to use this endpoint.</response> /// <response code="403_WebhookNotFound">Webhook URL to send exchange request is unavailable.</response> /// <response code="500">Server error.</response> /// <response code="503">Service unavailable for the specified conversion.</response> /// <returns></returns> public async Task <Result <CreateOrderResponse, ErrorResponse> > CreateOrderAsync( string apiKey, string apiSecret, string sendingAddressPrivateKey, string receivingAddressPrivateKey, CreateOrderRequest orderRequest) { #region IEnumerable <ValidationResult> validation = orderRequest.Validate(); if (validation.Any()) { foreach (var item in validation) { throw new ArgumentNullException(item.ErrorMessage); } } if (string.IsNullOrWhiteSpace(sendingAddressPrivateKey)) { throw new ArgumentNullException(nameof(sendingAddressPrivateKey)); } else if (string.IsNullOrWhiteSpace(receivingAddressPrivateKey)) { throw new ArgumentNullException(nameof(receivingAddressPrivateKey)); } #endregion string token = getAuthToken(apiKey, apiSecret); var result = new Result <CreateOrderResponse, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/Orders"; string btcpublicKey = null; if (orderRequest.Conversion.Value.IsSourceCurrencyBtc()) { btcpublicKey = Key.Parse(sendingAddressPrivateKey, mEnv.Network).PubKey.ToString(); } PostOrderRequest bodyParams = new PostOrderRequest() { Conversion = orderRequest.Conversion.ToString(), SendingAddress = orderRequest.SendingAddress, SendingAddressSignature = GluwaService.GetAddressSignature(sendingAddressPrivateKey, orderRequest.Conversion.Value.ToSourceCurrency(), mEnv), ReceivingAddress = orderRequest.ReceivingAddress, ReceivingAddressSignature = GluwaService.GetAddressSignature(receivingAddressPrivateKey, orderRequest.Conversion.Value.ToTargetCurrency(), mEnv), SourceAmount = orderRequest.SourceAmount, Price = orderRequest.Price, BtcPublicKey = btcpublicKey }; string json = bodyParams.ToJson(); StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(AUTHORIZATION, $"{BASIC} {token}"); using (HttpResponseMessage response = await httpClient.PostAsync(requestUri, content)) { if (response.IsSuccessStatusCode) { CreateOrderResponse orderResponse = await response.Content.ReadAsAsync <CreateOrderResponse>(); result.IsSuccess = true; result.Data = orderResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Retrieve all orders. /// </summary> /// <param name="apiKey">Your apiKey.</param> /// <param name="apiSecret">Your apiSecretKey.</param> /// <param name="options">Request body.</param> /// <response code="200">List of orders.</response> /// <response code="400_InvalidUrlParameters">Invalid URL parameters.</response> /// <response code="403">Not authorized to use this endpoint.</response> /// <response code="500">Server error.</response> /// <returns></returns> public async Task <Result <List <GetOrdersResponse>, ErrorResponse> > GetOrdersAsync(string apiKey, string apiSecret, GetOrdersOptions options) { #region IEnumerable <ValidationResult> validation = options.Validate(); if (validation.Any()) { foreach (var item in validation) { throw new ArgumentNullException(item.ErrorMessage); } } #endregion string token = getAuthToken(apiKey, apiSecret); var result = new Result <List <GetOrdersResponse>, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/Orders"; var queryParams = new List <string>(); if (options.StartDateTime.HasValue) { queryParams.Add($"startDateTime={options.StartDateTime.Value.ToString("o")}"); } if (options.EndDateTime.HasValue) { queryParams.Add($"endDateTime={options.EndDateTime.Value.ToString("o")}"); } if (options.Status.HasValue) { queryParams.Add($"status={options.Status}"); } queryParams.Add($"offset={options.Offset}"); queryParams.Add($"limit={options.Limit}"); requestUri = $"{requestUri}?{string.Join("&", queryParams)}"; try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(AUTHORIZATION, $"{BASIC} {token}"); using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { if (response.IsSuccessStatusCode) { List <GetOrdersResponse> orderResponse = await response.Content.ReadAsAsync <List <GetOrdersResponse> >(); result.IsSuccess = true; result.Data = orderResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Get a list of accepted quotes. /// </summary> /// <param name="currency">The source currency of the quote.</param> /// <param name="address">The sending address of the quote.</param> /// <param name="privateKey">The privateKey of the sending address.</param> /// <param name="options">Request body.</param> /// <response code="200">array of Quotes.</response> /// <response code="400_InvalidUrlParameters">Invalid URL parameters.</response> /// <response code="403_SignatureMissing">X-REQUEST-SIGNATURE header is missing.</response> /// <response code="403_SignatureExpired">X-REQUEST-SIGNATURE has expired.</response> /// <response code="403_InvalidSignature">Invalid X-REQUEST-SIGNATURE.</response> /// <response code="500">Server error.</response> /// <returns></returns> public async Task <Result <List <GetQuotesResponse>, ErrorResponse> > GetQuotesAsync( ECurrency currency, string address, string privateKey, GetQuotesOptions options) { #region if (!currency.IsGluwaExchangeCurrency()) { throw new ArgumentOutOfRangeException($"Unsupported currency: {currency}"); } IEnumerable <ValidationResult> validation = options.Validate(); if (validation.Any()) { foreach (var item in validation) { throw new ArgumentNullException(item.ErrorMessage); } } if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException(nameof(address)); } #endregion var result = new Result <List <GetQuotesResponse>, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/{currency}/Addresses/{address}/Quotes"; var queryParams = new List <string>(); if (options.StartDateTime.HasValue) { queryParams.Add($"startDateTime={options.StartDateTime.Value.ToString("o")}"); } if (options.EndDateTime.HasValue) { queryParams.Add($"endDateTime={options.EndDateTime.Value.ToString("o")}"); } if (options.Status.HasValue) { queryParams.Add($"status={options.Status}"); } queryParams.Add($"offset={options.Offset}"); queryParams.Add($"limit={options.Limit}"); requestUri = $"{requestUri}?{string.Join("&", queryParams)}"; try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(X_REQUEST_SIGNATURE, GluwaService.GetAddressSignature(privateKey, currency, mEnv)); using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { if (response.IsSuccessStatusCode) { List <GetQuotesResponse> quoteResponse = await response.Content.ReadAsAsync <List <GetQuotesResponse> >(); result.IsSuccess = true; result.Data = quoteResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Accept quote received from POST /v1/Quote endpoint. /// </summary> /// <param name="currency">The source currency of the quote.</param> /// <param name="address">The sending address of the quote.</param> /// <param name="privateKey">The privateKey of the sending address.</param> /// <param name="quoteRequest">Request body.</param> /// <response code="202">Quote is accepted.</response> /// <response code="400_InvalidUrlParameters">Invalid URL parameters.</response> /// <response code="400_MissingBody">Request body is missing.</response> /// <response code="400_InvalidBody">Request validation errors. See InnerErrors.</response> /// <response code="400_ValidationError">Request validation errors. See InnerErrors.</response> /// <response code="403">Invalid checksum. Checksum may be wrong or expired.</response> /// <response code="404">One of the matched orders are no longer available.</response> /// <response code="500">Server error.</response> /// <returns></returns> public async Task <Result <AcceptQuoteResponse, ErrorResponse> > AcceptQuoteAsync( ECurrency currency, string address, string privateKey, AcceptQuoteRequest quoteRequest) { #region if (!currency.IsGluwaExchangeCurrency()) { throw new ArgumentOutOfRangeException($"Unsupported currency: {currency}"); } foreach (var order in quoteRequest.MatchedOrders) { IEnumerable <ValidationResult> validation = quoteRequest.Validate(currency); if (validation.Any()) { foreach (var item in validation) { throw new ArgumentNullException(item.ErrorMessage); } } } if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException(nameof(address)); } else if (string.IsNullOrWhiteSpace(privateKey)) { throw new ArgumentNullException(nameof(privateKey)); } #endregion var result = new Result <AcceptQuoteResponse, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/Quote"; List <MatchedOrderRequest> matchedOrders = new List <MatchedOrderRequest>(); foreach (var matchedOrder in quoteRequest.MatchedOrders) { if (currency.IsGluwaCoinCurrency()) { BigInteger nonce = BigInteger.Parse(GluwaService.GetNonceString()); BigInteger convertExpiryBlockNumber = BigInteger.Parse(matchedOrder.ExpiryBlockNumber); string signature = getGluwacoinReserveTxnSignature( currency, address, matchedOrder.SourceAmount, matchedOrder.Fee, matchedOrder.DestinationAddress, matchedOrder.Executor, nonce, convertExpiryBlockNumber, privateKey); MatchedOrderRequest matchedOrderRequest = new MatchedOrderRequest() { OrderID = matchedOrder.OrderID, ReserveTxnSignature = signature, Nonce = nonce.ToString() }; matchedOrders.Add(matchedOrderRequest); } else { BtcTxnSignature txnSignature = await getBtcTxnSignaturesAsync( currency, address, matchedOrder.SourceAmount, matchedOrder.Fee, matchedOrder.DestinationAddress, matchedOrder.ReservedFundsAddress, matchedOrder.ReservedFundsRedeemScript, privateKey); MatchedOrderRequest matchedOrderRequest = new MatchedOrderRequest() { OrderID = matchedOrder.OrderID, ReserveTxnSignature = txnSignature.ReserveTxnSignature, ExecuteTxnSignature = txnSignature.ExecuteTxnSignature, ReclaimTxnSignature = txnSignature.ReclaimTxnSignature }; matchedOrders.Add(matchedOrderRequest); } } PutQuoteRequest bodyParams = new PutQuoteRequest() { MatchedOrders = matchedOrders, Checksum = quoteRequest.Checksum }; string json = bodyParams.ToJson(); StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); try { using (HttpClient httpClient = new HttpClient()) using (HttpResponseMessage response = await httpClient.PutAsync(requestUri, content)) { if (response.IsSuccessStatusCode) { AcceptQuoteResponse quoteResponse = await response.Content.ReadAsAsync <AcceptQuoteResponse>(); result.IsSuccess = true; result.Data = quoteResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Create a new Bitcoin or Gluwacoin transaction. /// </summary> /// <param name="currency">Currency type</param> /// <param name="address">Your public Address.</param> /// <param name="privateKey">Your Private Key.</param> /// <param name="amount">Transaction amount, not including the fee.</param> /// <param name="target">The address that the transaction will be sent to.</param> /// <param name="merchantOrderID">Identifier for the transaction that was provided by the merchant user. Optional.</param> /// <param name="note">Additional information about the transaction that a user can provide. Optional.</param> /// <param name="nonce">Nonce for the transaction. For Gluwacoin currencies only.</param> /// <param name="idem">Idempotent key for the transaction to prevent duplicate transactions.</param> /// <param name="paymentID">ID for the QR code payment.</param> /// <param name="paymentSig">Signature of the QR code payment.Required if PaymentID is not null.</param> /// <response code="202">Newly accepted transaction.</response> /// <response code="400">Invalid request. or Validation error. See inner errors for more details. or (BTC only) Signed BTC transaction could not be verified.</response> /// <response code="403">For payments, payment signature could not be verified.</response> /// <response code="409">A transaction with the same transaction hash, payment ID, or idem already exists.</response> /// <response code="500">Server error.</response> /// <response code="503">Service unavailable.</response> public async Task <Result <bool, ErrorResponse> > CreateTransactionAsync( ECurrency currency, string address, string privateKey, string amount, string target, string merchantOrderID = null, string note = null, string nonce = null, Guid?idem = null, Guid?paymentID = null, string paymentSig = null) { if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException(nameof(address)); } else if (string.IsNullOrWhiteSpace(privateKey)) { throw new ArgumentNullException(nameof(privateKey)); } else if (string.IsNullOrWhiteSpace(amount)) { throw new ArgumentNullException(nameof(amount)); } else if (string.IsNullOrWhiteSpace(target)) { throw new ArgumentNullException(nameof(target)); } else if (paymentID != null) { if (string.IsNullOrWhiteSpace(paymentSig)) { throw new ArgumentException(nameof(paymentSig)); } } var result = new Result <bool, ErrorResponse>(); var requestUri = $"{mEnv.BaseUrl}/v1/Transactions"; Result <FeeResponse, ErrorResponse> getFee = await getFeeAsync(currency); if (getFee.IsFailure) { result.Error = getFee.Error; return(result); } string fee = getFee.Data.MinimumFee; string signature = null; if (currency == ECurrency.BTC) { signature = await getBtcTransactionSignatureAsync(currency, address, amount, fee, target, privateKey); } else { if (nonce == null) { nonce = GluwaService.GetNonceString(); } signature = getGluwacoinTransactionSignature(currency, amount, fee, nonce, address, target, privateKey); } TransactionRequest bodyParams = new TransactionRequest { Signature = signature, Currency = currency, Target = target, Amount = amount, Fee = getFee.Data.MinimumFee, Source = address, Nonce = nonce, MerchantOrderID = merchantOrderID, Note = note, Idem = idem, PaymentID = paymentID, PaymentSig = paymentSig }; string json = bodyParams.ToJson(); StringContent content = new StringContent(json, Encoding.UTF8, "application/json"); try { using (HttpClient httpClient = new HttpClient()) using (var response = await httpClient.PostAsync(requestUri, content)) { if (response.IsSuccessStatusCode) { result.IsSuccess = true; result.Data = true; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }
/// <summary> /// Get a list of transactions for specified currency. /// </summary> /// <param name="currency">Currency type.</param> /// <param name="address">Your public Address.</param> /// <param name="privateKey">Your Private Key.</param> /// <param name="limit">Number of transactions to include in the result. optional. Defaults to 100.</param> /// <param name="status">Filter by transaction status. Optional. Defaults to Confimred.</param> /// <param name="offset">Number of transactions to skip; used for pagination. Optional. Default to 0.</param> /// <response code="200">List of transactions associated with the address.</response> /// <response code="400">Invalid request or Address does not have a valid format.</response> /// <response code="403">Request signature header is not valid.</response> /// <response code="500">Server error.</response> /// <response code="503">Service unavailable.</response> public async Task <Result <List <TransactionResponse>, ErrorResponse> > GetTransactionListAsync( ECurrency currency, string address, string privateKey, uint limit = 100, ETransactionStatusFilter status = ETransactionStatusFilter.Confirmed, uint offset = 0) { if (string.IsNullOrWhiteSpace(address)) { throw new ArgumentNullException(nameof(address)); } else if (string.IsNullOrWhiteSpace(privateKey)) { throw new ArgumentNullException(nameof(privateKey)); } var result = new Result <List <TransactionResponse>, ErrorResponse>(); string requestUri = $"{mEnv.BaseUrl}/v1/{currency}/Addresses/{address}/Transactions"; var queryParams = new List <string>(); if (offset > 0) { queryParams.Add($"offset={offset}"); } if (limit > 0) { queryParams.Add($"limit={limit}"); } if (queryParams.Any()) { queryParams.Add($"status={status}"); requestUri = $"{requestUri}?{string.Join("&", queryParams)}"; } try { using (HttpClient httpClient = new HttpClient()) { httpClient.DefaultRequestHeaders.Add(X_REQUEST_SIGNATURE, GluwaService.GetAddressSignature(privateKey, currency, mEnv)); using (HttpResponseMessage response = await httpClient.GetAsync(requestUri)) { if (response.IsSuccessStatusCode) { List <TransactionResponse> transactionResponse = await response.Content.ReadAsAsync <List <TransactionResponse> >(); result.IsSuccess = true; result.Data = transactionResponse; return(result); } string contentString = await response.Content.ReadAsStringAsync(); result.Error = ResponseHandler.GetError(response.StatusCode, requestUri, contentString); } } } catch (HttpRequestException) { result.IsSuccess = false; result.Error = ResponseHandler.GetExceptionError(); } return(result); }