Skip to content

Commit 4c63248

Browse files
authored
Implement poll-based event subscription for Starknet (#221)
* Add receipt block info to MessageResponse * Managed to poll SendPacket events successfully * Add StarknetEventEncoding field * Implement HasEncoding<AsStarknetEvent> for StarknetChain * Implementing CanPollStarknetIbcEvents * Finish draft for CanPollStarknetIbcEvents * Define CanQueryBlockEvents component * Drafting Starknet event stream * Done initial implementation of CanCreateStarknetSubscription * Multiplex event subscription * Add wait and retry block events querier * Implement CanQueryBlockEvents and CanCreateStarknetSubscription for StarknetChain * Fix clippy * Remove sleep in test * Add address argument for get_block_events * Rename providers * Implement StarknetEvent::from_emitted_event * Implement GetStarknetBlockEvents
1 parent 0a14290 commit 4c63248

File tree

27 files changed

+537
-37
lines changed

27 files changed

+537
-37
lines changed

relayer/Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub struct AsStarknetEvent;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod as_felt;
2+
pub mod as_starknet_event;
23
pub mod nat;

relayer/crates/starknet-chain-components/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ cgp = { workspace = true }
1414
hermes-relayer-components = { workspace = true }
1515
hermes-test-components = { workspace = true }
1616
hermes-runtime-components = { workspace = true }
17+
hermes-async-runtime-components = { workspace = true }
1718
hermes-chain-components = { workspace = true }
1819
hermes-chain-type-components = { workspace = true }
1920
hermes-encoding-components = { workspace = true }
@@ -35,4 +36,5 @@ serde = { workspace = true }
3536
serde_json = { workspace = true }
3637
starknet = { workspace = true }
3738
tonic = { workspace = true }
39+
futures = { workspace = true }
3840
crypto-bigint = "0.5.5"

relayer/crates/starknet-chain-components/src/components/chain.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ use crate::impls::payload_builders::create_client::BuildStarknetCreateClientPayl
7373
use crate::impls::payload_builders::update_client::BuildStarknetUpdateClientPayload;
7474
use crate::impls::queries::ack_commitment::QueryStarknetAckCommitment;
7575
use crate::impls::queries::balance::QueryStarknetWalletBalance;
76+
use crate::impls::queries::block_events::default::DefaultQueryBlockEvents;
7677
use crate::impls::queries::channel_end::QueryChannelEndFromStarknet;
7778
use crate::impls::queries::client_state::QueryCometClientState;
7879
use crate::impls::queries::connection_end::QueryConnectionEndFromStarknet;
@@ -111,6 +112,7 @@ pub use crate::traits::contract::invoke::ContractInvokerComponent;
111112
pub use crate::traits::contract::message::InvokeContractMessageBuilderComponent;
112113
pub use crate::traits::messages::transfer::TransferTokenMessageBuilderComponent;
113114
pub use crate::traits::queries::address::ContractAddressQuerierComponent;
115+
use crate::traits::queries::block_events::BlockEventsQuerierComponent;
114116
pub use crate::traits::queries::token_balance::TokenBalanceQuerierComponent;
115117
pub use crate::traits::transfer::TokenTransferComponent;
116118
pub use crate::traits::types::blob::BlobTypeComponent;
@@ -229,6 +231,8 @@ cgp_preset! {
229231
ReadPacketSrcStarknetFields,
230232
ChainStatusQuerierComponent:
231233
QueryStarknetChainStatus,
234+
BlockEventsQuerierComponent:
235+
DefaultQueryBlockEvents,
232236
MessageSenderComponent:
233237
SendCallMessages,
234238
TxSubmitterComponent:

relayer/crates/starknet-chain-components/src/components/starknet_to_cosmos.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,5 @@ cgp_preset! {
9494
PacketDstChannelIdGetterComponent,
9595
]:
9696
ReadPacketDstStarknetFields,
97-
9897
}
9998
}

relayer/crates/starknet-chain-components/src/impls/encoding/option.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,16 @@ where
2121
) -> Result<Option<Value>, Encoding::Error> {
2222
let class_hashes = encoding.get_field(PhantomData);
2323

24-
if class_hashes.contains(&event.class_hash) {
25-
let value = encoding.decode(event)?;
26-
Ok(Some(value))
27-
} else {
28-
Ok(None)
24+
match &event.class_hash {
25+
Some(class_hash) => {
26+
if class_hashes.contains(class_hash) {
27+
let value = encoding.decode(event)?;
28+
Ok(Some(value))
29+
} else {
30+
Ok(None)
31+
}
32+
}
33+
None => Ok(None),
2934
}
3035
}
3136
}

relayer/crates/starknet-chain-components/src/impls/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub mod queries;
1414
pub mod send_message;
1515
pub mod starknet_to_cosmos;
1616
pub mod submit_tx;
17+
pub mod subscription;
1718
pub mod transfer;
1819
pub mod tx_response;
1920
pub mod types;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use cgp::prelude::CanRaiseAsyncError;
2+
use hermes_chain_components::traits::queries::chain_status::CanQueryChainHeight;
3+
use hermes_chain_components::traits::types::event::HasEventType;
4+
use hermes_chain_components::traits::types::height::HasHeightType;
5+
use hermes_chain_type_components::traits::types::address::HasAddressType;
6+
use hermes_runtime_components::traits::runtime::HasRuntime;
7+
use hermes_runtime_components::traits::sleep::CanSleep;
8+
use starknet::core::types::Felt;
9+
use starknet::providers::ProviderError;
10+
11+
use crate::impls::queries::block_events::get::GetStarknetBlockEvents;
12+
use crate::impls::queries::block_events::retry::RetryQueryBlockEvents;
13+
use crate::impls::queries::block_events::wait::WaitBlockHeightAndQueryEvents;
14+
use crate::traits::provider::HasStarknetProvider;
15+
use crate::traits::queries::block_events::BlockEventsQuerier;
16+
use crate::types::event::StarknetEvent;
17+
18+
pub struct DefaultQueryBlockEvents;
19+
20+
impl<Chain> BlockEventsQuerier<Chain> for DefaultQueryBlockEvents
21+
where
22+
Chain: HasRuntime
23+
+ HasHeightType<Height = u64>
24+
+ HasEventType<Event = StarknetEvent>
25+
+ HasAddressType<Address = Felt>
26+
+ HasStarknetProvider
27+
+ CanQueryChainHeight
28+
+ CanRaiseAsyncError<ProviderError>,
29+
Chain::Runtime: CanSleep,
30+
{
31+
async fn query_block_events(
32+
chain: &Chain,
33+
height: &Chain::Height,
34+
address: &Chain::Address,
35+
) -> Result<Vec<Chain::Event>, Chain::Error> {
36+
<RetryQueryBlockEvents<WaitBlockHeightAndQueryEvents<GetStarknetBlockEvents>>>::query_block_events(chain, height, address).await
37+
}
38+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use cgp::prelude::*;
2+
use hermes_chain_components::traits::types::event::HasEventType;
3+
use hermes_chain_components::traits::types::height::HasHeightType;
4+
use hermes_chain_type_components::traits::types::address::HasAddressType;
5+
use starknet::core::types::{BlockId, EventFilter, Felt};
6+
use starknet::providers::{Provider, ProviderError};
7+
8+
use crate::traits::provider::HasStarknetProvider;
9+
use crate::traits::queries::block_events::BlockEventsQuerier;
10+
use crate::types::event::StarknetEvent;
11+
12+
pub struct GetStarknetBlockEvents;
13+
14+
impl<Chain> BlockEventsQuerier<Chain> for GetStarknetBlockEvents
15+
where
16+
Chain: HasHeightType<Height = u64>
17+
+ HasEventType<Event = StarknetEvent>
18+
+ HasAddressType<Address = Felt>
19+
+ HasStarknetProvider
20+
+ CanRaiseAsyncError<ProviderError>,
21+
{
22+
async fn query_block_events(
23+
chain: &Chain,
24+
height: &u64,
25+
address: &Felt,
26+
) -> Result<Vec<StarknetEvent>, Chain::Error> {
27+
let provider = chain.provider();
28+
29+
let raw_events = provider
30+
.get_events(
31+
EventFilter {
32+
from_block: Some(BlockId::Number(*height)),
33+
to_block: Some(BlockId::Number(*height)),
34+
address: Some(*address),
35+
keys: None,
36+
},
37+
None,
38+
1000,
39+
)
40+
.await
41+
.map_err(Chain::raise_error)?;
42+
43+
let events = raw_events
44+
.events
45+
.into_iter()
46+
.map(StarknetEvent::from)
47+
.collect();
48+
49+
Ok(events)
50+
}
51+
}

0 commit comments

Comments
 (0)