1 {-# LANGUAGE FlexibleContexts #-}
2 module Cryptsy
.API
.Public
.MarketData
3 ( GMarketData
(..), MarketData
4 , extractMarketData
, extractJSONMarketData
5 , withComponents
, withMarket
7 , module Cryptsy
.API
.Public
8 , module Cryptsy
.API
.Public
.Market
9 -- |Re-exported from Data.Text
11 -- |Re-exported from Data.Aeson
12 , Value
, Object
, FromJSON
(..)
13 -- |Re-exported from Data.Aeson.Types
15 -- |Re-exported from Data.HashMap.Strict
21 import Data
.Aeson
( FromJSON
(..), Value
, Object
, withObject
)
22 import Data
.Aeson
.Types
(Parser
, Result
(..), parse
)
25 import Control
.Monad
(fail)
26 import Data
.Either (Either(..))
27 import Data
.Function
(($))
28 import Data
.Functor
(fmap, (<$>))
29 import Data
.List
((++))
30 import Data
.Maybe (maybe)
31 import Data
.String (String)
32 import Data
.Traversable
(mapM)
33 import Prelude
(Show(show))
36 import Control
.Monad
.Trans
.Either (left
, right
)
39 import Data
.Text
(Text
, pack
)
41 -- unordered-containers
42 import Data
.HashMap
.Strict
(HashMap
)
43 import qualified Data
.HashMap
.Strict
as HM
(lookup)
47 import Cryptsy
.API
.Public
(CryptsyNum
(..), CryptsyError
(..), PubCryptsy
)
48 import Cryptsy
.API
.Public
.Market
56 -- |general market data parameterized by types for prices, quantities,
57 -- date/time values, and totals (price * quantity)
58 newtype GMarketData p q dt t
=
59 MarketData
{ markets
:: HashMap Text
(GMarket p q dt t
) }
61 type MarketData
= GMarketData CryptsyNum CryptsyNum Text CryptsyNum
63 instance (FromJSON p
, FromJSON q
, FromJSON dt
, FromJSON t
) =>
64 FromJSON
(GMarketData p q dt t
)
66 parseJSON
= withObject
"markets" $ withComponents parseJSON
69 marketsStr
= "markets"
72 missingMsg
= "Missing '" ++ marketsStr
++ "' key."
74 -- |Key in JSON object for market data
76 marketsKey
= pack marketsStr
78 extractMarketDataEither
:: (Value
-> Parser
(GMarketData p q dt t
))
79 -> Value
-- ^ API return data
80 -> Either String (GMarketData p q dt t
)
81 extractMarketDataEither parseMarkets v
=
82 case parse parser v
of
86 parser
= withObject
"return" $ \o
->
87 maybe (fail missingMsg
) parseMarkets
$ HM
.lookup marketsKey o
89 extractMarketData
:: (Object
-> Parser
(GMarketData p q dt t
))
90 -> Value
-- ^ API return data
91 -> PubCryptsy
(GMarketData p q dt t
)
92 extractMarketData parseMarkets v
=
93 hoistFailParseReturn v
94 $ extractMarketDataEither
(withObject marketsStr parseMarkets
) v
96 extractJSONMarketData
:: FromJSON
(GMarketData p q dt t
)
97 => Value
-- ^ API return data
98 -> PubCryptsy
(GMarketData p q dt t
)
99 extractJSONMarketData v
=
100 hoistFailParseReturn v
$ extractMarketDataEither parseJSON v
102 hoistFailParseReturn
:: Value
-> Either String a
-> PubCryptsy a
103 hoistFailParseReturn ret
(Left err
) = left
$ FailParseReturn ret err
104 hoistFailParseReturn _
(Right m
) = right m
106 -- |Build parser for multiple markets from parser for single market.
107 withComponents
:: (Value
-> Parser
(GMarket p q dt t
)) -- ^ market parser
108 -> Object
-> Parser
(GMarketData p q dt t
)
109 withComponents parseMarket
= fmap MarketData
<$> mapM parseMarket
111 -- |Build parser for multiple markets from parser for single market object.
112 withMarket
:: (Object
-> Parser
(GMarket p q dt t
)) -- ^ market parser
113 -> Object
-> Parser
(GMarketData p q dt t
)
114 withMarket parseMarket
= withComponents
(withObject
"market" parseMarket
)