{-# LANGUAGE UndecidableInstances #-}
module Tendermint.Utils.QueryClient.Class where
import Control.Lens ((^.))
import Control.Monad.Reader (ReaderT)
import qualified Data.ByteArray.Base64String as Base64
import qualified Data.ByteArray.HexString as Hex
import Data.ByteString (ByteString)
import Data.Kind (Type)
import Data.Proxy
import Data.String.Conversions (cs)
import Data.Text (Text, intercalate)
import Data.Word (Word64)
import GHC.TypeLits (KnownSymbol, symbolVal)
import Network.ABCI.Types.Messages.FieldTypes (WrappedVal (..))
import qualified Network.ABCI.Types.Messages.Request as Req
import qualified Network.ABCI.Types.Messages.Response as Resp
import qualified Network.Tendermint.Client as RPC
import Servant.API
import Servant.API.Modifiers
import Tendermint.SDK.BaseApp.Errors (queryAppError)
import Tendermint.SDK.BaseApp.Query.Store (StoreLeaf)
import Tendermint.SDK.BaseApp.Query.Types (EmptyQueryServer, Leaf,
QA, QueryArgs (..),
QueryData (..),
QueryResult (..))
import qualified Tendermint.SDK.BaseApp.Store.Array as A
import qualified Tendermint.SDK.BaseApp.Store.Map as M
import qualified Tendermint.SDK.BaseApp.Store.Var as V
import Tendermint.SDK.Codec (HasCodec (decode))
import Tendermint.Utils.QueryClient.Types
class Monad m => RunQueryClient m where
runQuery :: Req.Query -> m Resp.Query
instance RunQueryClient (ReaderT RPC.Config IO) where
runQuery :: Query -> ReaderT Config IO Query
runQuery Req.Query{..} =
let rpcQ :: RequestABCIQuery
rpcQ = RequestABCIQuery :: Maybe Text
-> HexString
-> Maybe (WrappedVal Int64)
-> Bool
-> RequestABCIQuery
RPC.RequestABCIQuery
{ requestABCIQueryPath :: Maybe Text
RPC.requestABCIQueryPath = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
queryPath
, requestABCIQueryData :: HexString
RPC.requestABCIQueryData = ByteArrayAccess ByteString => ByteString -> HexString
forall ba. ByteArrayAccess ba => ba -> HexString
Hex.fromBytes @ByteString (ByteString -> HexString)
-> (Base64String -> ByteString) -> Base64String -> HexString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Base64String -> ByteString
forall ba. ByteArray ba => Base64String -> ba
Base64.toBytes (Base64String -> HexString) -> Base64String -> HexString
forall a b. (a -> b) -> a -> b
$ Base64String
queryData
, requestABCIQueryHeight :: Maybe (WrappedVal Int64)
RPC.requestABCIQueryHeight = WrappedVal Int64 -> Maybe (WrappedVal Int64)
forall a. a -> Maybe a
Just (WrappedVal Int64 -> Maybe (WrappedVal Int64))
-> WrappedVal Int64 -> Maybe (WrappedVal Int64)
forall a b. (a -> b) -> a -> b
$ WrappedVal Int64
queryHeight
, requestABCIQueryProve :: Bool
RPC.requestABCIQueryProve = Bool
queryProve
}
in ResultABCIQuery -> Query
RPC.resultABCIQueryResponse (ResultABCIQuery -> Query)
-> ReaderT Config IO ResultABCIQuery -> ReaderT Config IO Query
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RequestABCIQuery -> ReaderT Config IO ResultABCIQuery
RPC.abciQuery RequestABCIQuery
rpcQ
type QueryStringList = [(Text, Text)]
class HasQueryClient m layout where
type ClientQ (m :: Type -> Type) layout :: Type
genClientQ :: Proxy m -> Proxy layout -> (Req.Query, QueryStringList) -> ClientQ m layout
instance (HasQueryClient m a, HasQueryClient m b) => HasQueryClient m (a :<|> b) where
type ClientQ m (a :<|> b) = ClientQ m a :<|> ClientQ m b
genClientQ :: Proxy m
-> Proxy (a :<|> b)
-> (Query, QueryStringList)
-> ClientQ m (a :<|> b)
genClientQ pm :: Proxy m
pm _ (q :: Query
q,qs :: QueryStringList
qs) = Proxy m -> Proxy a -> (Query, QueryStringList) -> ClientQ m a
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy a
forall k (t :: k). Proxy t
Proxy @a) (Query
q,QueryStringList
qs) ClientQ m a -> ClientQ m b -> ClientQ m a :<|> ClientQ m b
forall a b. a -> b -> a :<|> b
:<|> Proxy m -> Proxy b -> (Query, QueryStringList) -> ClientQ m b
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy b
forall k (t :: k). Proxy t
Proxy @b) (Query
q,QueryStringList
qs)
instance (KnownSymbol path, HasQueryClient m a) => HasQueryClient m (path :> a) where
type ClientQ m (path :> a) = ClientQ m a
genClientQ :: Proxy m
-> Proxy (path :> a)
-> (Query, QueryStringList)
-> ClientQ m (path :> a)
genClientQ pm :: Proxy m
pm _ (q :: Query
q,qs :: QueryStringList
qs) = Proxy m -> Proxy a -> (Query, QueryStringList) -> ClientQ m a
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy a
forall k (t :: k). Proxy t
Proxy @a)
(Query
q {queryPath :: Text
Req.queryPath = Query -> Text
Req.queryPath Query
q Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
forall a b. ConvertibleStrings a b => a -> b
cs (Proxy path -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy path
forall k (t :: k). Proxy t
Proxy @path))}, QueryStringList
qs)
appendToQueryString
:: Text
-> Maybe Text
-> QueryStringList
-> QueryStringList
appendToQueryString :: Text -> Maybe Text -> QueryStringList -> QueryStringList
appendToQueryString pname :: Text
pname pvalue :: Maybe Text
pvalue qs :: QueryStringList
qs =
QueryStringList
-> (Text -> QueryStringList) -> Maybe Text -> QueryStringList
forall b a. b -> (a -> b) -> Maybe a -> b
maybe QueryStringList
qs (\v :: Text
v -> (Text
pname, Text
v) (Text, Text) -> QueryStringList -> QueryStringList
forall a. a -> [a] -> [a]
: QueryStringList
qs) Maybe Text
pvalue
instance (KnownSymbol sym, ToHttpApiData a, HasQueryClient m api, SBoolI (FoldRequired mods))
=> HasQueryClient m (QueryParam' mods sym a :> api) where
type ClientQ m (QueryParam' mods sym a :> api) = RequiredArgument mods a -> ClientQ m api
genClientQ :: Proxy m
-> Proxy (QueryParam' mods sym a :> api)
-> (Query, QueryStringList)
-> ClientQ m (QueryParam' mods sym a :> api)
genClientQ pm :: Proxy m
pm Proxy (q :: Query
q,qs :: QueryStringList
qs) mparam :: If (FoldRequired mods) a (Maybe a)
mparam =
Proxy m -> Proxy api -> (Query, QueryStringList) -> ClientQ m api
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy api
forall k (t :: k). Proxy t
Proxy :: Proxy api) ((Query, QueryStringList) -> ClientQ m api)
-> (Query, QueryStringList) -> ClientQ m api
forall a b. (a -> b) -> a -> b
$ Proxy mods
-> (a -> (Query, QueryStringList))
-> (Maybe a -> (Query, QueryStringList))
-> If (FoldRequired mods) a (Maybe a)
-> (Query, QueryStringList)
forall (mods :: [*]) a r.
SBoolI (FoldRequired mods) =>
Proxy mods
-> (a -> r) -> (Maybe a -> r) -> RequiredArgument mods a -> r
foldRequiredArgument
(Proxy mods
forall k (t :: k). Proxy t
Proxy :: Proxy mods) a -> (Query, QueryStringList)
add ((Query, QueryStringList)
-> (a -> (Query, QueryStringList))
-> Maybe a
-> (Query, QueryStringList)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Query
q,QueryStringList
qs) a -> (Query, QueryStringList)
add) If (FoldRequired mods) a (Maybe a)
mparam
where
add :: a -> (Req.Query, QueryStringList)
add :: a -> (Query, QueryStringList)
add param :: a
param = (Query
q, Text -> Maybe Text -> QueryStringList -> QueryStringList
appendToQueryString Text
pname (Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ a -> Text
forall a. ToHttpApiData a => a -> Text
toQueryParam a
param) QueryStringList
qs)
pname :: Text
pname :: Text
pname = String -> Text
forall a b. ConvertibleStrings a b => a -> b
cs (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Proxy sym -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy sym
forall k (t :: k). Proxy t
Proxy :: Proxy sym)
instance (QueryData k, HasQueryClient m a) => HasQueryClient m (QA k :> a) where
type ClientQ m (QA k :> a) = QueryArgs k -> ClientQ m a
genClientQ :: Proxy m
-> Proxy (QA k :> a)
-> (Query, QueryStringList)
-> ClientQ m (QA k :> a)
genClientQ pm :: Proxy m
pm _ (q :: Query
q,qs :: QueryStringList
qs) QueryArgs{..} = Proxy m -> Proxy a -> (Query, QueryStringList) -> ClientQ m a
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy a
forall k (t :: k). Proxy t
Proxy @a)
(Query
q { queryData :: Base64String
Req.queryData = k -> Base64String
forall a. QueryData a => a -> Base64String
toQueryData k
queryArgsData
, queryHeight :: WrappedVal Int64
Req.queryHeight = Int64 -> WrappedVal Int64
forall a. a -> WrappedVal a
WrappedVal Int64
queryArgsHeight
, queryProve :: Bool
Req.queryProve = Bool
queryArgsProve
}, QueryStringList
qs)
instance (ToHttpApiData a, HasQueryClient m api) => HasQueryClient m (Capture' mods capture a :> api) where
type ClientQ m (Capture' mods capture a :> api) = a -> ClientQ m api
genClientQ :: Proxy m
-> Proxy (Capture' mods capture a :> api)
-> (Query, QueryStringList)
-> ClientQ m (Capture' mods capture a :> api)
genClientQ pm :: Proxy m
pm _ (q :: Query
q,qs :: QueryStringList
qs) val :: a
val =
let p :: Text
p = a -> Text
forall a. ToHttpApiData a => a -> Text
toUrlPiece a
val
q' :: Query
q' = Query
q { queryPath :: Text
Req.queryPath = Query -> Text
Req.queryPath Query
q Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
p }
in Proxy m -> Proxy api -> (Query, QueryStringList) -> ClientQ m api
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy api
forall k (t :: k). Proxy t
Proxy :: Proxy api) (Query
q', QueryStringList
qs)
addQueryParamsToPath
:: QueryStringList
-> Text
-> Text
addQueryParamsToPath :: QueryStringList -> Text -> Text
addQueryParamsToPath qs :: QueryStringList
qs path :: Text
path =
let qParams :: Text
qParams = Text -> [Text] -> Text
intercalate "&" ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ ((Text, Text) -> Text) -> QueryStringList -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (\(n :: Text
n,v :: Text
v) -> Text
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "=" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
v) QueryStringList
qs
in case QueryStringList
qs of
[] -> Text
path
_ -> Text
path Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> "?" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
qParams
instance (HasCodec a, RunQueryClient m) => HasQueryClient m (Leaf a) where
type ClientQ m (Leaf a) = m (QueryClientResponse a)
genClientQ :: Proxy m
-> Proxy (Leaf a) -> (Query, QueryStringList) -> ClientQ m (Leaf a)
genClientQ _ _ = (Query, QueryStringList) -> ClientQ m (Leaf a)
forall a (m :: * -> *).
(HasCodec a, RunQueryClient m) =>
(Query, QueryStringList) -> m (QueryClientResponse a)
leafGenClient
leafGenClient
:: HasCodec a
=> RunQueryClient m
=> (Req.Query, QueryStringList)
-> m (QueryClientResponse a)
leafGenClient :: (Query, QueryStringList) -> m (QueryClientResponse a)
leafGenClient (q :: Query
q,qs :: QueryStringList
qs) = do
let reqPath :: Text
reqPath = QueryStringList -> Text -> Text
addQueryParamsToPath QueryStringList
qs (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Query -> Text
Req.queryPath Query
q
r :: Query
r@Resp.Query{..} <- Query -> m Query
forall (m :: * -> *). RunQueryClient m => Query -> m Query
runQuery Query
q { queryPath :: Text
Req.queryPath = Text
reqPath }
QueryClientResponse a -> m (QueryClientResponse a)
forall (m :: * -> *) a. Monad m => a -> m a
return (QueryClientResponse a -> m (QueryClientResponse a))
-> QueryClientResponse a -> m (QueryClientResponse a)
forall a b. (a -> b) -> a -> b
$ case Word32
queryCode of
0 -> case ByteString -> Either Text a
forall a. HasCodec a => ByteString -> Either Text a
decode (ByteString -> Either Text a) -> ByteString -> Either Text a
forall a b. (a -> b) -> a -> b
$ Base64String -> ByteString
forall ba. ByteArray ba => Base64String -> ba
Base64.toBytes Base64String
queryValue of
Left err :: Text
err -> String -> QueryClientResponse a
forall a. HasCallStack => String -> a
error (String -> QueryClientResponse a)
-> String -> QueryClientResponse a
forall a b. (a -> b) -> a -> b
$ "Impossible parse error: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a b. ConvertibleStrings a b => a -> b
cs Text
err
Right a :: a
a -> QueryResult a -> QueryClientResponse a
forall a. QueryResult a -> QueryClientResponse a
QueryResponse (QueryResult a -> QueryClientResponse a)
-> QueryResult a -> QueryClientResponse a
forall a b. (a -> b) -> a -> b
$ QueryResult :: forall a.
a -> Int64 -> Base64String -> Maybe Proof -> Int64 -> QueryResult a
QueryResult
{ queryResultData :: a
queryResultData = a
a
, queryResultIndex :: Int64
queryResultIndex = WrappedVal Int64 -> Int64
forall a. WrappedVal a -> a
unWrappedVal WrappedVal Int64
queryIndex
, queryResultHeight :: Int64
queryResultHeight = WrappedVal Int64 -> Int64
forall a. WrappedVal a -> a
unWrappedVal WrappedVal Int64
queryHeight
, queryResultProof :: Maybe Proof
queryResultProof = Maybe Proof
queryProof
, queryResultKey :: Base64String
queryResultKey = Base64String
queryKey
}
_ -> AppError -> QueryClientResponse a
forall a. AppError -> QueryClientResponse a
QueryError (AppError -> QueryClientResponse a)
-> AppError -> QueryClientResponse a
forall a b. (a -> b) -> a -> b
$ Query
r Query -> Getting AppError Query AppError -> AppError
forall s a. s -> Getting a s a -> a
^. Getting AppError Query AppError
Lens' Query AppError
queryAppError
instance (HasCodec a, RunQueryClient m) => HasQueryClient m (StoreLeaf (V.Var a)) where
type ClientQ m (StoreLeaf (V.Var a)) = ClientQ m (QA () :> Leaf a)
genClientQ :: Proxy m
-> Proxy (StoreLeaf (Var a))
-> (Query, QueryStringList)
-> ClientQ m (StoreLeaf (Var a))
genClientQ pm :: Proxy m
pm _ = Proxy m
-> Proxy (QA () :> Leaf a)
-> (Query, QueryStringList)
-> ClientQ m (QA () :> Leaf a)
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy (QA () :> Leaf a)
forall k (t :: k). Proxy t
Proxy @(QA () :> Leaf a))
instance (HasCodec a, RunQueryClient m) => HasQueryClient m (StoreLeaf (A.Array a)) where
type ClientQ m (StoreLeaf (A.Array a)) = ClientQ m (QA Word64 :> Leaf a)
genClientQ :: Proxy m
-> Proxy (StoreLeaf (Array a))
-> (Query, QueryStringList)
-> ClientQ m (StoreLeaf (Array a))
genClientQ pm :: Proxy m
pm _ = Proxy m
-> Proxy (QA Word64 :> Leaf a)
-> (Query, QueryStringList)
-> ClientQ m (QA Word64 :> Leaf a)
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy (QA Word64 :> Leaf a)
forall k (t :: k). Proxy t
Proxy @(QA Word64 :> Leaf a))
instance (QueryData k, HasCodec v, RunQueryClient m) => HasQueryClient m (StoreLeaf (M.Map k v)) where
type ClientQ m (StoreLeaf (M.Map k v)) = ClientQ m (QA k :> Leaf v)
genClientQ :: Proxy m
-> Proxy (StoreLeaf (Map k v))
-> (Query, QueryStringList)
-> ClientQ m (StoreLeaf (Map k v))
genClientQ pm :: Proxy m
pm _ = Proxy m
-> Proxy (QA k :> Leaf v)
-> (Query, QueryStringList)
-> ClientQ m (QA k :> Leaf v)
forall (m :: * -> *) layout.
HasQueryClient m layout =>
Proxy m
-> Proxy layout -> (Query, QueryStringList) -> ClientQ m layout
genClientQ Proxy m
pm (Proxy (QA k :> Leaf v)
forall k (t :: k). Proxy t
Proxy @(QA k :> Leaf v))
data EmptyQueryClient = EmptyQueryClient deriving (EmptyQueryClient -> EmptyQueryClient -> Bool
(EmptyQueryClient -> EmptyQueryClient -> Bool)
-> (EmptyQueryClient -> EmptyQueryClient -> Bool)
-> Eq EmptyQueryClient
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EmptyQueryClient -> EmptyQueryClient -> Bool
$c/= :: EmptyQueryClient -> EmptyQueryClient -> Bool
== :: EmptyQueryClient -> EmptyQueryClient -> Bool
$c== :: EmptyQueryClient -> EmptyQueryClient -> Bool
Eq, Int -> EmptyQueryClient -> String -> String
[EmptyQueryClient] -> String -> String
EmptyQueryClient -> String
(Int -> EmptyQueryClient -> String -> String)
-> (EmptyQueryClient -> String)
-> ([EmptyQueryClient] -> String -> String)
-> Show EmptyQueryClient
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
showList :: [EmptyQueryClient] -> String -> String
$cshowList :: [EmptyQueryClient] -> String -> String
show :: EmptyQueryClient -> String
$cshow :: EmptyQueryClient -> String
showsPrec :: Int -> EmptyQueryClient -> String -> String
$cshowsPrec :: Int -> EmptyQueryClient -> String -> String
Show, EmptyQueryClient
EmptyQueryClient -> EmptyQueryClient -> Bounded EmptyQueryClient
forall a. a -> a -> Bounded a
maxBound :: EmptyQueryClient
$cmaxBound :: EmptyQueryClient
minBound :: EmptyQueryClient
$cminBound :: EmptyQueryClient
Bounded, Int -> EmptyQueryClient
EmptyQueryClient -> Int
EmptyQueryClient -> [EmptyQueryClient]
EmptyQueryClient -> EmptyQueryClient
EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient]
EmptyQueryClient
-> EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient]
(EmptyQueryClient -> EmptyQueryClient)
-> (EmptyQueryClient -> EmptyQueryClient)
-> (Int -> EmptyQueryClient)
-> (EmptyQueryClient -> Int)
-> (EmptyQueryClient -> [EmptyQueryClient])
-> (EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient])
-> (EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient])
-> (EmptyQueryClient
-> EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient])
-> Enum EmptyQueryClient
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: EmptyQueryClient
-> EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient]
$cenumFromThenTo :: EmptyQueryClient
-> EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient]
enumFromTo :: EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient]
$cenumFromTo :: EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient]
enumFromThen :: EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient]
$cenumFromThen :: EmptyQueryClient -> EmptyQueryClient -> [EmptyQueryClient]
enumFrom :: EmptyQueryClient -> [EmptyQueryClient]
$cenumFrom :: EmptyQueryClient -> [EmptyQueryClient]
fromEnum :: EmptyQueryClient -> Int
$cfromEnum :: EmptyQueryClient -> Int
toEnum :: Int -> EmptyQueryClient
$ctoEnum :: Int -> EmptyQueryClient
pred :: EmptyQueryClient -> EmptyQueryClient
$cpred :: EmptyQueryClient -> EmptyQueryClient
succ :: EmptyQueryClient -> EmptyQueryClient
$csucc :: EmptyQueryClient -> EmptyQueryClient
Enum)
instance HasQueryClient m EmptyQueryServer where
type ClientQ m EmptyQueryServer = EmptyQueryClient
genClientQ :: Proxy m
-> Proxy EmptyQueryServer
-> (Query, QueryStringList)
-> ClientQ m EmptyQueryServer
genClientQ _ _ _ = EmptyQueryClient
ClientQ m EmptyQueryServer
EmptyQueryClient