forest/rpc/methods/
misc.rs1use std::collections::BTreeMap;
5
6use cid::Cid;
7use enumflags2::BitFlags;
8use fvm_ipld_blockstore::Blockstore;
9use schemars::JsonSchema;
10use serde::{Deserialize, Serialize};
11
12use crate::db::EthMappingsStore;
13use crate::rpc::eth::CollectedEvent;
14use crate::rpc::eth::filter::{ParsedFilter, SkipEvent};
15use crate::{
16 blocks::TipsetKey,
17 lotus_json::{LotusJson, lotus_json_with_self},
18 rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError, types::EventEntry},
19 shim::{address::Address, clock::ChainEpoch},
20};
21
22pub enum GetActorEventsRaw {}
23impl RpcMethod<1> for GetActorEventsRaw {
24 const NAME: &'static str = "Filecoin.GetActorEventsRaw";
25 const PARAM_NAMES: [&'static str; 1] = ["eventFilter"];
26 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
27 const PERMISSION: Permission = Permission::Read;
28 const DESCRIPTION: Option<&'static str> = Some(
29 "Returns all user-programmed and built-in actor events that match the given filter. Results may be limited by MaxFilterResults, MaxFilterHeightRange, and the node's available historical data.",
30 );
31
32 type Params = (Option<ActorEventFilter>,);
33 type Ok = Vec<ActorEvent>;
34 async fn handle(
35 ctx: Ctx<impl Blockstore + EthMappingsStore + Send + Sync + 'static>,
36 (filter,): Self::Params,
37 _: &http::Extensions,
38 ) -> Result<Self::Ok, ServerError> {
39 if let Some(filter) = filter {
40 let parsed_filter = ParsedFilter::from_actor_event_filter(
41 ctx.chain_store().heaviest_tipset().epoch(),
42 ctx.eth_event_handler.max_filter_height_range,
43 filter,
44 )?;
45 let events = ctx
46 .eth_event_handler
47 .get_events_for_parsed_filter(&ctx, &parsed_filter, SkipEvent::Never)
48 .await?;
49 Ok(events.into_iter().map(|ce| ce.into()).collect())
50 } else {
51 Ok(vec![])
52 }
53 }
54}
55
56#[derive(Clone, JsonSchema, Serialize, Deserialize)]
57#[serde(rename_all = "camelCase")]
58pub struct ActorEventFilter {
59 #[serde(default, skip_serializing_if = "Vec::is_empty")]
60 pub addresses: Vec<LotusJson<Address>>,
61 #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
62 pub fields: BTreeMap<String, Vec<ActorEventBlock>>,
63 #[serde(default, skip_serializing_if = "Option::is_none")]
64 pub from_height: Option<ChainEpoch>,
65 #[serde(default, skip_serializing_if = "Option::is_none")]
66 pub to_height: Option<ChainEpoch>,
67 #[serde(default, skip_serializing_if = "Option::is_none")]
68 pub tipset_key: Option<LotusJson<TipsetKey>>,
69}
70
71#[derive(Clone, JsonSchema, Serialize, Deserialize)]
72pub struct ActorEventBlock {
73 pub codec: u64,
74 pub value: LotusJson<Vec<u8>>,
75}
76
77#[derive(Debug, PartialEq, Clone, JsonSchema, Serialize, Deserialize)]
78#[serde(rename_all = "camelCase")]
79pub struct ActorEvent {
80 pub entries: Vec<EventEntry>,
81 pub emitter: LotusJson<Address>,
82 pub reverted: bool,
83 pub height: ChainEpoch,
84 pub tipset_key: LotusJson<TipsetKey>,
85 pub msg_cid: LotusJson<Cid>,
86}
87
88lotus_json_with_self! {
89 ActorEvent,
90 ActorEventFilter
91}
92
93impl From<CollectedEvent> for ActorEvent {
94 fn from(event: CollectedEvent) -> Self {
95 ActorEvent {
96 entries: event.entries,
97 emitter: LotusJson(event.emitter_addr),
98 reverted: event.reverted,
99 height: event.height,
100 tipset_key: LotusJson(event.tipset_key),
101 msg_cid: LotusJson(event.msg_cid),
102 }
103 }
104}