web5-rust 1.1.9

A rust crate for interacting with Web5
Documentation
use super::Error;

use crate::ed25519::SecretKey as EdSecretKey;
use simple_crypto::{PublicKey, Hashable};
use simple_database::database::{FiltersBuilder, Filter, IndexBuilder};

use crate::dids::{Identity, DidKeyPair, Did};
use super::structs::{AgentKey, DwnKey, Record};
use super::json_rpc::JsonRpc;
use super::Agent;

use super::protocol::{SystemProtocols, Protocol};

use super::traits::Router;
use crate::dids::DidResolver;


pub struct Wallet {
    _did_key: EdSecretKey,
    sig_key: DidKeyPair,
    enc_key: DwnKey,
    com_key: DwnKey,
    router: Box<dyn Router>,
    did_resolver: Box<dyn DidResolver>,
}

impl Wallet {
    pub fn new(
        identity: Identity,
        did_resolver: Box<dyn DidResolver>,
        router: Option<Box<dyn Router>>,
    ) -> Self {
        let router = router.unwrap_or(Box::new(JsonRpc::new(did_resolver.clone())));
        Wallet{
            _did_key: identity.did_key,
            sig_key: identity.sig_key,
            enc_key: DwnKey::new_root(identity.enc_key),
            com_key: DwnKey::new_root(identity.com_key),
            router,
            did_resolver,
        }
    }

    pub fn tenant(&self) -> &Did {&self.sig_key.public.did}

    pub async fn get_agent_key(&self, protocol: &Protocol) -> Result<AgentKey, Error> {
        let protocol_hash = protocol.hash();
        let root_agent_key = AgentKey::new(self.sig_key.clone(), self.enc_key.clone(), self.com_key.clone(), protocol_hash);
        let pf = SystemProtocols::protocol_folder(protocol_hash);
        let agent = Agent::new(root_agent_key, vec![pf.clone()], self.did_resolver.clone(), Some(self.router.clone()));

        let record = Record::new(Some(protocol_hash), &pf, Vec::new());
        agent.create(&[], None, record, None).await?;
        let filters = FiltersBuilder::build(vec![
            ("author", Filter::equal(self.tenant().to_string())),
            ("type", Filter::equal("agent_keys".to_string()))
        ]);
        let mut agent_keys = agent.public_read(filters, None, None).await?.first().and_then(|(_, record)|
            serde_json::from_slice::<Vec<PublicKey>>(&record.payload).ok()
        ).unwrap_or_default();

        let enc_key = self.enc_key.derive_path(&[protocol_hash])?;
        if !agent_keys.contains(&enc_key.key.public_key()) {
            agent_keys.push(enc_key.key.public_key());
            let record = Record::new(None, &SystemProtocols::agent_keys(), serde_json::to_vec(&agent_keys)?);
            let index = IndexBuilder::build(vec![("type", "agent_keys")]);
            agent.public_update(record, index, None).await?;
        }
        Ok(AgentKey::new(self.sig_key.clone(), enc_key, self.com_key.clone(), protocol_hash))
    }
}

impl std::fmt::Debug for Wallet {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Wallet")
        .field("tenant", &self.tenant().to_string())
        .finish()
    }
}