Requesting exchange rates for crypto pairs in code the easy way
Here is some simple code to get the current rates for crypto currency pairs using the CryptoCompare API.
It is written in C# but should be simple enough to translate to other languages.
Might be a fun challenge to translate to other languages. If you do this post in the comments or write a piece and link back to my post :)
Anyway on with the post. The CryptoCompare API is simple enough, here is the request.
https://min-api.cryptocompare.com/data/price?fsym=XXX&tsyms=YYY
So ETH to USD would be
https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD
The response is a simple JSON stream. A valid response being:
{"USD":315.98}
And an error being
{
"Response":"Error",
"Message":"Additional supply depots required. (Invalid Market)",
"Data":[],
"Type":99
}
So to request the rate for a pair I have this simple class:
public static class PriceRequester
{
private const string ErrorResponseKey = "Message";
public static async Task<Either<decimal, string>>
GetExchangeRate(string from, string to)
{
try
{
using (var client = new HttpClient())
{
var response = await client
.GetStringAsync(
$"https://min-api.cryptocompare.com/data/price?fsym={from}&tsyms={to}")
.ConfigureAwait(false);
return ResponseParser(from, to, response);
}
}
catch (Exception ex)
{
return $"Failed to get rate for {from} in {to}: {ex.Message}".ToLeft<decimal, string>();
}
}
public static Either<decimal, string>
ResponseParser(string from, string to, string walletResponse)
{
var parser = JsonObject.Parse(walletResponse);
if (parser.Keys.Contains(ErrorResponseKey))
{
return parser[ErrorResponseKey].GetString().ToLeft<decimal, string>();
}
return ((decimal)parser[to].GetNumber()).ToRight<decimal, string>();
}
}
So it performs an async request to the API, if it gets a response that is parsed and returned as a rate or an error using an Either Monad.
You call it as follows.
var ethValue = PriceRequester.GetExchangeRate("ETH", "USD").Result;
The Either Monad is stolen from Haskell, a bit out of scope for this article but I have included the code to be complete.
It is either a Right value, this is a success value, or a Left value which is what is left if not valid. That is Haskell people for you :)
public static class Either
{
public static Either<TRight, TLeft> ToRight<TRight, TLeft>(this TRight right)
=> new Either<TRight, TLeft>.RightInstance(right);
public static Either<TRight, TLeft> ToLeft<TRight, TLeft>(this TLeft left)
=> new Either<TRight, TLeft>.LeftInstance(left);
}
public abstract class Either<TRight, TLeft>
{
public abstract TRight Right { get; }
public abstract TLeft Left { get; }
public abstract bool IsRight { get; }
public abstract bool IsLeft { get; }
public abstract Either<TRightResult, TLeft>
Select<TRightResult>(Func<TRight, TRightResult> map);
public abstract Either<TRightResult, TLeft>
SelectMany<TRightResult>(Func<TRight, Either<TRightResult, TLeft>> map);
internal class RightInstance : Either<TRight, TLeft>
{
public RightInstance(TRight right)
{
Right = right;
}
public override TRight Right { get; }
public override TLeft Left
=> throw new InvalidOperationException("Either is not Right");
public override bool IsRight => true;
public override bool IsLeft => false;
public override Either<TRightResult, TLeft>
Select<TRightResult>(Func<TRight, TRightResult> map)
=> map(Right).ToRight<TRightResult, TLeft>();
public override Either<TRightResult, TLeft>
SelectMany<TRightResult>(Func<TRight, Either<TRightResult, TLeft>> map)
=> map(Right);
}
internal class LeftInstance : Either<TRight, TLeft>
{
public LeftInstance(TLeft left)
{
Left = left;
}
public override TRight Right
=> throw new InvalidOperationException("Either is not Right");
public override TLeft Left { get; }
public override bool IsRight => false;
public override bool IsLeft => true;
public override Either<TRightResult, TLeft>
Select<TRightResult>(Func<TRight, TRightResult> map)
=> Left.ToLeft<TRightResult, TLeft>();
public override Either<TRightResult, TLeft>
SelectMany<TRightResult>(Func<TRight, Either<TRightResult, TLeft>> map)
=> Left.ToLeft<TRightResult, TLeft>();
}
}
Hope you found this helpful. Leave comments or questions below.
Happy coding
Woz
When I played around with a bot, I used the tools for Python linked on the bittrex homepage. There's also a script on github to load the historic price charts.