     /// - Parameter service: The service of the characteristics to find.
     /// - Parameter uuid: The UUID of the characteristics to find.
     /// - Parameter completion: The completion closure.
-    public func discoverCharacteristics(of service: Service,
-                                        by uuid: BluetoothUUID,
-                                        completion: @escaping (GATTClientResponse<[Characteristic]>) -> ()) {
+    public func discoverCharacteristics(
+        of service: Service,
+        by uuid: BluetoothUUID
+    ) async throws -> [Characteristic] {
         
         // The Attribute Protocol Read By Type Request is used to perform the beginning of the sub-procedure.
         // The Attribute Type is set to the UUID for «Characteristic» and the Starting Handle and Ending Handle
         // parameters shall be set to the service handle range.
-        
-        discoverCharacteristics(uuid: uuid, service: service, completion: completion)
+        return try await discoverCharacteristics(uuid: uuid, service: service)
     }
     
     /// Read Characteristic Value

public extension GATTClient {
    
    typealias Error = GATTClientError
    
    typealias Response<Value> = GATTClientResponse<Value>
    
    typealias Notification = (Data) -> ()
}


        // The Attribute Type is set to the known characteristic UUID and the Starting Handle and Ending Handle parameters
        // shall be set to the range over which this read is to be performed. This is typically the handle range for the service in which the characteristic belongs.
        
        let pdu = ATTReadByTypeRequest(
            startHandle: handleRange.start,
            endHandle: handleRange.end,
            attributeType: uuid
        )
        
        let operation = ReadUsingUUIDOperation(uuid: uuid, completion: completion)
        
        send(pdu) { [unowned self] in
            self.readByTypeResponse($0, operation: operation)
        }
    }
    
    /// Read Multiple Characteristic Values
