coinbase-pro-0.7.0.0: src/lib/CoinbasePro/Types.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module CoinbasePro.Types
( OrderId (..)
, Price (..)
, ProductId (..)
, Sequence
, Side (..)
, Size (..)
, Volume (..)
, TradeId (..)
, Funds
, OrderType (..)
, CreatedAt (..)
, Candle (..)
, CandleGranularity (..)
, TwentyFourHourStats (..)
, Currency (..)
, filterOrderFieldName
) where
import Data.Aeson (FromJSON, ToJSON, Value (Null),
parseJSON, toJSON, withArray,
withObject, withText, (.:), (.:?))
import qualified Data.Aeson as A
import Data.Aeson.Casing (camelCase, snakeCase)
import Data.Aeson.TH (constructorTagModifier, defaultOptions,
deriveJSON, fieldLabelModifier,
unwrapUnaryRecords)
import Data.Text (Text, pack, toLower, unpack)
import Data.Time.Clock (UTCTime)
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
import qualified Data.Vector as V
import Servant.API
import Text.Printf (printf)
type Sequence = Int
data Side = Buy | Sell
deriving (Eq, Ord, Show)
instance ToHttpApiData Side where
toUrlPiece = toLower . pack . show
toQueryParam = toLower . pack . show
deriveJSON defaultOptions
{ constructorTagModifier = camelCase
, fieldLabelModifier = snakeCase
} ''Side
newtype OrderId = OrderId { unOrderId :: Text }
deriving (Eq, Ord, Show, ToHttpApiData)
deriveJSON defaultOptions
{ fieldLabelModifier = snakeCase
, unwrapUnaryRecords = True
} ''OrderId
newtype ProductId = ProductId { unProductId :: Text }
deriving (Eq, Ord, Show, ToHttpApiData)
deriveJSON defaultOptions
{ fieldLabelModifier = snakeCase
, unwrapUnaryRecords = True
} ''ProductId
newtype Price = Price { unPrice :: Double }
deriving (Eq, Ord, Show, ToHttpApiData)
instance FromJSON Price where
parseJSON = withText "price" $ \t ->
return . Price . read $ unpack t
instance ToJSON Price where
toJSON (Price p) = A.String . pack $ printf "%.8f" p
newtype Size = Size { unSize :: Double }
deriving (Eq, Ord, Show, ToHttpApiData)
instance ToJSON Size where
toJSON (Size s) = A.String . pack $ printf "%.8f" s
instance FromJSON Size where
parseJSON = withText "size" $ \t ->
return . Size . read $ unpack t
newtype Volume = Volume { unVolume :: Double }
deriving (Eq, Ord, Show)
instance FromJSON Volume where
parseJSON = withText "volume" $ \t ->
return . Volume . read $ unpack t
instance ToJSON Volume where
toJSON (Volume v) = A.String . pack $ printf "%.8f" v
newtype TradeId = TradeId Int
deriving (Eq, Show)
deriveJSON defaultOptions { fieldLabelModifier = snakeCase } ''TradeId
newtype Funds = Funds { unFunds :: Double }
deriving (Eq, Ord, Show, ToHttpApiData)
instance ToJSON Funds where
toJSON (Funds s) = A.String . pack $ printf "%.16f" s
instance FromJSON Funds where
parseJSON = withText "size" $ \t ->
return . Funds . read $ unpack t
data OrderType = Limit | Market
deriving (Eq, Ord, Show)
instance ToHttpApiData OrderType where
toUrlPiece = toLower . pack . show
toQueryParam = toLower . pack . show
deriveJSON defaultOptions {constructorTagModifier = camelCase} ''OrderType
newtype CreatedAt = CreatedAt UTCTime
deriving (Eq, Show)
deriveJSON defaultOptions ''CreatedAt
filterOrderFieldName :: String -> String
filterOrderFieldName "order_type" = "type"
filterOrderFieldName s = s
data Candle = Candle
{ time :: UTCTime
, low :: Price
, high :: Price
, open :: Price
, close :: Price
, volume :: Double
} deriving (Eq, Show)
instance FromJSON Candle where
parseJSON = withArray "candle" $ \a -> do
let l = V.toList a
t <- posixSecondsToUTCTime <$> parseJSON (head l)
lw <- Price <$> parseJSON (l !! 1)
h <- Price <$> parseJSON (l !! 2)
o <- Price <$> parseJSON (l !! 3)
c <- Price <$> parseJSON (l !! 4)
v <- parseJSON $ l !! 5
return $ Candle t lw h o c v
data CandleGranularity = Minute | FiveMinutes | FifteenMinutes | Hour | SixHours | Day
deriving (Eq, Ord, Show)
instance ToHttpApiData CandleGranularity where
toUrlPiece Minute = "60"
toUrlPiece FiveMinutes = "300"
toUrlPiece FifteenMinutes = "900"
toUrlPiece Hour = "3600"
toUrlPiece SixHours = "21600"
toUrlPiece Day = "86400"
toQueryParam Minute = "60"
toQueryParam FiveMinutes = "300"
toQueryParam FifteenMinutes = "900"
toQueryParam Hour = "3600"
toQueryParam SixHours = "21600"
toQueryParam Day = "86400"
data TwentyFourHourStats = TwentyFourHourStats
{ open24 :: Price
, high24 :: Price
, low24 :: Price
, volume24 :: Volume
, last24 :: Price
, volume30 :: Volume
} deriving (Eq, Show)
deriveJSON defaultOptions { fieldLabelModifier = init . init } ''TwentyFourHourStats
data CurrencyDetails = CurrencyDetails
{ cdType :: Text
, symbol :: Maybe Text
, networkConfirmations :: Maybe Int
, sortOrder :: Maybe Int
, cryptoAddressLink :: Maybe Text
, pushPaymentMethods :: [Text]
, groupTypes :: Maybe [Text]
, maxPrecision :: Maybe Double
} deriving (Eq, Show)
instance FromJSON CurrencyDetails where
parseJSON = withObject "currency details" $ \o -> CurrencyDetails
<$> o .: "type"
<*> o .:? "symbol"
<*> o .:? "network_confirmations"
<*> o .:? "set_order"
<*> o .:? "crypto_address_link"
<*> o .: "push_payment_methods"
<*> o .:? "group_types"
<*> o .:? "max_precision"
data Currency = Currency
{ id :: Text
, name :: Text
, minSize :: Double
, status :: Text
, message :: Maybe Text
, details :: CurrencyDetails
} deriving (Eq, Show)
instance FromJSON Currency where
parseJSON = withObject "currency" $ \o -> Currency
<$> o .: "id"
<*> o .: "name"
<*> (read <$> o .: "min_size")
<*> o .: "status"
<*> o .:? "message"
<*> o .: "details"