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 Call a = ReaderT BitcoinURI IO (Either String a)
runCalls :: BitcoinURI -> ReaderT BitcoinURI IO a -> IO a
runCalls uri action = runReaderT action uri
newRequestId :: IO String
newRequestId = do
a <- randomRIO (1000000000,9999999999::Word64)
b <- newUnique
return (show a ++ ":" ++ show b)
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]
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
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")