Add files via upload

This commit is contained in:
Kalakoi
2017-12-15 12:57:02 -05:00
committed by GitHub
parent d792985047
commit eaf14093b5
15 changed files with 1894 additions and 0 deletions

View 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;
}
}
}

View 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;
}
}
}

View 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
View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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;
}
}
}

View 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
View 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
View 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;
}
}
}

View 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;
}
}
}