holochain_types/
activity.rs

1//! Types for agents chain activity
2
3use holo_hash::ActionHash;
4use holo_hash::AgentPubKey;
5use holochain_serialized_bytes::prelude::*;
6use holochain_zome_types::prelude::*;
7
8#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, SerializedBytes)]
9/// An agents chain records returned from a agent_activity_query
10pub struct AgentActivityResponse {
11    /// The agent this activity is for
12    pub agent: AgentPubKey,
13    /// Valid actions on this chain.
14    pub valid_activity: ChainItems,
15    /// Actions that were rejected by the agent activity
16    /// authority and therefor invalidate the chain.
17    pub rejected_activity: ChainItems,
18    /// The status of this chain.
19    pub status: ChainStatus,
20    /// The highest chain action that has
21    /// been observed by this authority.
22    pub highest_observed: Option<HighestObserved>,
23    /// Any warrants at the basis of this agent.
24    pub warrants: Vec<Warrant>,
25}
26
27impl AgentActivityResponse {
28    /// Convert an empty response to a different type.
29    pub fn from_empty(other: AgentActivityResponse) -> Self {
30        let convert_activity = |items: &ChainItems| match items {
31            ChainItems::Full(_) => ChainItems::Full(Vec::with_capacity(0)),
32            ChainItems::Hashes(_) => ChainItems::Hashes(Vec::with_capacity(0)),
33            ChainItems::NotRequested => ChainItems::NotRequested,
34        };
35        AgentActivityResponse {
36            agent: other.agent,
37            valid_activity: convert_activity(&other.valid_activity),
38            rejected_activity: convert_activity(&other.rejected_activity),
39            status: ChainStatus::Empty,
40            highest_observed: other.highest_observed,
41            warrants: other.warrants,
42        }
43    }
44
45    /// Convert to a status only response.
46    pub fn status_only(other: AgentActivityResponse) -> Self {
47        AgentActivityResponse {
48            agent: other.agent,
49            valid_activity: ChainItems::NotRequested,
50            rejected_activity: ChainItems::NotRequested,
51            status: ChainStatus::Empty,
52            highest_observed: other.highest_observed,
53            warrants: other.warrants,
54        }
55    }
56
57    /// Convert to a [ChainItems::Hashes] response.
58    pub fn hashes_only(other: AgentActivityResponse) -> Self {
59        let convert_activity = |items: ChainItems| match items {
60            ChainItems::Full(records) => ChainItems::Hashes(
61                records
62                    .into_iter()
63                    .map(|r| (r.action().action_seq(), r.address().clone()))
64                    .collect(),
65            ),
66            ChainItems::Hashes(h) => ChainItems::Hashes(h),
67            ChainItems::NotRequested => ChainItems::NotRequested,
68        };
69        AgentActivityResponse {
70            agent: other.agent,
71            valid_activity: convert_activity(other.valid_activity),
72            rejected_activity: convert_activity(other.rejected_activity),
73            status: other.status,
74            highest_observed: other.highest_observed,
75            warrants: other.warrants,
76        }
77    }
78}
79
80#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize, SerializedBytes)]
81/// The type of agent activity returned in this request
82pub enum ChainItems {
83    /// The full records
84    Full(Vec<Record>),
85    /// Just the hashes
86    Hashes(Vec<(u32, ActionHash)>),
87    /// Activity was not requested
88    NotRequested,
89}
90
91impl From<AgentActivityResponse> for AgentActivity {
92    fn from(a: AgentActivityResponse) -> Self {
93        let valid_activity = match a.valid_activity {
94            ChainItems::Full(records) => records
95                .into_iter()
96                .map(|el| (el.action().action_seq(), el.action_address().clone()))
97                .collect(),
98            ChainItems::Hashes(h) => h,
99            ChainItems::NotRequested => Vec::new(),
100        };
101        let rejected_activity = match a.rejected_activity {
102            ChainItems::Full(records) => records
103                .into_iter()
104                .map(|el| (el.action().action_seq(), el.action_address().clone()))
105                .collect(),
106            ChainItems::Hashes(h) => h,
107            ChainItems::NotRequested => Vec::new(),
108        };
109        Self {
110            valid_activity,
111            rejected_activity,
112            status: a.status,
113            highest_observed: a.highest_observed,
114            warrants: a.warrants,
115        }
116    }
117}
118
119/// A helper trait to allow [Record]s, [SignedActionHashed]s, and [ActionHashed]s to be converted into [ChainItems]
120/// without needing to know which source type is being operated on.
121pub trait ChainItemsSource {
122    /// Convert a source type into a [ChainItems] value.
123    fn to_chain_items(self) -> ChainItems;
124}
125
126impl ChainItemsSource for Vec<Record> {
127    fn to_chain_items(self) -> ChainItems {
128        ChainItems::Full(self)
129    }
130}
131
132impl ChainItemsSource for Vec<ActionHashed> {
133    fn to_chain_items(self) -> ChainItems {
134        ChainItems::Hashes(
135            self.into_iter()
136                .map(|a| (a.action_seq(), a.as_hash().clone()))
137                .collect(),
138        )
139    }
140}
141
142impl ChainItemsSource for Vec<(u32, ActionHash)> {
143    fn to_chain_items(self) -> ChainItems {
144        ChainItems::Hashes(self)
145    }
146}