use std::ops::ControlFlow;
use auths_id::keri::Event;
use auths_id::keri::types::Prefix;
use auths_id::ports::registry::RegistryBackend;
use crate::context::AuthsContext;
use crate::domains::identity::error::SetupError;
pub struct LocalSigner {
pub signer_did: String,
pub root_did: String,
pub anchor_seq: Option<u128>,
}
impl LocalSigner {
pub fn is_delegated(&self) -> bool {
self.signer_did != self.root_did
}
}
pub fn resolve_local_signer(ctx: &AuthsContext) -> Result<LocalSigner, SetupError> {
if let Ok(managed) = ctx.identity_storage.load_identity() {
let did = managed.controller_did.to_string();
let anchor_seq = root_tip_seq(ctx, &did);
return Ok(LocalSigner {
signer_did: did.clone(),
root_did: did,
anchor_seq,
});
}
let mut prefixes: Vec<String> = Vec::new();
ctx.registry
.visit_identities(&mut |prefix| {
prefixes.push(prefix.to_string());
ControlFlow::Continue(())
})
.map_err(|e| {
SetupError::StorageError(
auths_id::error::StorageError::InvalidData(e.to_string()).into(),
)
})?;
for prefix_str in prefixes {
let prefix = Prefix::new_unchecked(prefix_str);
if let Ok(Event::Dip(dip)) = ctx.registry.get_event(&prefix, 0) {
let root_did = format!("did:keri:{}", dip.di);
let anchor_seq = root_tip_seq(ctx, &root_did);
return Ok(LocalSigner {
signer_did: format!("did:keri:{}", dip.i),
root_did,
anchor_seq,
});
}
}
Err(SetupError::StorageError(
auths_id::error::StorageError::InvalidData(
"no local signing identity found (neither a root identity nor a delegated \
device). Run `auths init`, or pair this device with `auths pair --join`."
.to_string(),
)
.into(),
))
}
fn root_tip_seq(ctx: &AuthsContext, root_did: &str) -> Option<u128> {
let prefix = root_did.strip_prefix("did:keri:")?;
ctx.registry
.get_tip(&Prefix::new_unchecked(prefix.to_string()))
.ok()
.map(|tip| tip.sequence)
}