coinbase-pro-0.5.0.0: src/lib/CoinbasePro/Authenticated/Orders.hs
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
module CoinbasePro.Authenticated.Orders
( Status (..)
, Statuses (..)
, Order (..)
, STP (..)
, TimeInForce (..)
, PlaceOrderBody (..)
, statuses
) where
import Data.Aeson (FromJSON, ToJSON, parseJSON, withText)
import Data.Aeson.Casing (camelCase, snakeCase)
import Data.Aeson.TH (constructorTagModifier, defaultOptions,
deriveJSON, fieldLabelModifier,
omitNothingFields)
import Data.Set (Set, fromList)
import Data.Text (pack, toLower, unpack)
import Web.HttpApiData (ToHttpApiData (..))
import CoinbasePro.Types (CreatedAt, OrderId, OrderType, Price,
ProductId, Side, Size, filterOrderFieldName)
-- TODO: All is not a status
data Status = Open | Pending | Active | Done | All
deriving (Eq, Ord, Show)
instance ToHttpApiData Status where
toUrlPiece = toLower . pack . show
toQueryParam = toLower . pack . show
newtype Statuses = Statuses { unStatuses :: Set Status }
deriving (Eq, Show)
statuses :: [Status] -> Statuses
statuses = Statuses . fromList
data TimeInForce = GTC | GTT | IOC | FOK
deriving (Eq, Ord, Show)
instance ToHttpApiData TimeInForce where
toUrlPiece = toLower . pack . show
toQueryParam = toLower . pack . show
data STP = DC | CO | CN | CB
deriving (Eq, Ord, Show)
instance ToHttpApiData STP where
toUrlPiece = toLower . pack . show
toQueryParam = toLower . pack . show
deriveJSON defaultOptions {constructorTagModifier = camelCase} ''Status
deriveJSON defaultOptions ''TimeInForce
deriveJSON defaultOptions {constructorTagModifier = camelCase} ''STP
newtype FillFees = FillFees { unFillFees :: Double }
deriving (Eq, Ord, Show, ToJSON)
instance FromJSON FillFees where
parseJSON = withText "fill_fees" $ \t ->
return . FillFees . read $ unpack t
newtype ExecutedValue = ExecutedValue { unExecutedValue :: Double }
deriving (Eq, Ord, Show, ToJSON)
instance FromJSON ExecutedValue where
parseJSON = withText "executed_value" $ \t ->
return . ExecutedValue . read $ unpack t
-- TODO: This might need to be split up into different order types.
data Order = Order
{ id :: OrderId
, price :: Maybe Price
, size :: Maybe Size
, productId :: ProductId
, side :: Side
, stp :: Maybe STP
, orderType :: OrderType
, timeInForce :: Maybe TimeInForce
, postOnly :: Bool
, createdAt :: CreatedAt
, fillFees :: FillFees
, filledSize :: Size
, executedValue :: Maybe ExecutedValue
, status :: Status
, settled :: Bool
} deriving (Eq, Show)
deriveJSON defaultOptions {fieldLabelModifier = filterOrderFieldName . snakeCase} ''Order
data PlaceOrderBody = PlaceOrderBody
{ bProductId :: ProductId
, bSide :: Side
, bSize :: Size
, bPrice :: Price
, bPostOnly :: Bool
, bOrderType :: Maybe OrderType
, bStp :: Maybe STP
, bTif :: Maybe TimeInForce
} deriving (Eq, Show)
deriveJSON defaultOptions {fieldLabelModifier = snakeCase . drop 1, omitNothingFields = True} ''PlaceOrderBody