coinbase-pro-0.5.0.0: src/lib/CoinbasePro/Types.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module CoinbasePro.Types
( OrderId (..)
, Price (..)
, ProductId (..)
, Sequence
, Side (..)
, Size (..)
, TradeId (..)
, Funds
, OrderType (..)
, CreatedAt (..)
, Candle (..)
, CandleGranularity (..)
, TwentyFourHourStats (..)
, filterOrderFieldName
) where
import Data.Aeson (FromJSON, ToJSON, parseJSON, toJSON,
withArray, 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