diff --git a/Cargo.toml b/Cargo.toml
index 25f498f..32be834 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
+async-recursion = "1.0.4"
 async-trait = "0.1.68"
 quick-xml = { git = "https://github.com/tafia/quick-xml.git", features = ["async-tokio", "serialize"] }
 # TODO: remove unneeded features
diff --git a/notes.md b/notes.md
new file mode 100644
index 0000000..7d76da1
--- /dev/null
+++ b/notes.md
@@ -0,0 +1,5 @@
+tag =  or 
+element =  or 
+stanza = specific element   
+
+
diff --git a/src/client/encrypted.rs b/src/client/encrypted.rs
index a4bf0d1..76f600c 100644
--- a/src/client/encrypted.rs
+++ b/src/client/encrypted.rs
@@ -1,35 +1,26 @@
-use std::str;
-
 use quick_xml::{
-    de::Deserializer,
-    events::{BytesDecl, BytesStart, Event},
-    name::QName,
-    se::Serializer,
+    events::{BytesDecl, Event},
     Reader, Writer,
 };
-use rsasl::prelude::{Mechname, SASLClient};
-use serde::{Deserialize, Serialize};
-use tokio::io::{AsyncWriteExt, BufReader, ReadHalf, WriteHalf};
+use tokio::io::{BufReader, ReadHalf, WriteHalf};
 use tokio::net::TcpStream;
 use tokio_native_tls::TlsStream;
 
-use crate::stanza::{
-    sasl::{Auth, Challenge, Mechanisms},
-    stream::{StreamFeature, StreamFeatures},
-};
+use crate::element::Element;
+use crate::stanza::stream::{Stream, StreamFeature};
 use crate::Jabber;
 use crate::Result;
 
 pub struct JabberClient<'j> {
     reader: Reader>>>,
-    writer: WriteHalf>,
+    writer: Writer>>,
     jabber: &'j mut Jabber<'j>,
 }
 
 impl<'j> JabberClient<'j> {
     pub fn new(
         reader: Reader>>>,
-        writer: WriteHalf>,
+        writer: Writer>>,
         jabber: &'j mut Jabber<'j>,
     ) -> Self {
         Self {
@@ -40,90 +31,29 @@ impl<'j> JabberClient<'j> {
     }
 
     pub async fn start_stream(&mut self) -> Result<()> {
+        // client to server
         let declaration = BytesDecl::new("1.0", None, None);
-        let mut stream_element = BytesStart::new("stream:stream");
-        stream_element.push_attribute(("from".as_bytes(), self.jabber.jid.to_string().as_bytes()));
-        stream_element.push_attribute(("to".as_bytes(), self.jabber.server.as_bytes()));
-        stream_element.push_attribute(("version", "1.0"));
-        stream_element.push_attribute(("xml:lang", "en"));
-        stream_element.push_attribute(("xmlns", "jabber:client"));
-        stream_element.push_attribute(("xmlns:stream", "http://etherx.jabber.org/streams"));
-        let mut writer = Writer::new(&mut self.writer);
-        writer.write_event_async(Event::Decl(declaration)).await;
-        writer.write_event_async(Event::Start(stream_element)).await;
+        let server = &self.jabber.server.to_owned().try_into()?;
+        let stream_element =
+            Stream::new_client(&self.jabber.jid, server, None, Some("en".to_string()));
+        self.writer
+            .write_event_async(Event::Decl(declaration))
+            .await;
+        let stream_element: Element<'_> = stream_element.into();
+        stream_element.write_start(&mut self.writer).await?;
+        // server to client
         let mut buf = Vec::new();
-        loop {
-            match self.reader.read_event_into_async(&mut buf).await.unwrap() {
-                Event::Start(e) => {
-                    println!("{:?}", e);
-                    break;
-                }
-                e => println!("decl: {:?}", e),
-            };
-        }
+        self.reader.read_event_into_async(&mut buf).await?;
+        let _stream_response = Element::read_start(&mut self.reader).await?;
         Ok(())
     }
 
-    pub async fn get_node<'a>(&mut self) -> Result {
-        let mut buf = Vec::new();
-        let mut txt = Vec::new();
-        let mut qname_set = false;
-        let mut qname: Option> = None;
-        loop {
-            match self.reader.read_event_into_async(&mut buf).await? {
-                Event::Start(e) => {
-                    if !qname_set {
-                        qname = Some(e.name().into_inner().to_owned());
-                        qname_set = true;
-                    }
-                    txt.push(b'<');
-                    txt = txt
-                        .into_iter()
-                        .chain(buf.to_owned())
-                        .chain(vec![b'>'])
-                        .collect();
-                }
-                Event::End(e) => {
-                    let mut end = false;
-                    if e.name() == QName(qname.as_deref().unwrap()) {
-                        end = true;
-                    }
-                    txt.push(b'<');
-                    txt = txt
-                        .into_iter()
-                        .chain(buf.to_owned())
-                        .chain(vec![b'>'])
-                        .collect();
-                    if end {
-                        break;
-                    }
-                }
-                Event::Text(_e) => {
-                    txt = txt.into_iter().chain(buf.to_owned()).collect();
-                }
-                _ => {
-                    txt.push(b'<');
-                    txt = txt
-                        .into_iter()
-                        .chain(buf.to_owned())
-                        .chain(vec![b'>'])
-                        .collect();
-                }
-            }
-            buf.clear();
+    pub async fn get_features(&mut self) -> Result