twetch-sdk 0.0.1

rust twetch sdk with wasm builds
Documentation
use crate::{api::Api, chat::message::Message, wallet::Wallet};
use anyhow::Result;
use base64;
use bsv_wasm::{ECIESCiphertext, Hash, PrivateKey, PublicKey, ECIES};
use serde::*;
use serde_json::json;
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Conversation {
    id: String,
    key: String,
}

impl Conversation {
    pub async fn create(token: String, user_ids: Vec<String>) -> Result<Conversation> {
        let api = Api { token };
        let pubkeys = api
            .list_pubkeys(user_ids.clone())
            .await?
            .as_array()
            .unwrap()
            .clone();

        let key = Conversation::generate_key();

        let mut conversation_users = Vec::new();

        for e in 0..user_ids.len() {
            let pubkey = pubkeys[e]
                .get("publicKey")
                .unwrap()
                .as_str()
                .unwrap()
                .to_string();
            conversation_users.push(json!({
                "userId": user_ids[e],
                "encryptedKey": Conversation::encrypt_key(key.clone(), pubkey).unwrap()
            }))
        }

        let payload =
            json!({ "conversationUsers": serde_json::to_value(conversation_users).unwrap() })
                .to_string();

        let res = api.create_conversation(payload).await?;

        Ok(Conversation {
            id: res.get("id").unwrap().as_str().unwrap().to_string(),
            key,
        })
    }

    pub async fn create_message(&self, token: String, description: String) -> Result<Message> {
        Message::create(
            self.key.clone(),
            self.id.clone(),
            "1".to_string(),
            description,
            token,
        )
        .await
    }
}

#[wasm_bindgen]
impl Conversation {
    #[wasm_bindgen(js_name = generateKey)]
    pub fn generate_key() -> String {
        Hash::sha_256(&PrivateKey::from_random().to_bytes())
            .to_hex()
            .chars()
            .skip(32)
            .take(32)
            .collect()
    }

    #[wasm_bindgen(js_name = encrypt)]
    pub fn encrypt_key(key: String, pubkey: String) -> Option<String> {
        let public_key = match PublicKey::from_hex(&pubkey) {
            Ok(v) => v,
            Err(_) => return None,
        };

        let encrypted = match ECIES::encrypt_with_ephemeral_private_key(key.as_bytes(), &public_key)
        {
            Ok(v) => v.to_bytes(),
            Err(_) => return None,
        };

        Some(base64::encode_config(encrypted, base64::STANDARD))
    }

    #[wasm_bindgen(js_name = decrypt)]
    pub fn decrypt_key(encrypted_key: String, seed: String) -> Option<Vec<u8>> {
        let wallet = Wallet::new(seed);
        let xpriv = match wallet.xpriv_account() {
            Some(v) => v,
            None => return None,
        };

        let encrypted_key_buf = match base64::decode_config(encrypted_key, base64::STANDARD) {
            Ok(v) => v,
            Err(_) => return None,
        };

        let ciphertext = match ECIESCiphertext::from_bytes(&encrypted_key_buf, true) {
            Ok(v) => v,
            Err(_) => return None,
        };

        let pubkey = match ciphertext.extract_public_key() {
            Ok(v) => v,
            Err(_) => return None,
        };

        let decrypted = match ECIES::decrypt(&ciphertext, &xpriv.get_private_key(), &pubkey) {
            Ok(v) => v,
            Err(_) => return None,
        };

        return Some(decrypted);
    }
}