bitcoin-hs-0.0.1: Bitcoin/RPC/Call.hs
-- | wrappers around the RPC calls
{-# LANGUAGE PatternGuards #-}
module Bitcoin.RPC.Call where
--------------------------------------------------------------------------------
import Data.Word
import Text.JSON
import Text.JSON.Types
import Control.Monad.Reader
import System.Random
import Bitcoin.Misc.Unique
import Bitcoin.RPC.JSON
import Bitcoin.RPC.HTTP
--------------------------------------------------------------------------------
-- | Type of an RPC call (without arguments)
type Call a = ReaderT BitcoinURI IO (Either String a)
-- | Executes the "call monad"
runCalls :: BitcoinURI -> ReaderT BitcoinURI IO a -> IO a
runCalls uri action = runReaderT action uri
--------------------------------------------------------------------------------
-- | Creates a unique request id, using a combination of a counter and a random number.
newRequestId :: IO String
newRequestId = do
a <- randomRIO (1000000000,9999999999::Word64)
b <- newUnique
return (show a ++ ":" ++ show b)
--------------------------------------------------------------------------------
-- | Things which can be converted to an RPC call parameter list.
class ParamList l where
paramListJSON :: l -> [JSValue]
instance ParamList () where paramListJSON _ = []
instance JSON a => ParamList [a] where
paramListJSON xs = map showJSON xs
instance (JSON a, JSON b) => ParamList (a,b) where
paramListJSON (x,y) = [showJSON x, showJSON y]
instance (JSON a, JSON b, JSON c) => ParamList (a,b,c) where
paramListJSON (x,y,z) = [showJSON x, showJSON y, showJSON z]
instance (JSON a, JSON b, JSON c, JSON d) => ParamList (a,b,c,d) where
paramListJSON (x,y,z,w) = [showJSON x, showJSON y, showJSON z, showJSON w]
instance (JSON a, JSON b, JSON c, JSON d, JSON e) => ParamList (a,b,c,d,e) where
paramListJSON (x,y,z,w,u) = [showJSON x, showJSON y, showJSON z, showJSON w, showJSON u]
instance (JSON a, JSON b, JSON c, JSON d, JSON e, JSON f) => ParamList (a,b,c,d,e,f) where
paramListJSON (x,y,z,w,u,v) = [showJSON x, showJSON y, showJSON z, showJSON w, showJSON u, showJSON v]
--------------------------------------------------------------------------------
-- | Generic API call
makeCall :: ParamList l => String -> l -> (JSValue -> Maybe a) -> Call a
makeCall method params parseResponse = do
uri <- ask
lift $ do
reqid <- newRequestId
let pars = paramListJSON params
let req = Request method pars reqid :: Request JSValue
-- print req
eiresp <- rpcCall uri req
case eiresp of
Left err -> return (Left err)
Right (Response result mberror respid)
| respid /= reqid -> return (Left "response id does not match request id")
| Just err <- mberror -> return (Left "err")
| Just x <- parseResponse result -> return (Right x)
| otherwise -> return (Left "cannot parse response")
--------------------------------------------------------------------------------