keri-sdk 0.1.9

KERI Software Development Kit
Documentation
use ed25519_dalek::SigningKey;
use keri_core::{
    actor::parse_event_stream,
    event_message::{
        signature::{Nontransferable, Signature},
        signed_event_message::{Message, Op},
    },
    prefix::{BasicPrefix, IdentifierPrefix, SeedPrefix, SelfSigningPrefix},
    query::query_event::{SignedKelQuery, SignedQueryMessage},
    signer::Signer,
};
use keri_sdk::{database::redb::RedbDatabase, Controller};
use std::sync::Arc;
use teliox::database::{redb::RedbTelDatabase, TelEventDatabase};

struct KeysConfig {
    pub current: SeedPrefix,
    pub next: SeedPrefix,
}

impl Default for KeysConfig {
    fn default() -> Self {
        let current = SigningKey::generate(&mut rand::rngs::OsRng);
        let next = SigningKey::generate(&mut rand::rngs::OsRng);
        Self {
            current: SeedPrefix::RandomSeed256Ed25519(
                current.as_bytes().to_vec(),
            ),
            next: SeedPrefix::RandomSeed256Ed25519(next.as_bytes().to_vec()),
        }
    }
}

#[tokio::test]
async fn test_init_id() -> Result<(), ()> {
    let root = tempfile::Builder::new()
        .prefix("test-db")
        .tempdir()
        .unwrap();
    println!("Root path: {:?}", root.path());
    std::fs::create_dir_all(root.path()).unwrap();

    let db_path = root.path().to_path_buf();
    let event_database = {
        let mut path = db_path.clone();
        path.push("events_database");
        Arc::new(RedbDatabase::new(&path).unwrap())
    };

    let tel_events_db = {
        let mut path = db_path.clone();
        path.push("tel");
        path.push("events");
        Arc::new(RedbTelDatabase::new(&path).unwrap())
    };

    let keys = KeysConfig::default();
    let (next_pub_key, _next_secret_keys) =
        keys.next.derive_key_pair().map_err(|_e| ())?;

    let signer =
        Arc::new(Signer::new_with_seed(&keys.current.clone()).unwrap());

    let controller = Controller::new(event_database, tel_events_db);
    let public_keys = vec![BasicPrefix::Ed25519(signer.public_key())];
    let next_pub_keys = vec![BasicPrefix::Ed25519NT(next_pub_key)];

    let signing_inception =
        controller.incept(public_keys.clone(), next_pub_keys)?;
    let signature = SelfSigningPrefix::new(
        cesrox::primitives::codes::self_signing::SelfSigning::Ed25519Sha512,
        signer.sign(signing_inception.as_bytes()).unwrap(),
    );
    let signing_identifier =
        controller.finalize_incept(signing_inception.as_bytes(), &signature)?;
    println!("Identifier: {:?}", signing_identifier.get_prefix());
    println!("KEL: {:?}", signing_identifier.get_own_kel());

    let witness_id = serde_json::Value::String(
        "BNJJhjUnhlw-lsbYdehzLsX1hJMG9QJlK_wJ5AunJLrM".to_string(),
    );
    let id_str = serde_json::Value::String(
        "EHIydjfGpSu8mKvrDeWWPaV-mBPeP6Ad7DE6v5fZv2ps".to_string(),
    );
    let id: IdentifierPrefix =
        serde_json::from_value(id_str).map_err(|_e| ())?;
    let witness_prefix: IdentifierPrefix =
        serde_json::from_value(witness_id).map_err(|_e| ())?;
    let q = signing_identifier.get_log_query(id, witness_prefix, None, None);
    let signature_qry = Signature::NonTransferable(Nontransferable::Couplet(vec![(
            public_keys[0].clone(),
            SelfSigningPrefix::new(
                cesrox::primitives::codes::self_signing::SelfSigning::Ed25519Sha512,
                signer.sign(q.encode().unwrap()).unwrap(),
            )
    )]));
    let singed_kel_q = SignedKelQuery {
        query: q,
        signature: signature_qry,
    };
    let signed_qry = SignedQueryMessage::KelQuery(singed_kel_q);

    let body = Message::Op(Op::Query(signed_qry)).to_cesr().unwrap();
    let client = reqwest::Client::new();
    let url: url::Url = serde_json::from_value(serde_json::Value::String(
        "http://w1.ea.argo.colossi.network/query".to_string(),
    ))
    .map_err(|_e| ())?;
    let response = client.post(url).body(body).send().await.map_err(|e| {
        eprintln!("Request error: {:?}", e);
    })?;

    if !response.status().is_success() {
        println!("Request failed with status: {}", response.status());
        let error_text = response.text().await.map_err(|_| ())?;
        println!("Error body: {}", error_text);
        return Err(());
    }

    let kel = response.text().await.map_err(|_| ())?;
    let parsed_kel = parse_event_stream(kel.as_bytes()).map_err(|_e| ())?;
    println!("KEL: {:?}", kel);
    println!("Parsed KEL: {:?}", parsed_kel.len());
    controller.process_kel(&parsed_kel).map_err(|e| {
        eprintln!("Processing error: {:?}", e);
    })?;

    // let msg = r#"{"v":"ACDC10JSON000207_","d":"EGRIIeNj2HIP787COJFiQbYqsp6UwAR22oeqWsEVhq42","i":"EHIydjfGpSu8mKvrDeWWPaV-mBPeP6Ad7DE6v5fZv2ps","ri":"EMDfCDynqGvpaN7Fbm5FADyfS98q_WUkPKmbZapBB1J_","s":"EHLjK9n1i1osh8SPYpyotPxC8IeBqtdfK-Qrz4_TZp6G","a":{"d":"ENaVuh9EMbTGgVjbnPHDZDDxvhsvzIZsuvTEIkFa3JPP","a":{"last_name":"KOWALSKI","first_name":"JAN","birth_date":"07.04.1964","birth_place":"WARSZAWA","issue_date":"06.03.2019","expiry_date":"18.01.2028","issuer":"PREZYDENT m.st. WARSZAWY","pesel":"64040738293","number":"SP006/15/1"}}}"#;
    let vc_said: said::SelfAddressingIdentifier =
        "EGRIIeNj2HIP787COJFiQbYqsp6UwAR22oeqWsEVhq42"
            .parse()
            .unwrap();
    let registry_id: said::SelfAddressingIdentifier =
        "EMDfCDynqGvpaN7Fbm5FADyfS98q_WUkPKmbZapBB1J_"
            .parse()
            .unwrap();

    let tel_qry = signing_identifier
        .get_tel_query(
            IdentifierPrefix::self_addressing(registry_id),
            IdentifierPrefix::self_addressing(vc_said.clone()),
        )
        .map_err(|_e| ())?;

    let signature_tel_query = SelfSigningPrefix::new(
        cesrox::primitives::codes::self_signing::SelfSigning::Ed25519Sha512,
        signer.sign(tel_qry.encode().unwrap()).unwrap(),
    );
    let tel_query = match signing_identifier.id {
        IdentifierPrefix::Basic(bp) => {
            teliox::query::SignedTelQuery::new_nontrans(
                tel_qry.clone(),
                bp.clone(),
                signature_tel_query,
            )
        }
        _ => {
            let signatures =
                vec![keri_core::prefix::IndexedSignature::new_both_same(
                    signature_tel_query,
                    0,
                )];
            teliox::query::SignedTelQuery::new_trans(
                tel_qry.clone(),
                signing_identifier.id.clone(),
                signatures,
            )
        }
    };

    let tel_url: url::Url = serde_json::from_value(serde_json::Value::String(
        "http://wa1.hcf.argo.colossi.network/query/tel".to_string(),
    ))
    .map_err(|_e| ())?;
    let tel_response = client
        .post(tel_url)
        .body(tel_query.to_cesr().unwrap())
        .send()
        .await
        .map_err(|e| {
            eprintln!("Request error: {:?}", e);
        })?;

    if !tel_response.status().is_success() {
        println!("Request failed with status: {}", tel_response.status());
        let error_text = tel_response.text().await.map_err(|_| ())?;
        println!("Error body: {}", error_text);
        return Err(());
    }

    let tel = tel_response.text().await.map_err(|_| ())?;
    println!("Tel: {}", tel);
    let _ = controller.process_tel(tel.as_bytes());
    let state = controller.get_vc_state(&vc_said).map_err(|_e| ())?;
    println!("VC said: {:?}", vc_said);
    println!("VC State: {:?}", state);

    Ok(())
}