module Bittrex.Internal where
import Control.Lens
import Data.Aeson
import Data.Aeson.Lens (key, nth)
import qualified Data.ByteString.Char8 as BC
import qualified Data.ByteString.Lazy as L
import Data.Char
import Data.Digest.Pure.SHA
import Data.List
import Data.List.Split (splitOn)
import Data.Monoid
import Data.Time.Clock.POSIX
import Network.Wreq
import Debug.Trace
import Bittrex.Types
defOpts :: APIOpts
defOpts = APIOpts PublicAPI [] "v1.1" mempty (APIKeys mempty mempty)
callAPI
:: FromJSON v
=> APIOpts
-> IO (Either ErrorMessage v)
callAPI APIOpts {..} = do
let APIKeys {..} = keys
nonce <- head . splitOn "." . show <$> getPOSIXTime
let addAuth = apiType `elem` [AccountAPI, MarketAPI]
authParams = concat
[ [ ("apikey", apiKey) | addAuth ]
, [ ("nonce", nonce) | addAuth ]
]
addHeader o =
if addAuth
then o & header "apisign" .~ [
BC.pack $ showDigest $
hmacSha512 (L.fromStrict (BC.pack secretKey)) $
L.fromStrict (BC.pack urlForHash)
]
else o
urlForHash = init $
mconcat [ url
, "?"
, go =<< do qParams ++ authParams
]
go (k,v) = k <> "=" <> v <> "&"
url = intercalate "/" [ "https://bittrex.com/api"
, version
, toLower <$> show apiType
, path
]
r <- getWith (addHeader defaults) urlForHash
let Just (Bool success) = r ^? responseBody . key "success"
Just result = r ^? responseBody . key "result"
Just msg = r ^? responseBody . key "message"
pure $ if success
then case fromJSON result of
Error s -> Left (DecodeFailure s result)
Success m -> Right m
else case fromJSON msg of
Success m -> Left (BittrexError m)
Error s -> Left (DecodeFailure s msg)