Requesting exchange rates for crypto pairs in code the easy way
programming·@woz.software·
0.000 HBDRequesting 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](https://www.cryptocompare.com/) 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](https://www.cryptocompare.com/) 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