1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use crate::{Error, Result};
use diem_json_rpc_types::views::{AccountStateWithProofView, EventWithProofView};
use diem_types::{
account_state::AccountState,
account_state_blob::AccountStateBlob,
contract_event::{ContractEvent, EventWithProof},
};
use move_core_types::{language_storage::TypeTag, move_resource::{MoveResource, MoveStructType}};
use serde::de::DeserializeOwned;
use std::convert::TryFrom;
#[derive(Debug, Clone)]
pub struct Event<T: MoveStructType + DeserializeOwned> {
data: T,
event: ContractEvent,
}
impl<T: MoveStructType + DeserializeOwned> Event<T> {
pub fn data(&self) -> &T {
&self.data
}
pub fn event(&self) -> &ContractEvent {
&self.event
}
}
pub fn get_events<T: MoveStructType + DeserializeOwned>(
events: Vec<EventWithProofView>,
) -> Result<Vec<Event<T>>> {
let events_with_proof: Vec<EventWithProof> = events
.into_iter()
.map(|e| {
bcs::from_bytes::<EventWithProof>(e.event_with_proof.inner()).map_err(Error::decode)
})
.collect::<Result<Vec<EventWithProof>>>()?;
let event_type_tag = TypeTag::Struct(T::struct_tag());
events_with_proof
.into_iter()
.map(|e| {
if &event_type_tag != e.event.type_tag() {
Err(Error::decode(format!(
"Type tag of events in stream {:?} does not match type tag of generic type T {:?}", event_type_tag, e.event.type_tag()),
))
} else {
bcs::from_bytes::<T>(e.event.event_data())
.map(|data| Event {
data,
event: e.event,
})
.map_err(Error::decode)
}
})
.collect::<Result<Vec<Event<T>>>>()
}
fn get_account_state(
account_state_with_proof: AccountStateWithProofView,
) -> Result<Option<AccountState>> {
let account_opt = account_state_with_proof.blob;
if let Some(account) = account_opt {
let account_state_blob: AccountStateBlob =
bcs::from_bytes(account.inner()).map_err(Error::decode)?;
return Ok(Some(
AccountState::try_from(&account_state_blob).map_err(Error::decode)?,
));
}
Ok(None)
}
pub fn get_resource<T: MoveResource>(
account_state_with_proof: AccountStateWithProofView,
) -> Result<Option<T>> {
if let Some(account_state) = get_account_state(account_state_with_proof)? {
return account_state.get_resource::<T>().map_err(Error::decode);
}
Ok(None)
}