diff --git a/grpc-etcd-client.cabal b/grpc-etcd-client.cabal
--- a/grpc-etcd-client.cabal
+++ b/grpc-etcd-client.cabal
@@ -2,10 +2,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 3392648f92ab73a947ea1cebfa2c865ee727a9c4d122aca95a316bbbb2f3ea99
+-- hash: fe4df847fc02c4a21ca937d7018145dd7276df51b662536b3c17dcbc79eb6ee4
 
 name:           grpc-etcd-client
-version:        0.1.1.0
+version:        0.1.1.1
 synopsis:       gRPC client for etcd
 description:    Please see the README on GitHub at <https://github.com/lucasdicioccio/etcd-grpc#readme>
 category:       Distributed Computing
@@ -35,14 +35,14 @@
       src
   default-extensions: DataKinds OverloadedStrings
   build-depends:
-      base >=4.7 && <5
-    , bytestring
-    , data-default-class
+      base >=4.11 && <5
+    , bytestring >=0.10 && <0.11
+    , data-default-class >=0.1 && <0.2
     , grpc-api-etcd ==0.1.0.1
-    , http2-client
-    , http2-client-grpc >=0.5 && <0.6
-    , lens
-    , network
-    , proto-lens
-    , proto-lens-protoc
+    , http2-client >=0.8 && <0.9
+    , http2-client-grpc >=0.5.0.2 && <0.6
+    , lens >=4.16 && <4.17
+    , network >=2.6 && <2.7
+    , proto-lens >=0.3 && <0.4
+    , proto-lens-protoc >=0.3 && <0.4
   default-language: Haskell2010
diff --git a/src/Network/EtcdV3.hs b/src/Network/EtcdV3.hs
--- a/src/Network/EtcdV3.hs
+++ b/src/Network/EtcdV3.hs
@@ -47,16 +47,11 @@
 etcdClientConfigSimple host port tls =
     (grpcClientConfigSimple host port tls) { _grpcClientConfigCompression = uncompressed }
 
--- | Helper to unpack an unary gRPC call output.
-unaryOutput
-  :: (Applicative f, Field3 a1 b1 (Either c1 a2) (Either c1 b2)) =>
-     (a2 -> f b2)
-     -> Either c2 (Either c3 a1) -> f (Either c2 (Either c3 b1))
-unaryOutput = _Right . _Right . _3 . _Right
-
 -- | Type alias to simplify type signatures.
 type EtcdQuery a = IO (Maybe a)
 
+-----------------------------------------------------------------------------------------
+
 -- | Data type to unify the three addressing schemes in etcd.
 --
 -- See 'range'.
@@ -103,6 +98,8 @@
     rest = C8.dropWhile (== '\xff') $ C8.reverse k
     kPlus1 = if C8.null rest then "\NUL" else C8.reverse $ C8.cons (succ (C8.head rest)) (C8.drop 1 rest)
 
+-----------------------------------------------------------------------------------------
+
 -- | Asks for a lease of a given duration.
 grantLease
   :: GrpcClient
@@ -135,6 +132,8 @@
 keepAlive grpc (GrantedLease leaseID) =
     preview unaryOutput <$> rawUnary (RPC :: RPC EtcdRPC.Lease "leaseKeepAlive") grpc (def & EtcdPB.id .~ leaseID)
 
+-----------------------------------------------------------------------------------------
+
 -- | Put one value.
 put
   :: GrpcClient
@@ -164,6 +163,8 @@
   where
     (k0, kend) = rangePairForRangeQuery r
 
+-----------------------------------------------------------------------------------------
+
 -- | Opaque lock.
 --
 -- Show instance used for printing purposes only.
@@ -194,3 +195,12 @@
   -> EtcdQuery LockRPC.UnlockResponse
 unlock grpc (AcquiredLock k) = preview unaryOutput <$>
     rawUnary (RPC :: RPC LockRPC.Lock "unlock") grpc (def & LockPB.key .~ k)
+
+-----------------------------------------------------------------------------------------
+
+watch
+  :: GrpcClient
+  -> (a -> EtcdRPC.WatchResponse -> IO a)
+  -> a
+  -> EtcdQuery (a)
+watch grpc foo = undefined
