packages feed

bitx-bitcoin 0.5.0.0 → 0.5.0.1

raw patch · 10 files changed

+166/−97 lines, 10 filesdep ~basedep ~http-conduitPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, http-conduit

API changes (from Hackage documentation)

Files

README.md view
@@ -1,40 +1,40 @@-[![Build Status](https://travis-ci.org/tebello-thejane/bitx-haskell.svg?branch=master)](https://travis-ci.org/tebello-thejane/bitx-haskell)
-[![Hackage](https://budueba.com/hackage/bitx-bitcoin)](https://hackage.haskell.org/package/bitx-bitcoin)
-[![CC0 Public Domain](http://b.repl.ca/v1/CC0-Public_Domain-brightgreen.png)](http://creativecommons.org/publicdomain/zero/1.0/)
-
+[![Build Status](https://travis-ci.org/tebello-thejane/bitx-haskell.svg?branch=master)](https://travis-ci.org/tebello-thejane/bitx-haskell)+[![Hackage](https://budueba.com/hackage/bitx-bitcoin)](https://hackage.haskell.org/package/bitx-bitcoin)+[![CC0 Public Domain](http://b.repl.ca/v1/CC0-Public_Domain-brightgreen.png)](http://creativecommons.org/publicdomain/zero/1.0/)+ (Hopefully useful) Haskell bindings to the [BitX](https://bitx.co/) bitcoin exchange's [API](https://bitx.co/api).  As a minimal example, to get the current selling price (in South African Rand) of bitcoin on the-BitX exchange, do the following:
-
-```haskell
-{-# LANGUAGE DataKinds #-}
-
-import Control.Lens ((^.))
-import Network.Bitcoin.BitX (BitXAPIResponse(..), getTicker, CcyPair(..))
-import qualified Network.Bitcoin.BitX as BitX
-import Data.Text (unpack)
-import Network.HTTP.Types.Status (Status(..))
-import Network.HTTP.Conduit (responseStatus)
-
-main :: IO ()
-main = do
-  bitXResponse <- getTicker XBTZAR
-  case bitXResponse of
-    ValidResponse tic        -> print (tic ^. BitX.ask)
-    ErrorResponse err        ->
-        error $ "BitX error received: \"" ++ unpack (err ^. BitX.error) ++ "\""
-    ExceptionResponse ex     ->
-        error $ "Exception was thrown: \"" ++ show ex ++ "\""
-    UnparseableResponse resp ->
-        error $ "Bad HTTP response; HTTP status code was: \"" ++ (show . statusCode . responseStatus $ resp) ++ "\""
-```
-
+BitX exchange, do the following:++```haskell+{-# LANGUAGE DataKinds #-}++import Control.Lens ((^.))+import Network.Bitcoin.BitX (BitXAPIResponse(..), getTicker, CcyPair(..))+import qualified Network.Bitcoin.BitX as BitX+import Data.Text (unpack)+import Network.HTTP.Types.Status (Status(..))+import Network.HTTP.Conduit (responseStatus)++main :: IO ()+main = do+  bitXResponse <- getTicker XBTZAR+  case bitXResponse of+    ValidResponse tic        -> print (tic ^. BitX.ask)+    ErrorResponse err        ->+        error $ "BitX error received: \"" ++ unpack (err ^. BitX.error) ++ "\""+    ExceptionResponse ex     ->+        error $ "Exception was thrown: \"" ++ show ex ++ "\""+    UnparseableResponse resp ->+        error $ "Bad HTTP response; HTTP status code was: \"" ++ (show . statusCode . responseStatus $ resp) ++ "\""+```+ Note that the code snippet above depends on [http-types](https://hackage.haskell.org/package/http-types),-[http-conduit](https://hackage.haskell.org/package/http-conduit), [lens](https://hackage.haskell.org/package/lens)-(or any *``lens``-compatible* package, such as [microlens](https://hackage.haskell.org/package/microlens)),-and finally **bitx-bitcoin**.
-
+[text](https://hackage.haskell.org/package/text), [http-conduit](https://hackage.haskell.org/package/http-conduit),+[lens](https://hackage.haskell.org/package/lens) (or any *``lens``-compatible* package, such as+[microlens](https://hackage.haskell.org/package/microlens)), and finally **bitx-bitcoin**.+ This library is known to work on Windows, but if you wish to use it then you will have to do a bit more work due to the ``Network`` library not building on Windows out of the box. See-[this blog post by Neil Mitchell](http://neilmitchell.blogspot.com/2010/12/installing-haskell-network-library-on.html).
+[this blog post by Neil Mitchell](http://neilmitchell.blogspot.com/2010/12/installing-haskell-network-library-on.html).
bitx-bitcoin.cabal view
@@ -1,5 +1,5 @@ name:                bitx-bitcoin-version:             0.5.0.0+version:             0.5.0.1 synopsis:            A Haskell library for working with the BitX bitcoin exchange.  description:@@ -124,5 +124,20 @@   main-is:             Doctests.hs   build-depends:       base,                        doctest >= 0.8+  hs-source-dirs:      test+  default-language:    Haskell2010++--------------------------------------------------------------------------------++test-suite example+  type:                exitcode-stdio-1.0+  ghc-options:         -threaded+  main-is:             Example.hs+  build-depends:       base,+                       microlens,+                       bitx-bitcoin,+                       http-types,+                       http-conduit,+                       text   hs-source-dirs:      test   default-language:    Haskell2010
src/Network/Bitcoin/BitX/Internal.hs view
@@ -50,14 +50,14 @@         userID = Txt.encodeUtf8 (auth ^. Types.id)         userSecret = Txt.encodeUtf8 (auth ^. Types.secret) -simpleBitXGetAuth_ :: BitXAesRecordConvert recd aes => BitXAuth -> String -> IO (BitXAPIResponse recd)+simpleBitXGetAuth_ :: BitXAesRecordConvert recd => BitXAuth -> String -> IO (BitXAPIResponse recd) simpleBitXGetAuth_ auth verb = withSocketsDo $     rateLimit         (authConnect auth             . fromJust . NetCon.parseUrl $ (bitXAPIRoot ++ verb))         consumeResponseIO -simpleBitXPOSTAuth_ :: (BitXAesRecordConvert recd aes, POSTEncodeable inprec) => BitXAuth -> inprec+simpleBitXPOSTAuth_ :: (BitXAesRecordConvert recd, POSTEncodeable inprec) => BitXAuth -> inprec     -> String -> IO (BitXAPIResponse recd) simpleBitXPOSTAuth_ auth encrec verb = withSocketsDo $     rateLimit@@ -66,14 +66,14 @@             . fromJust . NetCon.parseUrl $ (bitXAPIRoot ++ verb))         consumeResponseIO -simpleBitXMETHAuth_ :: BitXAesRecordConvert recd aes => BitXAuth -> BS.ByteString+simpleBitXMETHAuth_ :: BitXAesRecordConvert recd => BitXAuth -> BS.ByteString     -> String -> IO (BitXAPIResponse recd) simpleBitXMETHAuth_ auth meth verb = withSocketsDo $     rateLimit         (authConnect auth (fromJust (NetCon.parseUrl (bitXAPIRoot ++ verb))) { method = meth })         consumeResponseIO -simpleBitXGet_ :: BitXAesRecordConvert recd aes => String -> IO (BitXAPIResponse recd)+simpleBitXGet_ :: BitXAesRecordConvert recd => String -> IO (BitXAPIResponse recd) simpleBitXGet_ verb = withSocketsDo $ do     manager <- globalManager     rateLimit@@ -81,7 +81,7 @@         consumeResponseIO  rateLimit :: IO (Either NetCon.HttpException c) -> (Either NetCon.HttpException c -> IO d) -> IO d-rateLimit act1 act2 = go 500000+rateLimit act1 act2 = go (500 * 000)     where         go del = do             resp <- act1@@ -95,14 +95,14 @@         maxLimit = 5 * 1000 * 1000 -- 5 seconds probably means something else is wrong...         incDelay = round . (* (1.5 :: Double)) . fromIntegral -consumeResponseIO :: BitXAesRecordConvert recd aes => Either NetCon.HttpException (NetCon.Response BL.ByteString)+consumeResponseIO :: BitXAesRecordConvert recd => Either NetCon.HttpException (NetCon.Response BL.ByteString)     -> IO (BitXAPIResponse recd) consumeResponseIO resp =     return $ case resp of         Left ex -> ExceptionResponse ex         Right k -> bitXErrorOrPayload k -bitXErrorOrPayload :: BitXAesRecordConvert recd aes => Response BL.ByteString -> BitXAPIResponse recd+bitXErrorOrPayload :: BitXAesRecordConvert recd => Response BL.ByteString -> BitXAPIResponse recd bitXErrorOrPayload resp = fromJust $         ErrorResponse . aesToRec <$> Aeson.decode body -- is it a BitX error?     <|> ValidResponse . aesToRec <$> Aeson.decode body
src/Network/Bitcoin/BitX/Types/Internal.hs view
@@ -1,5 +1,5 @@-{-# LANGUAGE QuasiQuotes, OverloadedStrings, TemplateHaskell, MultiParamTypeClasses,-    FunctionalDependencies, FlexibleInstances, DataKinds, CPP, RecordWildCards #-}+{-# LANGUAGE QuasiQuotes, OverloadedStrings, TemplateHaskell, TypeFamilies, FlexibleContexts,+    FlexibleInstances, DataKinds, CPP, RecordWildCards #-}  module Network.Bitcoin.BitX.Types.Internal     (@@ -41,9 +41,13 @@     . ( / 1000)     . (fromIntegral :: Integer -> Scientific) -class (FromJSON aes) => BitXAesRecordConvert recd aes | recd -> aes where-    aesToRec :: aes -> recd+--class (FromJSON aes) => BitXAesRecordConvert recd aes | recd -> aes where+--    aesToRec :: aes -> recd +class FromJSON (Aes recd) => BitXAesRecordConvert recd where+    type Aes recd+    aesToRec :: Aes recd -> recd+ class POSTEncodeable recd where     postEncode :: recd -> [(ByteString, ByteString)] @@ -65,7 +69,7 @@    parseJSON _          = mempty  instance FromJSON QuotedInt where-   parseJSON (String x) = return . QuotedInt . read . Txt.unpack $ x+   parseJSON (String x) = return . QuotedInt . (truncate :: Scientific -> Int) . read . Txt.unpack $ x    parseJSON (Number x) = return . QuotedInt . (truncate :: Scientific -> Int) . read . show $ x    parseJSON _          = mempty @@ -143,7 +147,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Ticker_) -instance BitXAesRecordConvert Types.Ticker Ticker_ where+instance BitXAesRecordConvert Types.Ticker where+    type Aes Types.Ticker = Ticker_     aesToRec (Ticker_ {..}) =         Types.Ticker {tickerTimestamp = tsmsToUTCTime ticker'timestamp,                   tickerBid = qiToInt ticker'bid,@@ -161,7 +166,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Tickers_) -instance BitXAesRecordConvert [Types.Ticker] Tickers_ where+instance BitXAesRecordConvert [Types.Ticker] where+    type Aes [Types.Ticker] = Tickers_     aesToRec (Tickers_ {..}) =         map aesToRec tickers'tickers @@ -174,7 +180,8 @@  $(AesTH.deriveJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"} ''BitXError_) -instance BitXAesRecordConvert Types.BitXError BitXError_ where+instance BitXAesRecordConvert Types.BitXError where+    type Aes Types.BitXError = BitXError_     aesToRec (BitXError_ {..}) =         Types.BitXError { bitXErrorError = bitXError'error, bitXErrorErrorCode = bitXError'error_code} @@ -187,7 +194,8 @@  $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"} ''Order_) -instance BitXAesRecordConvert Types.Order Order_ where+instance BitXAesRecordConvert Types.Order where+    type Aes Types.Order = Order_     aesToRec (Order_ {..}) =         Types.Order {orderVolume = qsToScientific order'volume,               orderPrice = qiToInt order'price}@@ -206,7 +214,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Orderbook_) -instance BitXAesRecordConvert Types.Orderbook Orderbook_ where+instance BitXAesRecordConvert Types.Orderbook where+    type Aes Types.Orderbook = Orderbook_     aesToRec (Orderbook_ {..}) =         Types.Orderbook {orderbookTimestamp = tsmsToUTCTime orderbook'timestamp,                   orderbookBids = map aesToRec orderbook'bids,@@ -223,7 +232,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Trade_) -instance BitXAesRecordConvert Types.Trade Trade_ where+instance BitXAesRecordConvert Types.Trade where+    type Aes Types.Trade = Trade_     aesToRec (Trade_ {..}) =         Types.Trade { tradeTimestamp = tsmsToUTCTime trade'timestamp,             tradeVolume = qsToScientific trade'volume,@@ -238,7 +248,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''PublicTrades_) -instance BitXAesRecordConvert [Types.Trade] PublicTrades_ where+instance BitXAesRecordConvert [Types.Trade] where+    type Aes [Types.Trade] = PublicTrades_     aesToRec (PublicTrades_ {..}) =         map aesToRec publicTrades'trades @@ -262,7 +273,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''PrivateOrder_) -instance BitXAesRecordConvert Types.PrivateOrder PrivateOrder_ where+instance BitXAesRecordConvert Types.PrivateOrder where+    type Aes Types.PrivateOrder = PrivateOrder_     aesToRec (PrivateOrder_ {..}) =         Types.PrivateOrder {privateOrderBase = qsToScientific privateOrder'base,                   privateOrderCounter = qsToScientific privateOrder'counter,@@ -286,7 +298,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''PrivateOrders_) -instance BitXAesRecordConvert [Types.PrivateOrder] PrivateOrders_ where+instance BitXAesRecordConvert [Types.PrivateOrder] where+    type Aes [Types.PrivateOrder] = PrivateOrders_     aesToRec (PrivateOrders_ {..}) =         map aesToRec privateOrders'orders @@ -308,7 +321,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''OrderIDRec_) -instance BitXAesRecordConvert Types.OrderID OrderIDRec_ where+instance BitXAesRecordConvert Types.OrderID where+    type Aes Types.OrderID = OrderIDRec_     aesToRec (OrderIDRec_ {..}) =         orderIDResponse'order_id @@ -325,7 +339,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''RequestSuccess_) -instance BitXAesRecordConvert Types.RequestSuccess RequestSuccess_ where+instance BitXAesRecordConvert Types.RequestSuccess where+    type Aes Types.RequestSuccess = RequestSuccess_     aesToRec (RequestSuccess_ {..}) =         requestSuccess'success @@ -350,7 +365,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''PrivateOrderWithTrades_) -instance BitXAesRecordConvert Types.PrivateOrderWithTrades PrivateOrderWithTrades_ where+instance BitXAesRecordConvert Types.PrivateOrderWithTrades where+    type Aes Types.PrivateOrderWithTrades = PrivateOrderWithTrades_     aesToRec (PrivateOrderWithTrades_ {..}) =         Types.PrivateOrderWithTrades {privateOrderWithTradesBase = qsToScientific privateOrderWithTrades'base,                   privateOrderWithTradesCounter = qsToScientific privateOrderWithTrades'counter,@@ -379,7 +395,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Balance_) -instance BitXAesRecordConvert Types.Balance Balance_ where+instance BitXAesRecordConvert Types.Balance where+    type Aes Types.Balance = Balance_     aesToRec (Balance_ {..}) =         Types.Balance {balanceId = balance'account_id,                   balanceAsset = balance'asset,@@ -396,7 +413,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Balances_) -instance BitXAesRecordConvert [Types.Balance] Balances_ where+instance BitXAesRecordConvert [Types.Balance] where+    type Aes [Types.Balance] = Balances_     aesToRec (Balances_ {..}) =         map aesToRec balances'balance @@ -412,7 +430,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''FundingAddress_) -instance BitXAesRecordConvert Types.FundingAddress FundingAddress_ where+instance BitXAesRecordConvert Types.FundingAddress where+    type Aes Types.FundingAddress = FundingAddress_     aesToRec (FundingAddress_ {..}) =         Types.FundingAddress {fundingAddressAsset = fundingAdress'asset,                   fundingAddressAddress = fundingAdress'address,@@ -435,7 +454,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''WithdrawalRequest_) -instance BitXAesRecordConvert Types.WithdrawalRequest WithdrawalRequest_ where+instance BitXAesRecordConvert Types.WithdrawalRequest where+    type Aes Types.WithdrawalRequest = WithdrawalRequest_     aesToRec (WithdrawalRequest_ {..}) =         Types.WithdrawalRequest {withdrawalRequestStatus = requestStatusParse withdrawalRequest'status,                   withdrawalRequestId = withdrawalRequest'id}@@ -449,7 +469,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''WithdrawalRequests_) -instance BitXAesRecordConvert [Types.WithdrawalRequest] WithdrawalRequests_ where+instance BitXAesRecordConvert [Types.WithdrawalRequest] where+    type Aes [Types.WithdrawalRequest] = WithdrawalRequests_     aesToRec (WithdrawalRequests_ {..}) =         map aesToRec withdrawalRequests'withdrawals @@ -498,7 +519,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''OrderQuote_) -instance BitXAesRecordConvert Types.OrderQuote OrderQuote_ where+instance BitXAesRecordConvert Types.OrderQuote where+    type Aes Types.OrderQuote = OrderQuote_     aesToRec (OrderQuote_ {..}) =         Types.OrderQuote {orderQuoteId = orderQuote'id,                   orderQuoteQuoteType = orderQuote'type,@@ -520,7 +542,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''BitXAuth_) -instance BitXAesRecordConvert Types.BitXAuth BitXAuth_ where+instance BitXAesRecordConvert Types.BitXAuth where+    type Aes Types.BitXAuth = BitXAuth_     aesToRec (BitXAuth_ {..}) =         Types.BitXAuth {bitXAuthId = bitXAuth'api_key_id,                   bitXAuthSecret = bitXAuth'api_key_secret}@@ -541,7 +564,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Transaction_) -instance BitXAesRecordConvert Types.Transaction Transaction_ where+instance BitXAesRecordConvert Types.Transaction where+    type Aes Types.Transaction = Transaction_     aesToRec (Transaction_ {..}) =         Types.Transaction {transactionRowIndex = transaction'row_index,                   transactionTimestamp = tsmsToUTCTime transaction'timestamp,@@ -561,7 +585,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Transactions_) -instance BitXAesRecordConvert [Types.Transaction] Transactions_ where+instance BitXAesRecordConvert [Types.Transaction] where+    type Aes [Types.Transaction] = Transactions_     aesToRec (Transactions_ {..}) =         map aesToRec transactions'transactions @@ -573,7 +598,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''PendingTransactions_) -instance BitXAesRecordConvert PendingTransactions__ PendingTransactions_ where+instance BitXAesRecordConvert PendingTransactions__ where+    type Aes PendingTransactions__ = PendingTransactions_     aesToRec (PendingTransactions_ {..}) =         PendingTransactions__ {pendingTransactions__transactions = map aesToRec transactions'pending} @@ -594,7 +620,8 @@ $(AesTH.deriveFromJSON AesTH.defaultOptions{AesTH.fieldLabelModifier = last . splitOn "'"}     ''Account_) -instance BitXAesRecordConvert Types.Account Account_ where+instance BitXAesRecordConvert Types.Account where+    type Aes Types.Account = Account_     aesToRec (Account_ {..}) =         Types.Account {accountId = account'id,                   accountName = account'name,
+ test/Example.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE DataKinds #-}++import Lens.Micro ((^.))+import Network.Bitcoin.BitX (BitXAPIResponse(..), getTicker, CcyPair(..))+import qualified Network.Bitcoin.BitX as BitX+import Data.Text (unpack)+import Network.HTTP.Types.Status (Status(..))+import Network.HTTP.Conduit (responseStatus)++main :: IO ()+main = do+  bitXResponse <- getTicker XBTZAR+  case bitXResponse of+    ValidResponse tic        -> putStrLn ("1 bitcoin will set you back ZAR" ++ show (tic ^. BitX.ask) ++ ".00.")+    ErrorResponse err        ->+        error $ "BitX error received: \"" ++ unpack (err ^. BitX.error) ++ "\""+    ExceptionResponse ex     ->+        error $ "Exception was thrown: \"" ++ show ex ++ "\""+    UnparseableResponse resp ->+        error $ "Bad HTTP response; HTTP status code was: \"" ++ (show . statusCode . responseStatus $ resp) ++ "\""+
test/Network/Bitcoin/BitX/Spec/Common.hs view
@@ -8,5 +8,5 @@ import Network.Bitcoin.BitX (BitXAesRecordConvert(..)) import Data.ByteString.Lazy (ByteString) -recordAesCheck :: (BitXAesRecordConvert recd aes, Show recd, Eq recd) => ByteString -> recd -> Expectation+recordAesCheck :: (BitXAesRecordConvert recd, Show recd, Eq recd) => ByteString -> recd -> Expectation recordAesCheck aesTxt recd = fmap aesToRec (decode aesTxt) `shouldBe` Just recd
test/Network/Bitcoin/BitX/Spec/Specs/AesonRecordSpec.hs view
@@ -19,8 +19,8 @@         BitXError {bitXErrorError = "oops", bitXErrorErrorCode = "ABadError"}     it "Ticker is parsed properly" $       recordAesCheck-        "{\"timestamp\":1431811395699,\"bid\":\"3083\",\"ask\":\"3115\",\-            \ \"last_trade\":\"3116\",\"rolling_24_hour_volume\":\"19.776608\",\"pair\":\"XBTZAR\"}"+        "{\"timestamp\":1431811395699,\"bid\":\"3083.00\",\"ask\":\"3115.00\",\+            \ \"last_trade\":\"3116.00\",\"rolling_24_hour_volume\":\"19.776608\",\"pair\":\"XBTZAR\"}"         Ticker {              tickerTimestamp = posixSecondsToUTCTime 1431811395.699,              tickerBid = 3083,@@ -30,18 +30,18 @@              tickerPair = XBTZAR}     it "Balance is parsed properly" $       recordAesCheck-        "{\"account_id\":\"314159\",\"asset\":\"ZAR\",\"balance\":\"2159.15\",\"reserved\":\"320\",\-            \ \"unconfirmed\":\"175\"}"+        "{\"account_id\":\"314159\",\"asset\":\"ZAR\",\"balance\":\"2159.15\",\"reserved\":\"320.43\",\+            \ \"unconfirmed\":\"175.34\"}"         Balance             {balanceId = "314159",              balanceAsset = ZAR,              balanceBalance = 2159.15,-             balanceReserved = 320,-             balanceUnconfirmed = 175}+             balanceReserved = 320.43,+             balanceUnconfirmed = 175.34}     it "Order is parsed properly" $       recordAesCheck-        "{\"volume\":\"314159\",\"price\":4321}"-        Order {orderVolume = 314159, orderPrice = 4321}+        "{\"volume\":\"314159.26\",\"price\":4321.00}"+        Order {orderVolume = 314159.26, orderPrice = 4321}     it "WithdrawalRequest is parsed properly" $       recordAesCheck         "{\"status\":\"PENDING\",\"id\":\"271828\"}"@@ -50,21 +50,21 @@             withdrawalRequestId = "271828" }     it "Tickers is parsed properly" $       recordAesCheck-        "{\"tickers\":[{\"timestamp\":1431811395699,\"bid\":\"3083\",\"ask\":\"3115\",\-            \ \"last_trade\":\"3116\",\"rolling_24_hour_volume\":\"19.776608\",\+        "{\"tickers\":[{\"timestamp\":1431811395699,\"bid\":\"3083.00\",\"ask\":\"3115.00\",\+            \ \"last_trade\":\"3116.00\",\"rolling_24_hour_volume\":\"19.776608\",\             \ \"pair\":\"XBTZAR\"}]}"         [tickerInner]     it "Orderbook is parsed properly" $       recordAesCheck-        "{\"timestamp\":1431811395699,\"bids\":[{\"volume\":\"654.98\",\"price\":\"3789\"}],\-            \ \"asks\":[{\"volume\":\"654.98\",\"price\":\"3789\"}]}"+        "{\"timestamp\":1431811395699,\"bids\":[{\"volume\":\"654.98\",\"price\":\"3789.00\"}],\+            \ \"asks\":[{\"volume\":\"654.98\",\"price\":\"3789.00\"}]}"         Orderbook             {orderbookTimestamp = posixSecondsToUTCTime 1431811395.699,              orderbookBids = [orderInner],              orderbookAsks = [orderInner]}     it "Trade is parsed properly" $       recordAesCheck-        "{\"timestamp\":1431811395699,\"volume\":\"6754.09\",\"price\":\"5327\"}"+        "{\"timestamp\":1431811395699,\"volume\":\"6754.09\",\"price\":\"5327.00\"}"         Trade             {tradeTimestamp = posixSecondsToUTCTime 1431811395.699,              tradeVolume = 6754.09,@@ -72,13 +72,13 @@     it "PublicTrades is parsed properly" $       recordAesCheck         "{\"trades\":[{\"timestamp\":1431811395699,\"volume\":\"6754.09\",\-            \ \"price\":\"5327\"}],\"currency\":\"ZAR\"}"+            \ \"price\":\"5327.00\"}],\"currency\":\"ZAR\"}"         [tradeInner]     it "PrivateOrder is parsed properly" $       recordAesCheck         "{\"base\":\"568.7\", \"counter\":3764.2,\"creation_timestamp\":478873467, \             \ \"expiration_timestamp\":8768834222, \"fee_base\":\"3687.3\", \"fee_counter\":12.9,\-            \ \"limit_price\":765,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\+            \ \"limit_price\":765.00,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\             \ \"state\":\"COMPLETE\",\"type\":\"BID\"}"         PrivateOrder             {privateOrderBase = 568.7,@@ -97,7 +97,7 @@       recordAesCheck         "{\"orders\":[{\"base\":\"568.7\", \"counter\":3764.2,\"creation_timestamp\":478873467, \             \ \"expiration_timestamp\":8768834222, \"fee_base\":\"3687.3\", \"fee_counter\":12.9,\-            \ \"limit_price\":765,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\+            \ \"limit_price\":765.00,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\             \ \"state\":\"COMPLETE\",\"type\":\"BID\"}]}"         [privateOrderInner]     it "OrderID is parsed properly" $@@ -106,7 +106,7 @@         ("57983" :: OrderID)     it "PublicTrades is parsed properly" $       recordAesCheck-        "{\"trades\":[{\"timestamp\":1431811395699,\"volume\":\"6754.09\",\"price\":\"5327\"}], \+        "{\"trades\":[{\"timestamp\":1431811395699,\"volume\":\"6754.09\",\"price\":\"5327.00\"}], \             \ \"currency\":\"ZAR\"}"          [tradeInner]     it "RequestSuccess is parsed properly" $@@ -117,9 +117,9 @@       recordAesCheck         "{\"base\":\"568.7\", \"counter\":3764.2,\"creation_timestamp\":478873467, \             \ \"expiration_timestamp\":8768834222, \"fee_base\":\"3687.3\", \"fee_counter\":12.9,\-            \ \"limit_price\":765,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\+            \ \"limit_price\":765.00,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\             \ \"state\":\"COMPLETE\",\"type\":\"BID\", \"trades\":[{\"timestamp\":1431811395699, \-            \ \"volume\":\"6754.09\",\"price\":\"5327\"}]}"+            \ \"volume\":\"6754.09\",\"price\":\"5327.00\"}]}"         PrivateOrderWithTrades             {privateOrderWithTradesBase = 568.7,              privateOrderWithTradesCounter = 3764.2,
test/Network/Bitcoin/BitX/Spec/Specs/JsonSpec.hs view
@@ -31,17 +31,17 @@         (Order 314159 4321)     it "QuotedInt is parsed when quoted" $       recordAesCheck-        "{\"volume\":0,\"price\":\"4321\"}"+        "{\"volume\":0,\"price\":\"4321.00\"}"         (Order 0 4321)     it "QuotedInt is parsed when not quoted" $       recordAesCheck-        "{\"volume\":0,\"price\":4321}"+        "{\"volume\":0,\"price\":4321.00}"         (Order 0 4321)     it "OrderType BUY is parsed properly" $       recordAesCheck         "{\"base\":\"568.7\", \"counter\":3764.2,\"creation_timestamp\":478873467, \             \\"expiration_timestamp\":8768834222, \"fee_base\":\"3687.3\", \"fee_counter\":12.9,\-            \\"limit_price\":765,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\+            \\"limit_price\":765.00,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\             \\"state\":\"COMPLETE\",\"type\":\"BUY\"}"         PrivateOrder             {privateOrderBase = 568.7,@@ -60,7 +60,7 @@       recordAesCheck         "{\"base\":\"568.7\", \"counter\":3764.2,\"creation_timestamp\":478873467, \             \\"expiration_timestamp\":8768834222, \"fee_base\":\"3687.3\", \"fee_counter\":12.9,\-            \\"limit_price\":765,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\+            \\"limit_price\":765.00,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\             \\"state\":\"COMPLETE\",\"type\":\"BID\"}"         PrivateOrder             {privateOrderBase = 568.7,@@ -79,7 +79,7 @@       recordAesCheck         "{\"base\":\"568.7\", \"counter\":3764.2,\"creation_timestamp\":478873467, \             \\"expiration_timestamp\":8768834222, \"fee_base\":\"3687.3\", \"fee_counter\":12.9,\-            \\"limit_price\":765,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\+            \\"limit_price\":765.00,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\             \\"state\":\"COMPLETE\",\"type\":\"ASK\"}"         PrivateOrder             {privateOrderBase = 568.7,@@ -98,7 +98,7 @@       recordAesCheck         "{\"base\":\"568.7\", \"counter\":3764.2,\"creation_timestamp\":478873467, \             \\"expiration_timestamp\":8768834222, \"fee_base\":\"3687.3\", \"fee_counter\":12.9,\-            \\"limit_price\":765,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\+            \\"limit_price\":765.00,\"limit_volume\":55.2,\"order_id\":\"83YG\",\"pair\":\"NADXBT\",\             \\"state\":\"COMPLETE\",\"type\":\"SELL\"}"         PrivateOrder             {privateOrderBase = 568.7,
test/Network/Bitcoin/BitX/Spec/Specs/PostSpec.hs view
@@ -17,7 +17,7 @@             {orderRequestPair = XBTZAR,              orderRequestOrderType = BID,              orderRequestVolume = 83.02,-             orderRequestPrice = 15 }+             orderRequestPrice = 15}       `shouldBe`         [("pair", "XBTZAR"),          ("type", "BID"),
test/Network/Bitcoin/BitX/Spec/Specs/PrivateSpec.hs view
@@ -19,6 +19,12 @@ --import Text.Show.Pretty (parseValue, valToStr) import Safe +-- To use this spec, create a file called "PRIVATE_API_KEY" with the private key and secret, respectively.+--  placed on their own lines.+--+-- To ensure that nothing funny happens, you can create an Api key without the Perm_W_Withdrawals+--  permission.+ spec :: Spec spec = describe "Private functionality test" $ do     mauth <- runIO privateAuth