Add files via upload
This commit is contained in:
93
src/ShapeShift/CancelResult.cs
Normal file
93
src/ShapeShift/CancelResult.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ability to cancel pending exchanges.
|
||||
/// </summary>
|
||||
public class CancelResult
|
||||
{
|
||||
/*url: shapeshift.io/cancelpending
|
||||
method: POST
|
||||
data type: JSON
|
||||
data required: address = The deposit address associated with the pending transaction
|
||||
|
||||
Example data : {address : "1HB5XMLmzFVj8ALj6mfBsbifRoD4miY36v"}
|
||||
|
||||
Success Output:
|
||||
|
||||
{ success : " Pending Transaction cancelled " }
|
||||
|
||||
Error Output:
|
||||
|
||||
{ error : {errorMessage} }
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// True if cancel was successful.
|
||||
/// </summary>
|
||||
public bool Success { get; private set; }
|
||||
/// <summary>
|
||||
/// Message returned from cancel operation, if any.
|
||||
/// </summary>
|
||||
public string Message { get; private set; }
|
||||
/// <summary>
|
||||
/// Error message thrown during cancel, if any.
|
||||
/// </summary>
|
||||
public string Error { get; private set; }
|
||||
|
||||
private CancelResult() { }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to cancel pending exchange
|
||||
/// </summary>
|
||||
/// <param name="Address">The deposit address associated with the pending transaction.</param>
|
||||
/// <returns>Result of cancel operation.</returns>
|
||||
internal static async Task<CancelResult> CancelAsync(string Address)
|
||||
{
|
||||
//Get URI for POST request
|
||||
Uri uri = GetUri();
|
||||
//Generate JSON data string
|
||||
string data = CreateData(Address);
|
||||
//Send POST request
|
||||
string response = await RestServices.GetPostResponseAsync(uri, data).ConfigureAwait(false);
|
||||
//Parse response for results
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetUri() =>
|
||||
new Uri(@"https://shapeshift.io/cancelpending");
|
||||
|
||||
private static string CreateData(string Address) =>
|
||||
"{" + string.Format("\"address\":\"{0}\"", Address) + "}";
|
||||
|
||||
private static async Task<CancelResult> ParseResponseAsync(string response)
|
||||
{
|
||||
CancelResult result = new CancelResult();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "success")
|
||||
{
|
||||
result.Success = true;
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.Message = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "error")
|
||||
{
|
||||
result.Success = false;
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.Error = jtr.Value.ToString();
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
103
src/ShapeShift/EmailReceipt.cs
Normal file
103
src/ShapeShift/EmailReceipt.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Status of Email request.
|
||||
/// </summary>
|
||||
public enum EmailStatuses { Success, Failure }
|
||||
|
||||
/// <summary>
|
||||
/// Provides ability to request a receipt for a transaction to be sent via email.
|
||||
/// </summary>
|
||||
public class EmailReceipt
|
||||
{
|
||||
/*url: shapeshift.io/mail
|
||||
method: POST
|
||||
data type: JSON
|
||||
data required:
|
||||
email = the address for receipt email to be sent to
|
||||
txid = the transaction id of the transaction TO the user (ie the txid for the withdrawal NOT the deposit)
|
||||
example data {"email":"mail@example.com", "txid":"123ABC"}
|
||||
|
||||
Success Output:
|
||||
{"email":
|
||||
{
|
||||
"status":"success",
|
||||
"message":"Email receipt sent"
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Status of receipt request.
|
||||
/// </summary>
|
||||
public EmailStatuses Status { get; private set; }
|
||||
/// <summary>
|
||||
/// Message returned by request, if any.
|
||||
/// </summary>
|
||||
public string Message { get; private set; }
|
||||
/// <summary>
|
||||
/// Error thrown by request, if any.
|
||||
/// </summary>
|
||||
public string Error { get; private set; }
|
||||
|
||||
private EmailReceipt() { }
|
||||
|
||||
/// <summary>
|
||||
/// Requests a receipt for transaction to be sent via email.
|
||||
/// </summary>
|
||||
/// <param name="Email">Email address to send receipt to.</param>
|
||||
/// <param name="TxID">Transaction ID of the transaction sent to the user.</param>
|
||||
/// <returns>Result of receipt request.</returns>
|
||||
internal static async Task<EmailReceipt> RequestAsync(string Email, string TxID)
|
||||
{
|
||||
//Get URI for POST request
|
||||
Uri uri = GetUri();
|
||||
//Generate JSON data as string to send
|
||||
string data = CreateData(Email, TxID);
|
||||
//Send POST request and awaits response
|
||||
string response = await RestServices.GetPostResponseAsync(uri, data).ConfigureAwait(false);
|
||||
//Parse response for results
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetUri() =>
|
||||
new Uri(@"https://shapeshift.io/mail");
|
||||
|
||||
private static string CreateData(string Email, string TxID) =>
|
||||
"{" + string.Format("\"email\":\"{0}\", \"txid\":\"{1}\"", Email, TxID) + "}";
|
||||
|
||||
private static async Task<EmailReceipt> ParseResponseAsync(string response)
|
||||
{
|
||||
EmailReceipt receipt = new EmailReceipt();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "status")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
receipt.Status = jtr.Value.ToString() == "success" ? EmailStatuses.Success : EmailStatuses.Failure;
|
||||
}
|
||||
else if (jtr.Value.ToString() == "message")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
receipt.Message = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "error")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
receipt.Error = jtr.Value.ToString();
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return receipt;
|
||||
}
|
||||
}
|
||||
}
|
139
src/ShapeShift/QuoteRequest.cs
Normal file
139
src/ShapeShift/QuoteRequest.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ability to request quotes for specific pair exchanges.
|
||||
/// </summary>
|
||||
public class QuoteRequest
|
||||
{
|
||||
/*url: shapeshift.io/sendamount
|
||||
method: POST
|
||||
data type: JSON
|
||||
|
||||
Data required:
|
||||
|
||||
amount = the amount to be sent to the withdrawal address
|
||||
pair = what coins are being exchanged in the form [input coin]_[output coin] ie ltc_btc
|
||||
|
||||
example data {"amount":123, "pair":"ltc_btc"}
|
||||
|
||||
Success Output:
|
||||
|
||||
{
|
||||
success:
|
||||
{
|
||||
pair: [pair],
|
||||
withdrawalAmount: [Withdrawal Amount], // Amount of the output coin you will receive
|
||||
depositAmount: [Deposit Amount], // Exact amount of input coin to send in
|
||||
expiration: [timestamp when this will expire],
|
||||
quotedRate: [the exchange rate to be honored]
|
||||
minerFee: [miner fee for this transaction]
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Coin pair to exchange between.
|
||||
/// </summary>
|
||||
public string Pair { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount of coin to be received by user.
|
||||
/// </summary>
|
||||
public double WithdrawalAmount { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount of coin required to be deposited.
|
||||
/// </summary>
|
||||
public double DepositAmount { get; private set; }
|
||||
/// <summary>
|
||||
/// Expiration timestamp of quote.
|
||||
/// </summary>
|
||||
public double Expiration { get; private set; }
|
||||
/// <summary>
|
||||
/// Quoted rate of exchange.
|
||||
/// </summary>
|
||||
public double QuotedRate { get; private set; }
|
||||
/// <summary>
|
||||
/// Fee to be sent to miners to fascilitate exchange.
|
||||
/// </summary>
|
||||
public double MinerFee { get; private set; }
|
||||
/// <summary>
|
||||
/// Error thrown by request, if any.
|
||||
/// </summary>
|
||||
public string Error { get; private set; }
|
||||
|
||||
private QuoteRequest() { }
|
||||
|
||||
/// <summary>
|
||||
/// Requests a quote for an exchange without exchanging.
|
||||
/// </summary>
|
||||
/// <param name="Pair">Coin pair to exchange between.</param>
|
||||
/// <param name="Amount">Amount of coin to be sent to withdrawal address.</param>
|
||||
/// <returns>Quote for exchange information.</returns>
|
||||
internal static async Task<QuoteRequest> RequestAsync(string Pair, double Amount)
|
||||
{
|
||||
Uri uri = GetUri();
|
||||
string data = CreateData(Pair, Amount);
|
||||
string response = await RestServices.GetPostResponseAsync(uri, data).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetUri() =>
|
||||
new Uri(@"https://shapeshift.io/sendamount");
|
||||
|
||||
private static string CreateData(string Pair, double Amount) =>
|
||||
"{" + string.Format("\"amount\":\"{0}\", \"pair\":\"{1}\"", Amount.ToString(), Pair) + "}";
|
||||
|
||||
private static async Task<QuoteRequest> ParseResponseAsync(string response)
|
||||
{
|
||||
QuoteRequest request = new QuoteRequest();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "pair")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.Pair = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "withdrawalAmount")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.WithdrawalAmount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "depositAmount")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.DepositAmount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "expiration")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.Expiration = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "quotedRate")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.QuotedRate = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "minerFee")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.MinerFee = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "error")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.Error = jtr.Value.ToString();
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
116
src/ShapeShift/RecentTx.cs
Normal file
116
src/ShapeShift/RecentTx.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to information on recent exchanges completed by ShapeShift.
|
||||
/// </summary>
|
||||
public class RecentTx
|
||||
{
|
||||
/*url: shapeshift.io/recenttx/[max]
|
||||
method: GET
|
||||
|
||||
[max] is an optional maximum number of transactions to return.
|
||||
If [max] is not specified this will return 5 transactions.
|
||||
Also, [max] must be a number between 1 and 50 (inclusive).
|
||||
|
||||
Success Output:
|
||||
[
|
||||
{
|
||||
curIn : [currency input],
|
||||
curOut: [currency output],
|
||||
amount: [amount],
|
||||
timestamp: [time stamp] //in seconds
|
||||
},
|
||||
...
|
||||
]
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Currency user sent to exchange.
|
||||
/// </summary>
|
||||
public string CurrencyInput { get; private set; }
|
||||
/// <summary>
|
||||
/// Currency user requested from exchange.
|
||||
/// </summary>
|
||||
public string CurrencyOutput { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount sent to user's withdrawal address.
|
||||
/// </summary>
|
||||
public double Amount { get; private set; }
|
||||
/// <summary>
|
||||
/// Timestamp of exchange.
|
||||
/// </summary>
|
||||
public double TimeStamp { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets information on recent transactions completed by ShapeShift.
|
||||
/// </summary>
|
||||
/// <param name="Max">Maximum number of transactions to return. Must be betweeen 1 and 50, inclusive.</param>
|
||||
/// <returns>List of recent transactions.</returns>
|
||||
internal static async Task<List<RecentTx>> GetRecentTransactionsAsync(int Max)
|
||||
{
|
||||
if (Max < 1 || Max > 50) throw new InvalidOperationException();
|
||||
Uri uri = GetUri(Max);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets information on recent transactions completed by ShapeShift.
|
||||
/// </summary>
|
||||
/// <returns>List of last 5 transactions.</returns>
|
||||
internal static async Task<List<RecentTx>> GetRecentTransactionsAsync() =>
|
||||
await GetRecentTransactionsAsync(5).ConfigureAwait(false);
|
||||
|
||||
private static Uri GetUri(int max = 5) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/recenttx/{0}", max.ToString()));
|
||||
|
||||
private static async Task<List<RecentTx>> ParseResponseAsync(string response)
|
||||
{
|
||||
List<RecentTx> TxList = new List<RecentTx>();
|
||||
RecentTx NewTx = new RecentTx();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.TokenType.ToString() == "StartObject")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(NewTx.CurrencyInput))
|
||||
TxList.Add(NewTx);
|
||||
NewTx = new RecentTx();
|
||||
}
|
||||
else if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "curIn")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.CurrencyInput = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "curOut")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.CurrencyOutput = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "amount")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.Amount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "timestamp")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.TimeStamp = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(NewTx.CurrencyInput))
|
||||
TxList.Add(NewTx);
|
||||
|
||||
return TxList;
|
||||
}
|
||||
}
|
||||
}
|
185
src/ShapeShift/SendAmountRequest.cs
Normal file
185
src/ShapeShift/SendAmountRequest.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ability to request amount needed to be sent to complete transaction.
|
||||
/// </summary>
|
||||
public class SendAmountRequest
|
||||
{
|
||||
/*url: shapeshift.io/sendamount
|
||||
method: POST
|
||||
data type: JSON
|
||||
|
||||
Data required:
|
||||
|
||||
amount = the amount to be sent to the withdrawal address
|
||||
withdrawal = the address for coin to be sent to
|
||||
pair = what coins are being exchanged in the form [input coin]_[output coin] ie ltc_btc
|
||||
returnAddress = (Optional) address to return deposit to if anything goes wrong with exchange
|
||||
destTag = (Optional) Destination tag that you want appended to a Ripple payment to you
|
||||
rsAddress = (Optional) For new NXT accounts to be funded, supply this on NXT payment to you
|
||||
apiKey = (Optional) Your affiliate PUBLIC KEY, for volume tracking, affiliate payments, split-shifts, etc...
|
||||
|
||||
example data {"amount":123, "withdrawal":"123ABC", "pair":"ltc_btc", returnAddress:"BBBBBBB"}
|
||||
|
||||
Success Output:
|
||||
|
||||
{
|
||||
success:
|
||||
{
|
||||
pair: [pair],
|
||||
withdrawal: [Withdrawal Address], //-- will match address submitted in post
|
||||
withdrawalAmount: [Withdrawal Amount], // Amount of the output coin you will receive
|
||||
deposit: [Deposit Address (or memo field if input coin is BTS / BITUSD)],
|
||||
depositAmount: [Deposit Amount], // Exact amount of input coin to send in
|
||||
expiration: [timestamp when this will expire],
|
||||
quotedRate: [the exchange rate to be honored]
|
||||
apiPubKey: [public API attached to this shift, if one was given]
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Coin pair requested for exchange.
|
||||
/// </summary>
|
||||
public string Pair { get; private set; }
|
||||
/// <summary>
|
||||
/// Address to send exchanged coins to.
|
||||
/// </summary>
|
||||
public string WithdrawalAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount of coins to be received from exchange.
|
||||
/// </summary>
|
||||
public double WithdrawalAmount { get; private set; }
|
||||
/// <summary>
|
||||
/// Address to send coins to be exchanged.
|
||||
/// </summary>
|
||||
public string DepositAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount of coins required to complete exchange.
|
||||
/// </summary>
|
||||
public double DepositAmount { get; private set; }
|
||||
/// <summary>
|
||||
/// Exchange expiration timestamp.
|
||||
/// </summary>
|
||||
public double Expiration { get; private set; }
|
||||
/// <summary>
|
||||
/// Quoted rate of exchange.
|
||||
/// </summary>
|
||||
public double QuotedRate { get; private set; }
|
||||
/// <summary>
|
||||
/// Public API key attached to this exchange, if any.
|
||||
/// </summary>
|
||||
public string APIKey { get; private set; }
|
||||
/// <summary>
|
||||
/// Error thrown by request, if any.
|
||||
/// </summary>
|
||||
public string Error { get; private set; }
|
||||
|
||||
private SendAmountRequest() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets information on pending exchange.
|
||||
/// </summary>
|
||||
/// <param name="Amount">Amount to be sent to withdrawal address.</param>
|
||||
/// <param name="Address">The withdrawal address.</param>
|
||||
/// <param name="Pair">The coin pair.</param>
|
||||
/// <param name="ReturnAddress">Address to return coins to if exchange fails.</param>
|
||||
/// <param name="RippleTag">Destination tag that you want appended to a Ripple payment to you.</param>
|
||||
/// <param name="NXTRsAddress">For new NXT accounts to be funded, supply this on NXT payment to you.</param>
|
||||
/// <param name="APIKey">Your affiliate PUBLIC KEY, for volume tracking, affiliate payments, split-shifts, etc...</param>
|
||||
/// <returns>Information on pending exchange.</returns>
|
||||
internal static async Task<SendAmountRequest> RequestAsync(double Amount, string Address, string Pair, string ReturnAddress = "", string RippleTag = "", string NXTRsAddress = "", string APIKey = "")
|
||||
{
|
||||
Uri uri = GetUri();
|
||||
string data = CreateData(Amount, Address, Pair, ReturnAddress, RippleTag, NXTRsAddress, APIKey);
|
||||
string response = await RestServices.GetPostResponseAsync(uri, data).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetUri() =>
|
||||
new Uri(@"https://shapeshift.io/sendamount");
|
||||
|
||||
private static string CreateData(double Amount, string Address, string Pair, string ReturnAddress, string RippleTag, string NXTRsAddress, string APIKey)
|
||||
{
|
||||
string dataFormat = "\"{0}\":\"{1}\"";
|
||||
string data = "{";
|
||||
data += string.Format(dataFormat, "amount", Amount.ToString());
|
||||
data += ", " + string.Format(dataFormat, "withdrawal", Address);
|
||||
data += ", " + string.Format(dataFormat, "pair", Pair);
|
||||
if (!string.IsNullOrEmpty(ReturnAddress))
|
||||
data += ", " + string.Format(dataFormat, "returnAddress", ReturnAddress);
|
||||
if (!string.IsNullOrEmpty(RippleTag))
|
||||
data += ", " + string.Format(dataFormat, "destTag", RippleTag);
|
||||
if (!string.IsNullOrEmpty(NXTRsAddress))
|
||||
data += ", " + string.Format(dataFormat, "rsAddress", NXTRsAddress);
|
||||
if (!string.IsNullOrEmpty(APIKey))
|
||||
data += ", " + string.Format(dataFormat, "apiKey", APIKey);
|
||||
data += "}";
|
||||
return data;
|
||||
}
|
||||
|
||||
private static async Task<SendAmountRequest> ParseResponseAsync(string response)
|
||||
{
|
||||
SendAmountRequest request = new SendAmountRequest();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "pair")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.Pair = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "withdrawal")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.WithdrawalAddress = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "withdrawalAmount")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.WithdrawalAmount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "deposit")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.DepositAddress = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "depositAmount")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.DepositAmount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "expiration")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.Expiration = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "quotedRate")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.QuotedRate = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "apiPubKey")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.APIKey = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "error")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
request.Error = jtr.Value.ToString();
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return request;
|
||||
}
|
||||
}
|
||||
}
|
166
src/ShapeShift/ShiftResult.cs
Normal file
166
src/ShapeShift/ShiftResult.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ability to send exchange requests to ShapeShift.
|
||||
/// </summary>
|
||||
public class ShiftResult
|
||||
{
|
||||
/*url: shapeshift.io/shift
|
||||
method: POST
|
||||
data type: JSON
|
||||
data required:
|
||||
withdrawal = the address for resulting coin to be sent to
|
||||
pair = what coins are being exchanged in the form [input coin]_[output coin] ie btc_ltc
|
||||
returnAddress = (Optional) address to return deposit to if anything goes wrong with exchange
|
||||
destTag = (Optional) Destination tag that you want appended to a Ripple payment to you
|
||||
rsAddress = (Optional) For new NXT accounts to be funded, you supply this on NXT payment to you
|
||||
apiKey = (Optional) Your affiliate PUBLIC KEY, for volume tracking, affiliate payments, split-shifts, etc...
|
||||
|
||||
example data: {"withdrawal":"AAAAAAAAAAAAA", "pair":"btc_ltc", returnAddress:"BBBBBBBBBBB"}
|
||||
|
||||
Success Output:
|
||||
{
|
||||
deposit: [Deposit Address (or memo field if input coin is BTS / BITUSD)],
|
||||
depositType: [Deposit Type (input coin symbol)],
|
||||
withdrawal: [Withdrawal Address], //-- will match address submitted in post
|
||||
withdrawalType: [Withdrawal Type (output coin symbol)],
|
||||
public: [NXT RS-Address pubkey (if input coin is NXT)],
|
||||
xrpDestTag : [xrpDestTag (if input coin is XRP)],
|
||||
apiPubKey: [public API attached to this shift, if one was given]
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Address to send coins to exchange.
|
||||
/// </summary>
|
||||
public string DepositAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// Currency to exchange from.
|
||||
/// </summary>
|
||||
public string DepositCoin { get; private set; }
|
||||
/// <summary>
|
||||
/// Address to send exchanged coins to.
|
||||
/// </summary>
|
||||
public string WithdrawalAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// Currency to exchange to.
|
||||
/// </summary>
|
||||
public string WithdrawalCoin { get; private set; }
|
||||
/// <summary>
|
||||
/// Destination tag to be appended to Ripple payment.
|
||||
/// </summary>
|
||||
public string RippleTag { get; private set; }
|
||||
/// <summary>
|
||||
/// NXT RS-Address public key.
|
||||
/// </summary>
|
||||
public string NXTRsAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// Public API key attached to this exchange, if any.
|
||||
/// </summary>
|
||||
public string APIKey { get; private set; }
|
||||
/// <summary>
|
||||
/// Error thrown by exchange request, if any.
|
||||
/// </summary>
|
||||
public string Error { get; private set; }
|
||||
|
||||
private ShiftResult() { }
|
||||
|
||||
/// <summary>
|
||||
/// Sends Shift request.
|
||||
/// </summary>
|
||||
/// <param name="Withdrawal">Address for resulting coins to be sent to.</param>
|
||||
/// <param name="Pair">Currency pair for exchange.</param>
|
||||
/// <param name="Return">Address to return coins to if exchange fails.</param>
|
||||
/// <param name="RippleTag">Destination tag that you want appended to a Ripple payment to you.</param>
|
||||
/// <param name="NXTRsAddress">For new NXT accounts to be funded, you supply this on NXT payment to you.</param>
|
||||
/// <param name="APIKey">Your affiliate PUBLIC KEY, for volume tracking, affiliate payments, split-shifts, etc...</param>
|
||||
/// <returns>Result of Shift request.</returns>
|
||||
internal static async Task<ShiftResult> ShiftAsync(string Withdrawal, string Pair, string Return = "", string RippleTag = "", string NXTRsAddress = "", string APIKey = "")
|
||||
{
|
||||
Uri uri = GetUri();
|
||||
string data = CreateData(Withdrawal, Pair, Return, RippleTag, NXTRsAddress, APIKey);
|
||||
string response = await RestServices.GetPostResponseAsync(uri, data).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetUri() =>
|
||||
new Uri(@"https://shapeshift.io/shift");
|
||||
|
||||
private static string CreateData(string Withdrawal, string Pair, string Return, string RippleTag, string NXTRsAddress, string APIKey)
|
||||
{
|
||||
string dataFormat = "\"{0}\":\"{1}\"";
|
||||
string data = "{";
|
||||
data += string.Format(dataFormat, "withdrawal", Withdrawal);
|
||||
data += ", " + string.Format(dataFormat, "pair", Pair);
|
||||
if (!string.IsNullOrEmpty(Return))
|
||||
data += ", " + string.Format(dataFormat, "returnAddress", Return);
|
||||
if (!string.IsNullOrEmpty(RippleTag))
|
||||
data += ", " + string.Format(dataFormat, "destTag", RippleTag);
|
||||
if (!string.IsNullOrEmpty(NXTRsAddress))
|
||||
data += ", " + string.Format(dataFormat, "rsAddress", NXTRsAddress);
|
||||
if (!string.IsNullOrEmpty(APIKey))
|
||||
data += ", " + string.Format(dataFormat, "apiKey", APIKey);
|
||||
data += "}";
|
||||
return data;
|
||||
}
|
||||
|
||||
private static async Task<ShiftResult> ParseResponseAsync(string response)
|
||||
{
|
||||
ShiftResult result = new ShiftResult();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "deposit")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.DepositAddress = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "depositType")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.DepositCoin = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "withdrawal")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.WithdrawalAddress = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "withdrawalType")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.WithdrawalCoin = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "public")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.NXTRsAddress = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "xrpDestTag")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.RippleTag = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "apiPubKey")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.APIKey = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "error")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
result.Error = jtr.Value.ToString();
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
127
src/ShapeShift/SupportedCoin.cs
Normal file
127
src/ShapeShift/SupportedCoin.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Exchange availability status of coin.
|
||||
/// </summary>
|
||||
public enum CoinStatuses { Available, Unavailable }
|
||||
|
||||
/// <summary>
|
||||
/// Provides information on specific currencies.
|
||||
/// </summary>
|
||||
public class SupportedCoin
|
||||
{
|
||||
/*url: shapeshift.io/getcoins
|
||||
method: GET
|
||||
|
||||
Success Output:
|
||||
|
||||
{
|
||||
"SYMBOL1" :
|
||||
{
|
||||
name: ["Currency Formal Name"],
|
||||
symbol: <"SYMBOL1">,
|
||||
image: ["https://shapeshift.io/images/coins/coinName.png"],
|
||||
status: [available / unavailable]
|
||||
}
|
||||
(one listing per supported currency)
|
||||
}
|
||||
|
||||
The status can be either "available" or "unavailable". Sometimes coins become temporarily unavailable during updates or
|
||||
unexpected service issues.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Name of currency.
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
/// <summary>
|
||||
/// Ticker symbol for currency.
|
||||
/// </summary>
|
||||
public string Symbol { get; private set; }
|
||||
/// <summary>
|
||||
/// Link to currency icon.
|
||||
/// </summary>
|
||||
public string ImageLink { get; private set; }
|
||||
/// <summary>
|
||||
/// Currency exchange availability.
|
||||
/// </summary>
|
||||
public CoinStatuses Status { get; private set; }
|
||||
|
||||
private SupportedCoin() { }
|
||||
|
||||
/// <summary>
|
||||
/// Provides information on all currencies supported by ShapeShift.
|
||||
/// </summary>
|
||||
/// <returns>List of all supported currencies.</returns>
|
||||
internal static async Task<List<SupportedCoin>> GetCoinsAsync()
|
||||
{
|
||||
Uri uri = GetUri();
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides information on a specific currency supported by ShapeShift.
|
||||
/// </summary>
|
||||
/// <param name="Symbol">Ticker symbol of currency.</param>
|
||||
/// <returns>Information on specific supported currency.</returns>
|
||||
internal static async Task<SupportedCoin> GetCoinAsync(string Symbol) =>
|
||||
(await GetCoinsAsync().ConfigureAwait(false)).First(c => c.Symbol == Symbol);
|
||||
|
||||
private static Uri GetUri() => new Uri(@"https://shapeshift.io/getcoins");
|
||||
|
||||
private static async Task<List<SupportedCoin>> ParseResponseAsync(string response)
|
||||
{
|
||||
List<SupportedCoin> CoinList = new List<SupportedCoin>();
|
||||
SupportedCoin ToAdd = new SupportedCoin();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.TokenType.ToString() == "StartObject")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ToAdd.Name))
|
||||
CoinList.Add(ToAdd);
|
||||
ToAdd = new SupportedCoin();
|
||||
continue;
|
||||
}
|
||||
if (jtr.Value != null)
|
||||
{
|
||||
if (jtr.Value.ToString() == "name")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
ToAdd.Name = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "symbol")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
ToAdd.Symbol = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "image")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
ToAdd.ImageLink = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "status")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
ToAdd.Status = jtr.Value.ToString() == "available" ? CoinStatuses.Available : CoinStatuses.Unavailable;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(ToAdd.Name))
|
||||
CoinList.Add(ToAdd);
|
||||
|
||||
return CoinList;
|
||||
}
|
||||
}
|
||||
}
|
84
src/ShapeShift/TimeRemaining.cs
Normal file
84
src/ShapeShift/TimeRemaining.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Statuses available for Time Remaining requests.
|
||||
/// </summary>
|
||||
public enum TimeStatuses { Pending, Expired }
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to information on time remaining for pending deposits.
|
||||
/// </summary>
|
||||
public class TimeRemaining
|
||||
{
|
||||
/*url: shapeshift.io/timeremaining/[address]
|
||||
method: GET
|
||||
|
||||
[address] is the deposit address to look up.
|
||||
|
||||
Success Output:
|
||||
|
||||
{
|
||||
status:"pending",
|
||||
seconds_remaining: 600
|
||||
}
|
||||
|
||||
The status can be either "pending" or "expired".
|
||||
If the status is expired then seconds_remaining will show 0.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Status of deposit.
|
||||
/// </summary>
|
||||
public TimeStatuses Status { get; private set; }
|
||||
/// <summary>
|
||||
/// Seconds remaining before transaction expires.
|
||||
/// </summary>
|
||||
public double SecondsRemaining { get; private set; }
|
||||
|
||||
private TimeRemaining() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets status of deposit and time remaining to complete deposit before expiration.
|
||||
/// </summary>
|
||||
/// <param name="Address">The deposit address to look up.</param>
|
||||
/// <returns>Time remaining for deposit.</returns>
|
||||
internal static async Task<TimeRemaining> GetTimeRemainingAsync(string Address)
|
||||
{
|
||||
Uri uri = GetUri(Address);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetUri(string Address) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/timeremaining/{0}", Address));
|
||||
|
||||
private static async Task<TimeRemaining> ParseResponseAsync(string response)
|
||||
{
|
||||
TimeRemaining tr = new TimeRemaining();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "status")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
tr.Status = jtr.Value.ToString() == "pending" ? TimeStatuses.Pending : TimeStatuses.Expired;
|
||||
}
|
||||
else if (jtr.Value.ToString() == "seconds_remaining")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
tr.SecondsRemaining = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return tr;
|
||||
}
|
||||
}
|
||||
}
|
103
src/ShapeShift/TradingLimit.cs
Normal file
103
src/ShapeShift/TradingLimit.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to trade limits for specific coin pairs.
|
||||
/// </summary>
|
||||
public class TradingLimit
|
||||
{
|
||||
/*url: shapeshift.io/limit/[pair]
|
||||
method: GET
|
||||
|
||||
[pair] is any valid coin pair such as btc_ltc or ltc_btc
|
||||
|
||||
Success Output:
|
||||
{
|
||||
"pair" : "btc_ltc",
|
||||
"limit" : "1.2345"
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Currency pair.
|
||||
/// </summary>
|
||||
public string Pair { get; private set; }
|
||||
/// <summary>
|
||||
/// Trade limit.
|
||||
/// </summary>
|
||||
public double Limit { get; private set; }
|
||||
|
||||
private TradingLimit() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets trade limit for specified currency pair.
|
||||
/// </summary>
|
||||
/// <param name="Pair">Currency pair to exchange.</param>
|
||||
/// <returns>Trading limit information.</returns>
|
||||
internal static async Task<TradingLimit> GetLimitAsync(string Pair)
|
||||
{
|
||||
Uri uri = GetUri(Pair);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets trade limit for specified currency pair.
|
||||
/// </summary>
|
||||
/// <param name="Ticker1">Ticker for currency to exchange from.</param>
|
||||
/// <param name="Ticker2">Ticker for currency to exchange to.</param>
|
||||
/// <returns>Trading limit information.</returns>
|
||||
internal static async Task<TradingLimit> GetLimitAsync(string Ticker1, string Ticker2) =>
|
||||
await GetLimitAsync(string.Format("{0}_{1}", Ticker1, Ticker2)).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets list of all trade limits.
|
||||
/// </summary>
|
||||
/// <returns>List of all trade limits.</returns>
|
||||
internal static async Task<List<TradingLimit>> GetAllLimitsAsync()
|
||||
{
|
||||
List<TradingLimit> LimitList = new List<TradingLimit>();
|
||||
List<TradingPair> PairList = await TradingPair.GetAllPairsAsync().ConfigureAwait(false);
|
||||
foreach (TradingPair tp in PairList)
|
||||
{
|
||||
TradingLimit NewLimit = await GetLimitAsync(tp.Pair).ConfigureAwait(false);
|
||||
LimitList.Add(NewLimit);
|
||||
}
|
||||
return LimitList;
|
||||
}
|
||||
|
||||
private static Uri GetUri(string Pair) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/limit/{0}", Pair));
|
||||
|
||||
private static async Task<TradingLimit> ParseResponseAsync(string response)
|
||||
{
|
||||
TradingLimit limit = new TradingLimit();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value != null)
|
||||
{
|
||||
if (jtr.Value.ToString() == "pair")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
limit.Pair = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "limit")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
limit.Limit = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
}
|
||||
}
|
135
src/ShapeShift/TradingMarketInfo.cs
Normal file
135
src/ShapeShift/TradingMarketInfo.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to exchange market info for currency pairs.
|
||||
/// </summary>
|
||||
public class TradingMarketInfo
|
||||
{
|
||||
/*url: shapeshift.io/marketinfo/[pair]
|
||||
method: GET
|
||||
|
||||
[pair] (OPTIONAL) is any valid coin pair such as btc_ltc or ltc_btc.
|
||||
The pair is not required and if not specified will return an array of all market infos.
|
||||
|
||||
Success Output:
|
||||
{
|
||||
"pair" : "btc_ltc",
|
||||
"rate" : 130.12345678,
|
||||
"limit" : 1.2345,
|
||||
"min" : 0.02621232,
|
||||
"minerFee" : 0.0001
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Currency pair.
|
||||
/// </summary>
|
||||
public string Pair { get; private set; }
|
||||
/// <summary>
|
||||
/// Exchange rate.
|
||||
/// </summary>
|
||||
public double Rate { get; private set; }
|
||||
/// <summary>
|
||||
/// Exchange limit.
|
||||
/// </summary>
|
||||
public double Limit { get; private set; }
|
||||
/// <summary>
|
||||
/// Minimum exchange amount.
|
||||
/// </summary>
|
||||
public double Min { get; private set; }
|
||||
/// <summary>
|
||||
/// Fee to be sent to miners for exchange.
|
||||
/// </summary>
|
||||
public double MinerFee { get; private set; }
|
||||
|
||||
private TradingMarketInfo() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets market info for specific currency pair.
|
||||
/// </summary>
|
||||
/// <param name="Pair">Pair to get information for.</param>
|
||||
/// <returns>Market Information.</returns>
|
||||
internal static async Task<TradingMarketInfo> GetMarketInfoAsync(string Pair)
|
||||
{
|
||||
Uri uri = GetUri(Pair);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets market info for specific currency pair.
|
||||
/// </summary>
|
||||
/// <param name="Ticker1">Ticker for currency to exchange from.</param>
|
||||
/// <param name="Ticker2">Ticker for currency to exchange to.</param>
|
||||
/// <returns>Market Information.</returns>
|
||||
internal static async Task<TradingMarketInfo> GetMarketInfoAsync(string Ticker1, string Ticker2) =>
|
||||
await GetMarketInfoAsync(string.Format("{0}_{1}", Ticker1, Ticker2)).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Gets market info for all currency pairs.
|
||||
/// </summary>
|
||||
/// <returns>List of Market Information.</returns>
|
||||
internal static async Task<List<TradingMarketInfo>> GetAllMarketsAsync()
|
||||
{
|
||||
List<TradingMarketInfo> MarketList = new List<TradingMarketInfo>();
|
||||
List<TradingPair> PairList = await TradingPair.GetAllPairsAsync().ConfigureAwait(false);
|
||||
foreach (TradingPair tp in PairList)
|
||||
{
|
||||
TradingMarketInfo NewMarket = await GetMarketInfoAsync(tp.Pair).ConfigureAwait(false);
|
||||
MarketList.Add(NewMarket);
|
||||
}
|
||||
return MarketList;
|
||||
}
|
||||
|
||||
private static Uri GetUri(string Pair) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/marketinfo/{0}", Pair));
|
||||
|
||||
private static async Task<TradingMarketInfo> ParseResponseAsync(string response)
|
||||
{
|
||||
TradingMarketInfo MarketInfo = new TradingMarketInfo();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value != null)
|
||||
{
|
||||
if (jtr.Value.ToString() == "pair")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
MarketInfo.Pair = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "rate")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
MarketInfo.Rate = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "limit")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
MarketInfo.Limit = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "min")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
MarketInfo.Min = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "minerFee")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
MarketInfo.MinerFee = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return MarketInfo;
|
||||
}
|
||||
}
|
||||
}
|
65
src/ShapeShift/TradingPair.cs
Normal file
65
src/ShapeShift/TradingPair.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to verified currency pairs available for exchange.
|
||||
/// </summary>
|
||||
public class TradingPair
|
||||
{
|
||||
/// <summary>
|
||||
/// The Pair string used by ShapeShift.
|
||||
/// </summary>
|
||||
public string Pair { get; private set; }
|
||||
/// <summary>
|
||||
/// The Ticker of the currency to be converted.
|
||||
/// </summary>
|
||||
public string Ticker1 { get; private set; }
|
||||
/// <summary>
|
||||
/// The Ticker of the currency to convert to.
|
||||
/// </summary>
|
||||
public string Ticker2 { get; private set; }
|
||||
|
||||
private TradingPair() { }
|
||||
|
||||
/// <summary>
|
||||
/// Generates a list of all TradingPairs supported by ShapeShift.
|
||||
/// </summary>
|
||||
/// <returns>A List of TradingPairs.</returns>
|
||||
internal static async Task<List<TradingPair>> GetAllPairsAsync()
|
||||
{
|
||||
//Initialize an empty List of TradingPairs
|
||||
List<TradingPair> PairList = new List<TradingPair>();
|
||||
//Generate a List of all SupportedCoins
|
||||
List<SupportedCoin> CoinList = await SupportedCoin.GetCoinsAsync().ConfigureAwait(false);
|
||||
//Loop through all SupportedCoins
|
||||
foreach (SupportedCoin Coin1 in CoinList)
|
||||
{
|
||||
//Check if coin is available for Shifting
|
||||
if (Coin1.Status == CoinStatuses.Available)
|
||||
{
|
||||
//Loop through all SupportedCoins again for generating all TradingPairs
|
||||
foreach (SupportedCoin Coin2 in CoinList)
|
||||
{
|
||||
//Check if both coins are not the same and both coins are available to Shift
|
||||
if (Coin1 != Coin2 && Coin2.Status == CoinStatuses.Available)
|
||||
{
|
||||
//Create new TradingPair object and assign values
|
||||
TradingPair NewPair = new TradingPair();
|
||||
NewPair.Ticker1 = Coin1.Symbol;
|
||||
NewPair.Ticker2 = Coin2.Symbol;
|
||||
NewPair.Pair = string.Format("{0}_{1}", Coin1.Symbol, Coin2.Symbol);
|
||||
//Add new TradingPair object to List of TradingPairs
|
||||
PairList.Add(NewPair);
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
//Return complete TradingPair List
|
||||
return PairList;
|
||||
}
|
||||
}
|
||||
}
|
104
src/ShapeShift/TradingRate.cs
Normal file
104
src/ShapeShift/TradingRate.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ability to find exchange rates for coin pairs.
|
||||
/// </summary>
|
||||
public class TradingRate
|
||||
{
|
||||
/*url: shapeshift.io/rate/[pair]
|
||||
method: GET
|
||||
|
||||
[pair] is any valid coin pair such as btc_ltc or ltc_btc
|
||||
|
||||
Success Output:
|
||||
|
||||
{
|
||||
"pair" : "btc_ltc",
|
||||
"rate" : "70.1234"
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Coin pair.
|
||||
/// </summary>
|
||||
public string Pair { get; private set; }
|
||||
/// <summary>
|
||||
/// Exchange rate.
|
||||
/// </summary>
|
||||
public double Rate { get; private set; }
|
||||
|
||||
private TradingRate() { }
|
||||
|
||||
/// <summary>
|
||||
/// Finds exchange rate for specified coin pair.
|
||||
/// </summary>
|
||||
/// <param name="Pair">Coin pair to find rate for.</param>
|
||||
/// <returns>Exchange rate.</returns>
|
||||
internal static async Task<TradingRate> GetRateAsync(string Pair)
|
||||
{
|
||||
Uri uri = GetUri(Pair);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds exchange rate for specified coin pair.
|
||||
/// </summary>
|
||||
/// <param name="Ticker1">Ticker symbol for coin to exchange.</param>
|
||||
/// <param name="Ticker2">Ticker symbol for resulting coin.</param>
|
||||
/// <returns>Exchange rate.</returns>
|
||||
internal static async Task<TradingRate> GetRateAsync(string Ticker1, string Ticker2) =>
|
||||
await GetRateAsync(string.Format("{0}_{1}", Ticker1, Ticker2)).ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// Finds exchange rates for all valid coin pairs.
|
||||
/// </summary>
|
||||
/// <returns>List of exchange rates.</returns>
|
||||
internal static async Task<List<TradingRate>> GetAllRatesAsync()
|
||||
{
|
||||
List<TradingRate> RateList = new List<TradingRate>();
|
||||
List<TradingPair> PairList = await TradingPair.GetAllPairsAsync().ConfigureAwait(false);
|
||||
foreach (TradingPair tp in PairList)
|
||||
{
|
||||
TradingRate NewRate = await GetRateAsync(tp.Pair).ConfigureAwait(false);
|
||||
RateList.Add(NewRate);
|
||||
}
|
||||
return RateList;
|
||||
}
|
||||
|
||||
private static Uri GetUri(string Pair) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/rate/{0}", Pair));
|
||||
|
||||
private static async Task<TradingRate> ParseResponseAsync(string response)
|
||||
{
|
||||
TradingRate rate = new TradingRate();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value != null)
|
||||
{
|
||||
if (jtr.Value.ToString() == "pair")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
rate.Pair = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "rate")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
rate.Rate = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rate;
|
||||
}
|
||||
}
|
||||
}
|
217
src/ShapeShift/Tx.cs
Normal file
217
src/ShapeShift/Tx.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ability to view previous transactions by address or API key.
|
||||
/// </summary>
|
||||
public class Tx
|
||||
{
|
||||
/// <summary>
|
||||
/// Transaction ID of the input coin going into shapeshift.
|
||||
/// </summary>
|
||||
public string InputTxID { get; private set; }
|
||||
/// <summary>
|
||||
/// Address that the input coin was paid to for this shift.
|
||||
/// </summary>
|
||||
public string InputAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// Currency type of the input coin.
|
||||
/// </summary>
|
||||
public string InputCoin { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount of input coin that was paid in on this shift.
|
||||
/// </summary>
|
||||
public double InputAmount { get; private set; }
|
||||
/// <summary>
|
||||
/// Transaction ID of the output coin going out to user.
|
||||
/// </summary>
|
||||
public string OutputTxID { get; private set; }
|
||||
/// <summary>
|
||||
/// Address that the output coin was sent to for this shift.
|
||||
/// </summary>
|
||||
public string OutputAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// Currency type of the output coin.
|
||||
/// </summary>
|
||||
public string OutputCoin { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount of output coin that was paid out on this shift.
|
||||
/// </summary>
|
||||
public double OutputAmount { get; private set; }
|
||||
/// <summary>
|
||||
/// The effective rate the user got on this shift.
|
||||
/// </summary>
|
||||
public double ShiftRate { get; private set; }
|
||||
/// <summary>
|
||||
/// Status of the shift.
|
||||
/// </summary>
|
||||
public TxStatuses Status { get; private set; }
|
||||
|
||||
private Tx() { }
|
||||
|
||||
/*url: shapeshift.io/txbyapikey/[apiKey]
|
||||
method: GET
|
||||
|
||||
[apiKey] is the affiliate's PRIVATE api key.
|
||||
|
||||
[
|
||||
{
|
||||
inputTXID: [Transaction ID of the input coin going into shapeshift],
|
||||
inputAddress: [Address that the input coin was paid to for this shift],
|
||||
inputCurrency: [Currency type of the input coin],
|
||||
inputAmount: [Amount of input coin that was paid in on this shift],
|
||||
outputTXID: [Transaction ID of the output coin going out to user],
|
||||
outputAddress: [Address that the output coin was sent to for this shift],
|
||||
outputCurrency: [Currency type of the output coin],
|
||||
outputAmount: [Amount of output coin that was paid out on this shift],
|
||||
shiftRate: [The effective rate the user got on this shift.],
|
||||
status: [status of the shift]
|
||||
}
|
||||
(one listing per transaction returned)
|
||||
]
|
||||
|
||||
The status can be "received", "complete", "returned", "failed".
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Finds all transactions sent using the specified API key.
|
||||
/// </summary>
|
||||
/// <param name="APIKey">The affiliate's PRIVATE api key.</param>
|
||||
/// <returns>List of transactions.</returns>
|
||||
internal static async Task<List<Tx>> GetTransactionsByAPIKeyAsync(string APIKey)
|
||||
{
|
||||
Uri uri = GetKeyUri(APIKey);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetKeyUri(string APIKey) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/txbyapikey/{0}", APIKey));
|
||||
|
||||
/*url: shapeshift.io/txbyaddress/[address]/[apiKey]
|
||||
method: GET
|
||||
|
||||
[address] the address that output coin was sent to for the shift
|
||||
[apiKey] is the affiliate's PRIVATE api key.
|
||||
|
||||
Success Output:
|
||||
|
||||
[
|
||||
{
|
||||
inputTXID: [Transaction ID of the input coin going into shapeshift],
|
||||
inputAddress: [Address that the input coin was paid to for this shift],
|
||||
inputCurrency: [Currency type of the input coin],
|
||||
inputAmount: [Amount of input coin that was paid in on this shift],
|
||||
outputTXID: [Transaction ID of the output coin going out to user],
|
||||
outputAddress: [Address that the output coin was sent to for this shift],
|
||||
outputCurrency: [Currency type of the output coin],
|
||||
outputAmount: [Amount of output coin that was paid out on this shift],
|
||||
shiftRate: [The effective rate the user got on this shift.],
|
||||
status: [status of the shift]
|
||||
}
|
||||
(one listing per transaction returned)
|
||||
]
|
||||
|
||||
The status can be "received", "complete", "returned", "failed".
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Finds all transactions sent to specified address.
|
||||
/// </summary>
|
||||
/// <param name="Address">The address that output coin was sent to for the shift.</param>
|
||||
/// <param name="APIKey">The affiliate's PRIVATE api key.</param>
|
||||
/// <returns>List of transactions.</returns>
|
||||
internal static async Task<List<Tx>> GetTransactionsByAddressAsync(string Address, string APIKey)
|
||||
{
|
||||
Uri uri = GetAddressUri(Address, APIKey);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetAddressUri(string Address, string APIKey) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/txbyaddress/{0}/{1}", Address, APIKey));
|
||||
|
||||
private static async Task<List<Tx>> ParseResponseAsync(string response)
|
||||
{
|
||||
List<Tx> TxList = new List<Tx>();
|
||||
Tx NewTx = new Tx();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.TokenType.ToString() == "StartObject")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(NewTx.InputTxID))
|
||||
TxList.Add(NewTx);
|
||||
NewTx = new Tx();
|
||||
}
|
||||
else if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "inputTXID")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.InputTxID = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "inputAddress")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.InputAddress = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "inputCurrency")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.InputCoin = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "inputAmount")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.InputAmount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "outputTXID")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.OutputTxID = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "outputAddress")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.OutputAddress = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "outputCurrency")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.OutputCoin = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "outputAmount")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.OutputAmount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "shiftRate")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.ShiftRate = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "status")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
NewTx.Status =
|
||||
jtr.Value.ToString() == "received" ? TxStatuses.Received :
|
||||
jtr.Value.ToString() == "complete" ? TxStatuses.Complete :
|
||||
jtr.Value.ToString() == "returned" ? TxStatuses.Returned :
|
||||
jtr.Value.ToString() == "failed" ? TxStatuses.Failed : TxStatuses.NoDeposits;
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(NewTx.InputTxID))
|
||||
TxList.Add(NewTx);
|
||||
|
||||
return TxList;
|
||||
}
|
||||
}
|
||||
}
|
175
src/ShapeShift/TxStatus.cs
Normal file
175
src/ShapeShift/TxStatus.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Transaction Statuses.
|
||||
/// </summary>
|
||||
public enum TxStatuses { NoDeposits, Received, Returned, Complete, Failed }
|
||||
|
||||
/// <summary>
|
||||
/// Provides access to transaction status.
|
||||
/// </summary>
|
||||
public class TxStatus
|
||||
{
|
||||
/*url: shapeshift.io/txStat/[address]
|
||||
method: GET
|
||||
|
||||
[address] is the deposit address to look up.
|
||||
|
||||
Success Output: (various depending on status)
|
||||
|
||||
Status: No Deposits Received
|
||||
{
|
||||
status:"no_deposits",
|
||||
address:[address] //matches address submitted
|
||||
}
|
||||
|
||||
Status: Received (we see a new deposit but have not finished processing it)
|
||||
{
|
||||
status:"received",
|
||||
address:[address] //matches address submitted
|
||||
}
|
||||
|
||||
Status: Complete
|
||||
{
|
||||
status : "complete",
|
||||
address: [address],
|
||||
withdraw: [withdrawal address],
|
||||
incomingCoin: [amount deposited],
|
||||
incomingType: [coin type of deposit],
|
||||
outgoingCoin: [amount sent to withdrawal address],
|
||||
outgoingType: [coin type of withdrawal],
|
||||
transaction: [transaction id of coin sent to withdrawal address]
|
||||
}
|
||||
|
||||
Status: Failed
|
||||
{
|
||||
status : "failed",
|
||||
error: [Text describing failure]
|
||||
}
|
||||
|
||||
//Note: this can still get the normal style error returned. For example if request is made without an address.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Status of exchange.
|
||||
/// </summary>
|
||||
public TxStatuses Status { get; private set; }
|
||||
/// <summary>
|
||||
/// Deposit address coins (need to be) sent to.
|
||||
/// </summary>
|
||||
public string Address { get; private set; }
|
||||
/// <summary>
|
||||
/// Address to send coins after exchange.
|
||||
/// </summary>
|
||||
public string WithdrawalAddress { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount to send to deposit address.
|
||||
/// </summary>
|
||||
public double IncomingAmount { get; private set; }
|
||||
/// <summary>
|
||||
/// Currency type to send.
|
||||
/// </summary>
|
||||
public string IncomingCoin { get; private set; }
|
||||
/// <summary>
|
||||
/// Amount (to be) received from exchange.
|
||||
/// </summary>
|
||||
public double OutgoingAmount { get; private set; }
|
||||
/// <summary>
|
||||
/// Currency type to receive.
|
||||
/// </summary>
|
||||
public string OutgoingCoin { get; private set; }
|
||||
/// <summary>
|
||||
/// Transaction ID of coin sent to withdrawal address.
|
||||
/// </summary>
|
||||
public string TxID { get; private set; }
|
||||
/// <summary>
|
||||
/// Error thrown by status check, if any.
|
||||
/// </summary>
|
||||
public string Error { get; private set; }
|
||||
|
||||
private TxStatus() { }
|
||||
|
||||
/// <summary>
|
||||
/// Gets status of transaction (to be) deposited to supplied address.
|
||||
/// </summary>
|
||||
/// <param name="Address">Deposit address.</param>
|
||||
/// <returns>Transaction status.</returns>
|
||||
internal static async Task<TxStatus> GetStatusAsync(string Address)
|
||||
{
|
||||
Uri uri = GetUri(Address);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetUri(string address) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/txStat/{0}", address));
|
||||
|
||||
private static async Task<TxStatus> ParseResponseAsync(string response)
|
||||
{
|
||||
TxStatus status = new TxStatus();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "status")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.Status =
|
||||
jtr.Value.ToString() == "no_deposits" ? TxStatuses.NoDeposits :
|
||||
jtr.Value.ToString() == "received" ? TxStatuses.Received :
|
||||
jtr.Value.ToString() == "complete" ? TxStatuses.Complete :
|
||||
jtr.Value.ToString() == "failed" ? TxStatuses.Failed : TxStatuses.Returned;
|
||||
}
|
||||
else if (jtr.Value.ToString() == "address")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.Address = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "withdraw")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.WithdrawalAddress = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "incomingCoin")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.IncomingAmount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "incomingType")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.IncomingCoin = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "outgoingCoin")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.OutgoingAmount = Convert.ToDouble(jtr.Value.ToString());
|
||||
}
|
||||
else if (jtr.Value.ToString() == "outgoingType")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.OutgoingCoin = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "transaction")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.TxID = jtr.Value.ToString();
|
||||
}
|
||||
else if (jtr.Value.ToString() == "error")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
status.Error = jtr.Value.ToString();
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
82
src/ShapeShift/ValidateAddress.cs
Normal file
82
src/ShapeShift/ValidateAddress.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kalakoi.Crypto.ShapeShift
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ability to validate addresses for supported coins.
|
||||
/// </summary>
|
||||
public class ValidateAddress
|
||||
{
|
||||
/*url: shapeshift.io/validateAddress/[address]/[coinSymbol]
|
||||
method: GET
|
||||
|
||||
[address] the address that the user wishes to validate
|
||||
[coinSymbol] the currency symbol of the coin
|
||||
|
||||
Success Output:
|
||||
|
||||
|
||||
{
|
||||
isValid: [true / false],
|
||||
error: [(if isvalid is false, there will be an error message)]
|
||||
}
|
||||
|
||||
|
||||
isValid will either be true or false. If isvalid returns false, an error parameter will be present and will contain a descriptive error message.
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// True if address is valid.
|
||||
/// </summary>
|
||||
public bool IsValid { get; private set; }
|
||||
/// <summary>
|
||||
/// Error thrown by validation check.
|
||||
/// </summary>
|
||||
public string Error { get; private set; }
|
||||
|
||||
private ValidateAddress() { }
|
||||
|
||||
/// <summary>
|
||||
/// Validates address belongs to specified currency.
|
||||
/// </summary>
|
||||
/// <param name="Address">Address to check.</param>
|
||||
/// <param name="Symbol">Ticker symbol for currency to check.</param>
|
||||
/// <returns>Validation results.</returns>
|
||||
internal static async Task<ValidateAddress> ValidateAsync(string Address, string Symbol)
|
||||
{
|
||||
Uri uri = GetUri(Address, Symbol);
|
||||
string response = await RestServices.GetResponseAsync(uri).ConfigureAwait(false);
|
||||
return await ParseResponseAsync(response).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Uri GetUri(string Address, string Symbol) =>
|
||||
new Uri(string.Format(@"https://shapeshift.io/validateaddress/{0}/{1}", Address, Symbol));
|
||||
|
||||
private static async Task<ValidateAddress> ParseResponseAsync(string response)
|
||||
{
|
||||
ValidateAddress va = new ValidateAddress();
|
||||
using (JsonTextReader jtr = new JsonTextReader(new StringReader(response)))
|
||||
{
|
||||
while (await jtr.ReadAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (jtr.Value == null) continue;
|
||||
else if (jtr.Value.ToString() == "isValid")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
va.IsValid = jtr.Value.ToString() == "true";
|
||||
}
|
||||
else if (jtr.Value.ToString() == "error")
|
||||
{
|
||||
await jtr.ReadAsync().ConfigureAwait(false);
|
||||
va.Error = jtr.Value.ToString();
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
}
|
||||
return va;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user