use polyc_eventlog::Event;
use polyc_proto::kinds;
pub fn verified_wallet_link_lifecycle_events<'a>(
events: &'a [Event],
trusted_signers: &'a [Vec<u8>],
) -> impl Iterator<Item = polyc_crypto::approval::VerifiedWalletLinkLifecycle> + 'a {
events.iter().filter_map(move |ev| {
let (base, _) = kinds::parse(&ev.kind);
if base != kinds::WALLET_LINK_LIFECYCLE {
return None;
}
let verified = polyc_crypto::approval::verify_signed_wallet_link_lifecycle(
&ev.payload,
trusted_signers,
)?;
if verified.kind != kinds::WALLET_LINK_LIFECYCLE {
return None;
}
Some(verified)
})
}
#[cfg(test)]
mod tests {
#![allow(clippy::pedantic, clippy::nursery, missing_docs, clippy::unwrap_used)]
use polyc_crypto::approval::{
ApprovalSigner, WalletLinkLifecyclePayload, wallet_link_lifecycle_payload,
};
use super::*;
fn signed_lifecycle_event(signer: &ApprovalSigner, transition: &str, subject: &str) -> Vec<u8> {
let (payload, sig, pk) = wallet_link_lifecycle_payload(
&WalletLinkLifecyclePayload {
kind: kinds::WALLET_LINK_LIFECYCLE,
transition,
subject,
wallet_address: "0x1111111111111111111111111111111111111111",
currency: "0x2222222222222222222222222222222222222222",
chain_id: "42431",
limit_base_units: "5000000",
limit_human: "5",
period_secs: "86400",
expiry_unix: "1780086400",
recipients: "",
conversation_id: "conv-1",
timestamp: "1780000000",
},
signer,
);
let _ = (sig, pk);
payload
}
#[test]
fn verified_wallet_link_lifecycle_events_drops_unknown_signer() {
let trusted = ApprovalSigner::from_seed(1);
let untrusted = ApprovalSigner::from_seed(2);
let events = vec![
Event::new(
"wallet_link_lifecycle".to_owned(),
signed_lifecycle_event(&trusted, "linked", "persona-1"),
),
Event::new(
"wallet_link_lifecycle".to_owned(),
signed_lifecycle_event(&untrusted, "linked", "persona-2"),
),
];
let trusted_signers = vec![trusted.public_key_bytes()];
let decoded: Vec<_> =
verified_wallet_link_lifecycle_events(&events, &trusted_signers).collect();
assert_eq!(decoded.len(), 1);
assert_eq!(decoded[0].subject, "persona-1");
}
#[test]
fn verified_wallet_link_lifecycle_events_filters_by_kind_base() {
let signer = ApprovalSigner::from_seed(3);
let events = vec![
Event::new(
kinds::WALLET_LINK_LIFECYCLE.to_owned(),
signed_lifecycle_event(&signer, "linked", "persona-1"),
),
Event::new("usage".to_owned(), vec![]),
];
let trusted_signers = vec![signer.public_key_bytes()];
let decoded: Vec<_> =
verified_wallet_link_lifecycle_events(&events, &trusted_signers).collect();
assert_eq!(decoded.len(), 1);
}
#[test]
fn verified_wallet_link_lifecycle_events_drops_malformed_payload() {
let events = vec![Event::new(
kinds::WALLET_LINK_LIFECYCLE.to_owned(),
vec![0xFF, 0xFE, 0xFD],
)];
let decoded: Vec<_> = verified_wallet_link_lifecycle_events(&events, &[]).collect();
assert_eq!(decoded.len(), 0);
}
}