coinbase-pro-0.8.0.0: src/lib/CoinbasePro/Types.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
module CoinbasePro.Types
( OrderId (..)
, ClientOrderId (..)
, Price (..)
, ProductId (..)
, Sequence
, UserId
, ProfileId
, Side (..)
, Size (..)
, Volume (..)
, TradeId (..)
, Funds
, OrderType (..)
, CreatedAt (..)
, Candle (..)
, CandleGranularity (..)
, TwentyFourHourStats (..)
, Currency (..)
, filterOrderFieldName
) where
import Data.Aeson (FromJSON, ToJSON, 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 Data.UUID (UUID, toText)
import qualified Data.Vector as V
import Servant.API
import Text.Printf (printf)
type UserId = Text
type ProfileId = Text
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 ClientOrderId = ClientOrderId { unClientOrderId :: UUID }
deriving (Eq, Ord, Show)
instance ToHttpApiData ClientOrderId where
toUrlPiece = ("client:" <>) . toText . unClientOrderId
deriveJSON defaultOptions
{ unwrapUnaryRecords = True
} ''ClientOrderId
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"