module Mondo.API where
import GHC.TypeLits
import qualified Data.ByteString.Internal as BS
import Data.Proxy
import Data.Monoid
import Control.Monad.Trans
import Control.Monad.Trans.Except
import Control.Monad.Trans.Reader
import Network.HTTP.Client (Manager, newManager)
import Network.HTTP.Client.TLS
import Servant.API hiding (addHeader)
import Servant.Common.Req (Req(..), addHeader)
import Servant.Client
import Mondo.Types
data MondoAuth
instance HasClient api => HasClient (MondoAuth :> api) where
type Client (MondoAuth :> api) = String -> Client api
clientWithRoute Proxy req url mgr val =
clientWithRoute (Proxy :: Proxy api) (mondoAuthReq val req) url mgr
mondoAuthReq :: String -> Req -> Req
mondoAuthReq token = addHeader "Authorization" ("Bearer " <> token)
data MondoAccount
instance HasClient api => HasClient (MondoAccount :> api) where
type Client (MondoAccount :> api) = AccountID -> Client api
clientWithRoute Proxy req url mgr val =
clientWithRoute (Proxy :: Proxy api) (addHeader "account_id" val req) url mgr
type MondoAPI =
MondoAuth :> "accounts" :> Get '[JSON] AccountsResponse
:<|> MondoAuth :> "balance" :> QueryParam "account_id" AccountID :> Get '[JSON] Balance
:<|> MondoAuth :> "transactions" :> Capture "transaction_id" String :> Get '[JSON] TransactionResponse
:<|> MondoAuth :> "transactions" :> QueryParam "account_id" AccountID :> Get '[JSON] Transactions
mondoAPI :: Proxy MondoAPI
mondoAPI = Proxy
mondoURL :: BaseUrl
mondoURL = BaseUrl Https "api.getmondo.co.uk" 443 "/"
type Mondo = ReaderT String (ReaderT Manager (ExceptT ServantError IO))
withMondo :: String -> Mondo a -> IO (Either ServantError a)
withMondo tkn m = do
manager <- newManager tlsManagerSettings
runExceptT (runReaderT (runReaderT m tkn) manager)
credential :: Mondo String
credential = ask
manager :: Mondo Manager
manager = lift ask
api = client mondoAPI mondoURL
getAccounts :: Mondo AccountsResponse
getAccounts = do
mgr <- manager
tkn <- credential
let
fn = getNth (Proxy :: Proxy 0) $ api mgr
lift $ lift $ fn tkn
getBalance :: String -> Mondo Balance
getBalance acc = do
mgr <- manager
tkn <- credential
let
fn = getNth (Proxy :: Proxy 1) $ api mgr
lift $ lift $ fn tkn (Just acc)
getTransaction :: String -> Mondo Transaction
getTransaction tr = do
mgr <- manager
tkn <- credential
let
fn = getNth (Proxy :: Proxy 2) $ api mgr
lift $ lift (transaction <$> fn tkn tr)
getTransactions :: AccountID -> Mondo Transactions
getTransactions acc = do
mgr <- manager
tkn <- credential
let
fn = getNth (Proxy :: Proxy 3) $ api mgr
lift $ lift $ fn tkn (Just acc)
class GetNth (n :: Nat) a b | n a -> b where
getNth :: Proxy n -> a -> b
instance x ~ y => GetNth 0 x y where
getNth _ x = x
instance
GetNth 0 (x :<|> y) x where
getNth _ (x :<|> _) = x
instance
(GetNth (n1) x y) => GetNth n (a :<|> x) y where
getNth _ (_ :<|> x) = getNth (Proxy :: Proxy (n1)) x