From 35dac5360329ad69a352dfb0ec7e6645cac2fec2 Mon Sep 17 00:00:00 2001 From: Valentino Cerutti Date: Mon, 11 Dec 2023 18:30:21 -0300 Subject: [PATCH] Feat #43: Adds support for ohcl and pair endpoints --- maestro-sdk.cabal | 3 + src/Maestro/API/V1.hs | 2 + src/Maestro/API/V1/DefiMarkets.hs | 23 +++++++ src/Maestro/Client/V1.hs | 2 + src/Maestro/Client/V1/DefiMarkets.hs | 35 +++++++++++ src/Maestro/Types/V1.hs | 2 + src/Maestro/Types/V1/DefiMarkets.hs | 90 ++++++++++++++++++++++++++++ 7 files changed, 157 insertions(+) create mode 100644 src/Maestro/API/V1/DefiMarkets.hs create mode 100644 src/Maestro/Client/V1/DefiMarkets.hs create mode 100644 src/Maestro/Types/V1/DefiMarkets.hs diff --git a/maestro-sdk.cabal b/maestro-sdk.cabal index 609e30b..c70e25f 100644 --- a/maestro-sdk.cabal +++ b/maestro-sdk.cabal @@ -49,6 +49,7 @@ library Maestro.API.V1.Addresses Maestro.API.V1.Blocks Maestro.API.V1.Datum + Maestro.API.V1.DefiMarkets Maestro.API.V1.General Maestro.API.V1.Pools Maestro.API.V1.Transactions @@ -64,6 +65,7 @@ library Maestro.Client.V1.Addresses Maestro.Client.V1.Blocks Maestro.Client.V1.Datum + Maestro.Client.V1.DefiMarkets Maestro.Client.V1.General Maestro.Client.V1.Pools Maestro.Client.V1.Transactions @@ -76,6 +78,7 @@ library Maestro.Types.V1.Addresses Maestro.Types.V1.Blocks Maestro.Types.V1.Datum + Maestro.Types.V1.DefiMarkets Maestro.Types.V1.Common Maestro.Types.V1.Common.Pagination Maestro.Types.V1.Common.Timestamped diff --git a/src/Maestro/API/V1.hs b/src/Maestro/API/V1.hs index 1cd12ee..e543551 100644 --- a/src/Maestro/API/V1.hs +++ b/src/Maestro/API/V1.hs @@ -5,6 +5,7 @@ import Maestro.API.V1.Accounts import Maestro.API.V1.Addresses import Maestro.API.V1.Blocks import Maestro.API.V1.Datum +import Maestro.API.V1.DefiMarkets import Maestro.API.V1.General import Maestro.API.V1.Pools import Maestro.API.V1.Transactions @@ -18,6 +19,7 @@ data MaestroApiV1 route = MaestroApiV1 , addresses :: route :- "addresses" :> ToServantApi AddressesAPI , blocks :: route :- "blocks" :> ToServantApi BlocksAPI , datums :: route :- "datums" :> ToServantApi DatumAPI + , defiMarkets :: route :- "markets" :> "dexs" :> ToServantApi DefiMarketsAPI , pools :: route :- "pools" :> ToServantApi PoolsAPI , txManager :: route :- "txmanager" :> ToServantApi TxManagerAPI , transactions :: route :- "transactions" :> ToServantApi TransactionsAPI diff --git a/src/Maestro/API/V1/DefiMarkets.hs b/src/Maestro/API/V1/DefiMarkets.hs new file mode 100644 index 0000000..02f3bdc --- /dev/null +++ b/src/Maestro/API/V1/DefiMarkets.hs @@ -0,0 +1,23 @@ +module Maestro.API.V1.DefiMarkets where + +import Maestro.Types.V1 +import Servant.API +import Servant.API.Generic + +data DefiMarketsAPI route = DefiMarketsAPI + { + dexOHLC + :: route + :- "ohlc" + :> Capture "dex" Dex + :> Capture "pair" (TaggedText PairOfDexTokens) + :> QueryParam "resolution" Resolution + :> QueryParam "sort" Order + :> Get '[JSON] [OHLCCandleInfo] + + , dexPairs + :: route + :- Capture "dex" Dex + :> Get '[JSON] DexPairResponse + + } deriving (Generic) diff --git a/src/Maestro/Client/V1.hs b/src/Maestro/Client/V1.hs index af26184..11324a5 100644 --- a/src/Maestro/Client/V1.hs +++ b/src/Maestro/Client/V1.hs @@ -5,6 +5,7 @@ module Maestro.Client.V1 , module Maestro.Client.V1.Addresses , module Maestro.Client.V1.Blocks , module Maestro.Client.V1.Datum + , module Maestro.Client.V1.DefiMarkets , module Maestro.Client.V1.General , module Maestro.Client.V1.Pools , module Maestro.Client.V1.Transactions @@ -18,6 +19,7 @@ import Maestro.Client.V1.Addresses import Maestro.Client.V1.Blocks import Maestro.Client.V1.Core import Maestro.Client.V1.Datum +import Maestro.Client.V1.DefiMarkets import Maestro.Client.V1.General import Maestro.Client.V1.Pools import Maestro.Client.V1.Transactions diff --git a/src/Maestro/Client/V1/DefiMarkets.hs b/src/Maestro/Client/V1/DefiMarkets.hs new file mode 100644 index 0000000..af3179d --- /dev/null +++ b/src/Maestro/Client/V1/DefiMarkets.hs @@ -0,0 +1,35 @@ +-- | Module to query for /"DeFi Markets"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/category/defi-market-api). + +module Maestro.Client.V1.DefiMarkets ( + pricesFromDex, + pairsFromDex + ) where + +import Maestro.API.V1 +import Maestro.API.V1.DefiMarkets +import Maestro.Client.Env +import Maestro.Client.V1.Core +import Maestro.Types.Common (Order) +import Maestro.Types.V1 (Resolution, Dex, TaggedText, PairOfDexTokens,DexPairResponse, OHLCCandleInfo) +import Servant.API.Generic +import Servant.Client + +defiMarketsClient :: MaestroEnv 'V1 -> DefiMarketsAPI (AsClientT IO) +defiMarketsClient = fromServant . defiMarkets . apiV1Client + +-- | Returns a list of OHLC formatted candles from the desired dex +pricesFromDex :: + MaestroEnv 'V1 -> + Dex -> + TaggedText PairOfDexTokens -> + Maybe Resolution -> + Maybe Order -> + IO [OHLCCandleInfo] +pricesFromDex = dexOHLC . defiMarketsClient + +-- | Returns a the list of pairs supported by the dex +pairsFromDex :: + MaestroEnv 'V1 -> + Dex -> + IO DexPairResponse +pairsFromDex = dexPairs . defiMarketsClient diff --git a/src/Maestro/Types/V1.hs b/src/Maestro/Types/V1.hs index 41c3e25..95ffbdb 100644 --- a/src/Maestro/Types/V1.hs +++ b/src/Maestro/Types/V1.hs @@ -6,6 +6,7 @@ module Maestro.Types.V1 , module Maestro.Types.V1.Blocks , module Maestro.Types.V1.Common , module Maestro.Types.V1.Datum + , module Maestro.Types.V1.DefiMarkets , module Maestro.Types.V1.General , module Maestro.Types.V1.Pools , module Maestro.Types.V1.Transactions @@ -16,6 +17,7 @@ import Maestro.Types.V1.Addresses import Maestro.Types.V1.Blocks import Maestro.Types.V1.Common import Maestro.Types.V1.Datum +import Maestro.Types.V1.DefiMarkets import Maestro.Types.V1.General import Maestro.Types.V1.Pools import Maestro.Types.V1.Transactions diff --git a/src/Maestro/Types/V1/DefiMarkets.hs b/src/Maestro/Types/V1/DefiMarkets.hs new file mode 100644 index 0000000..5cb5e6d --- /dev/null +++ b/src/Maestro/Types/V1/DefiMarkets.hs @@ -0,0 +1,90 @@ +-- | Module to define types for /"DeFi Markets"/ category of endpoints defined at [docs.gomaestro.org](https://docs.gomaestro.org/category/defi-market-api). + +module Maestro.Types.V1.DefiMarkets ( + Dex(..), + PairOfDexTokens, + Resolution (..), + DexPairResponse(..), + DexPairInfo (..), + OHLCCandleInfo (..) + ) where + +import qualified Data.Text as T +import Deriving.Aeson +import Maestro.Types.V1.Common +import qualified Data.Aeson as Aeson +import Servant.API + +-- | Denotes which dex to use +data Dex = Minswap + deriving stock (Eq, Ord, Generic) + +instance Show Dex where + show Minswap = "minswap" + +instance ToHttpApiData Dex where + toQueryParam = T.pack . show + +-- | Because there is only one dex at the moment, the derivation returns "[]". This can be removed once support for a new dex is added. +instance FromJSON Dex where + parseJSON (Aeson.String "minswap") = return Minswap + parseJSON _ = fail "Expecting oneof [minswap]" + +-- | Token Pair that is queried +type PairOfDexTokens = "Token pair to look for. Format: XXX-YYY" + +-- | Time resolution for OHLC Candles +data Resolution = Res1m | Res5m | Res15m | Res30m | Res1h | Res4h | Res1d | Res1w | Res1mo + deriving stock (Eq, Ord, Generic) + deriving (FromJSON, ToJSON) via CustomJSON '[ConstructorTagModifier '[StripPrefix "Res"]] Resolution + +instance Show Resolution where + show Res1m = "1m" + show Res5m = "5m" + show Res15m = "15m" + show Res30m = "30m" + show Res1h = "1h" + show Res4h = "4h" + show Res1d = "1d" + show Res1w = "1w" + show Res1mo = "1mo" + +instance ToHttpApiData Resolution where + toQueryParam = T.pack . show + +data DexPairInfo = DexPairInfo + { dexPairInfoCoinAAssetName :: TokenName + , dexPairInfoCoinAPolicy :: PolicyId + , dexPairInfoCoinBAssetName :: TokenName + , dexPairInfoCoinBPolicy :: PolicyId + , dexPairInfoPair :: String +} + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "dexPairInfo", CamelToSnake]] DexPairInfo + +data DexPairResponse = DexPairResponse + { dexPairResponseDex :: Dex + , dexPairResponsePairs :: [DexPairInfo] + } + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "dexPairResponse", LowerFirst]] DexPairResponse + +-- | Candle data according to the [OHLC format](https://en.wikipedia.org/wiki/Open-high-low-close_chart) +data OHLCCandleInfo = OHLCCandleInfo + { ohlcCandleInfoCoinAClose :: Double + , ohlcCandleInfoCoinAHigh :: Double + , ohlcCandleInfoCoinALow :: Double + , ohlcCandleInfoCoinAOpen :: Double + , ohlcCandleInfoCoinAVolume :: Double + , ohlcCandleInfoCoinBClose :: Double + , ohlcCandleInfoCoinBHigh :: Double + , ohlcCandleInfoCoinBLow :: Double + , ohlcCandleInfoCoinBOpen :: Double + , ohlcCandleInfoCoinBVolume :: Double + , ohlcCandleInfoCount :: Integer + } + deriving stock (Show, Eq, Ord, Generic) + deriving (FromJSON) + via CustomJSON '[FieldLabelModifier '[StripPrefix "ohlcCandleInfo", CamelToSnake]] OHLCCandleInfo