Skip to content

Commit

Permalink
Add query client state CLI (#148)
Browse files Browse the repository at this point in the history
* Implement initial StarknetBuilder and StarknetBuildComponents

* taplo fmt

* Add query client state CLI

* Implement BuilderLoader for StarknetAppComponents

* Add query client state CLI for Starknet to Cosmos

* Fix query client-state CLI name

* clippy fix

* Use Starknet chain config from Starknet relayer config instead of creating a new one
  • Loading branch information
ljoss17 authored Dec 18, 2024
1 parent 1a12e0b commit c47d9c3
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 2 deletions.
2 changes: 2 additions & 0 deletions relayer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions relayer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cgp = { version = "0.2.0" }
cgp-error-eyre = { version = "0.2.0" }

starknet = { version = "0.11.0" }
starknet-types-core = { version = "0.1.7" }
url = { version = "2.4.0" }
eyre = { version = "0.6.12" }
tokio = { version = "1.38" }
Expand Down
30 changes: 30 additions & 0 deletions relayer/crates/starknet-chain-components/src/types/client_id.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use core::fmt::{Display, Formatter, Result as FmtResult};
use core::str::FromStr;

use cgp::core::component::UseContext;
use cgp::prelude::*;
use hermes_encoding_components::impls::encode_mut::combine::CombineEncoders;
Expand Down Expand Up @@ -36,3 +39,30 @@ impl Transformer for EncodeClientId {
}
}
}

impl Display for ClientId {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
// TODO: Verify that the Display is correct
write!(f, "{}-{}", self.client_type, self.sequence)
}
}

impl FromStr for ClientId {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
// TODO: Verify that the parsing from str is correct
let values: Vec<&str> = s.split('-').collect();
let felt_str = values.first().ok_or_else(|| format!("client ID doesn't have correct format, expecting `<client_type>-<sequence>, got `{s}`"))?;
let sequence_str = values.get(1).ok_or_else(|| format!("client ID doesn't have correct format, expecting `<client_type>-<sequence>, got `{s}`"))?;
let client_type = Felt::from_str(felt_str)
.map_err(|e| format!("failed to parse {felt_str} to Felt. Cause: {e}"))?;
let sequence = sequence_str
.parse::<u64>()
.map_err(|e| format!("failed to parse {felt_str} to Felt. Cause: {e}"))?;
Ok(Self {
client_type,
sequence,
})
}
}
4 changes: 3 additions & 1 deletion relayer/crates/starknet-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ hermes-starknet-integration-tests = { workspace = true }
hermes-starknet-test-components = { workspace = true }
hermes-test-components = { workspace = true }

ibc = { workspace = true }
ibc = { workspace = true }
starknet = { workspace = true }
starknet-types-core = { workspace = true }

serde = { workspace = true, features = [ "derive" ] }
clap = { workspace = true, features = [ "derive" ] }
Expand Down
1 change: 1 addition & 0 deletions relayer/crates/starknet-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod query;
1 change: 1 addition & 0 deletions relayer/crates/starknet-cli/src/commands/query/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod subcommand;
23 changes: 23 additions & 0 deletions relayer/crates/starknet-cli/src/commands/query/subcommand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use hermes_cli_components::impls::commands::queries::client_state::QueryClientStateArgs;
use hermes_cli_components::traits::command::{CanRunCommand, CommandRunner};

#[derive(Debug, clap::Subcommand)]
pub enum QuerySubCommand {
ClientState(QueryClientStateArgs),
}

pub struct RunQuerySubCommand;

impl<App> CommandRunner<App, QuerySubCommand> for RunQuerySubCommand
where
App: CanRunCommand<QueryClientStateArgs>,
{
async fn run_command(
app: &App,
subcommand: &QuerySubCommand,
) -> Result<App::Output, App::Error> {
match subcommand {
QuerySubCommand::ClientState(args) => app.run_command(args).await,
}
}
}
43 changes: 43 additions & 0 deletions relayer/crates/starknet-cli/src/contexts/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,20 @@ use cgp::core::field::impls::use_field::WithField;
use cgp::core::types::impls::WithType;
use cgp::prelude::*;
use hermes_cli_components::impls::commands::bootstrap::chain::RunBootstrapChainCommand;
use hermes_cli_components::impls::commands::queries::client_state::{
QueryClientStateArgs, RunQueryClientStateCommand,
};
use hermes_cli_components::impls::config::get_config_path::GetDefaultConfigField;
use hermes_cli_components::impls::config::load_toml_config::LoadTomlConfig;
use hermes_cli_components::impls::config::save_toml_config::WriteTomlConfig;
use hermes_cli_components::impls::parse::string::{ParseFromOptionalString, ParseFromString};
use hermes_cli_components::traits::any_counterparty::ProvideAnyCounterparty;
use hermes_cli_components::traits::bootstrap::{
BootstrapLoaderComponent, BootstrapTypeComponent, CanLoadBootstrap,
};
use hermes_cli_components::traits::build::{
BuilderLoaderComponent, BuilderTypeComponent, CanLoadBuilder,
};
use hermes_cli_components::traits::command::{CanRunCommand, CommandRunnerComponent};
use hermes_cli_components::traits::config::config_path::{
ConfigPathGetterComponent, HasConfigPath,
Expand All @@ -21,7 +29,9 @@ use hermes_cli_components::traits::config::write_config::{CanWriteConfig, Config
use hermes_cli_components::traits::output::{
CanProduceOutput, OutputProducer, OutputTypeComponent,
};
use hermes_cli_components::traits::parse::ArgParserComponent;
use hermes_cli_components::traits::types::config::ConfigTypeComponent;
use hermes_cosmos_relayer::contexts::chain::CosmosChain;
use hermes_error::traits::wrap::CanWrapError;
use hermes_error::types::HermesError;
use hermes_logger::ProvideHermesLogger;
Expand All @@ -36,13 +46,18 @@ use hermes_runtime_components::traits::runtime::{
use hermes_starknet_chain_components::impls::types::config::{
StarknetChainConfig, StarknetRelayerConfig,
};
use hermes_starknet_chain_components::types::client_id::ClientId;
use hermes_starknet_integration_tests::contexts::bootstrap::StarknetBootstrap;
use hermes_starknet_integration_tests::contexts::chain_driver::StarknetChainDriver;
use hermes_starknet_relayer::contexts::builder::StarknetBuilder;
use hermes_test_components::chain_driver::traits::config::ConfigUpdater;
use starknet::core::types::Felt;
use toml::to_string_pretty;

use crate::commands::query::subcommand::{QuerySubCommand, RunQuerySubCommand};
use crate::impls::bootstrap::starknet_chain::{BootstrapStarknetChainArgs, LoadStarknetBootstrap};
use crate::impls::bootstrap::subcommand::{BootstrapSubCommand, RunBootstrapSubCommand};
use crate::impls::build::LoadStarknetBuilder;
use crate::impls::error::ProvideCliError;
use crate::impls::subcommand::{AllSubCommands, RunAllSubCommand};

Expand Down Expand Up @@ -96,17 +111,42 @@ delegate_components! {
WriteTomlConfig,
CommandRunnerComponent:
UseDelegate<StarknetCommandRunnerComponents>,
BuilderLoaderComponent:
LoadStarknetBuilder,
BuilderTypeComponent:
WithType<StarknetBuilder>,
ArgParserComponent:
UseDelegate<StarknetParserComponents>,
}
}

delegate_components! {
StarknetParserComponents {
(QueryClientStateArgs, symbol!("chain_id")): ParseFromString<Felt>,
(QueryClientStateArgs, symbol!("client_id")): ParseFromString<ClientId>,
(QueryClientStateArgs, symbol!("height")): ParseFromOptionalString<u64>,
}
}

delegate_components! {
StarknetCommandRunnerComponents {
AllSubCommands: RunAllSubCommand,
BootstrapSubCommand: RunBootstrapSubCommand,

QuerySubCommand: RunQuerySubCommand,
QueryClientStateArgs: RunQueryClientStateCommand,

BootstrapStarknetChainArgs: RunBootstrapChainCommand<UpdateStarknetConfig>,
}
}

impl<App> ProvideAnyCounterparty<App> for StarknetAppComponents
where
App: Async,
{
type AnyCounterparty = CosmosChain;
}

impl<Value> OutputProducer<StarknetApp, Value> for StarknetAppComponents {
fn produce_output(_app: &StarknetApp, _value: Value) {}
}
Expand Down Expand Up @@ -153,6 +193,9 @@ pub trait CanUseStarknetApp:
+ CanRunCommand<AllSubCommands>
+ CanRunCommand<BootstrapSubCommand>
+ CanRunCommand<BootstrapStarknetChainArgs>
+ CanLoadBuilder
+ CanRunCommand<QuerySubCommand>
+ CanRunCommand<QueryClientStateArgs>
{
}

Expand Down
45 changes: 45 additions & 0 deletions relayer/crates/starknet-cli/src/impls/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use cgp::prelude::CanRaiseError;
use hermes_cli_components::traits::build::{BuilderLoader, HasBuilderType};
use hermes_cli_components::traits::config::load_config::CanLoadConfig;
use hermes_cli_components::traits::types::config::HasConfigType;
use hermes_cosmos_relayer::contexts::build::CosmosBuilder;
use hermes_runtime::types::runtime::HermesRuntime;
use hermes_runtime_components::traits::runtime::HasRuntime;
use hermes_starknet_chain_components::impls::types::config::StarknetRelayerConfig;
use hermes_starknet_relayer::contexts::builder::StarknetBuilder;

pub struct LoadStarknetBuilder;

impl<App> BuilderLoader<App> for LoadStarknetBuilder
where
App: HasBuilderType<Builder = StarknetBuilder>
+ HasConfigType<Config = StarknetRelayerConfig>
+ HasRuntime<Runtime = HermesRuntime>
+ CanLoadConfig
+ CanRaiseError<&'static str>,
{
async fn load_builder(app: &App) -> Result<App::Builder, App::Error> {
let runtime = app.runtime().clone();
let config = app.load_config().await?;
let cosmos_chain_config = config.cosmos_chain_config.ok_or_else(|| {
App::raise_error("missing Cosmos chain config in Starknet relayer config")
})?;

let cosmos_builder = CosmosBuilder::new(
vec![cosmos_chain_config],
runtime.clone(),
Default::default(),
Default::default(),
Default::default(),
Default::default(),
);

let starknet_chain_config = config.starknet_chain_config.ok_or_else(|| {
App::raise_error("missing Starknet chain config in Starknet relayer config")
})?;

let builder = StarknetBuilder::new(cosmos_builder, runtime, starknet_chain_config);

Ok(builder)
}
}
4 changes: 4 additions & 0 deletions relayer/crates/starknet-cli/src/impls/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::convert::Infallible;
use core::num::ParseIntError;

use cgp::core::component::UseDelegate;
use cgp::core::error::{ErrorRaiser, ErrorRaiserComponent, ErrorTypeComponent};
Expand All @@ -14,6 +15,7 @@ use hermes_error::traits::wrap::WrapError;
use hermes_error::types::Error;
use hermes_relayer_components::error::traits::retry::RetryableErrorComponent;
use hermes_runtime::types::error::TokioRuntimeError;
use starknet_types_core::felt::FromStrError;

pub struct ProvideCliError;

Expand Down Expand Up @@ -46,6 +48,8 @@ delegate_components! {
Infallible: HandleInfallible,
[
Report,
FromStrError,
ParseIntError,
TokioRuntimeError,
toml::de::Error,
toml::ser::Error,
Expand Down
1 change: 1 addition & 0 deletions relayer/crates/starknet-cli/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod bootstrap;
pub mod build;
pub mod error;
pub mod subcommand;
6 changes: 5 additions & 1 deletion relayer/crates/starknet-cli/src/impls/subcommand.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
use hermes_cli_components::traits::command::{CanRunCommand, CommandRunner};

use crate::commands::query::subcommand::QuerySubCommand;
use crate::impls::bootstrap::subcommand::BootstrapSubCommand;

#[derive(Debug, clap::Subcommand)]
pub enum AllSubCommands {
#[clap(subcommand)]
Bootstrap(BootstrapSubCommand),
#[clap(subcommand)]
Query(QuerySubCommand),
}

pub struct RunAllSubCommand;

impl<App> CommandRunner<App, AllSubCommands> for RunAllSubCommand
where
App: CanRunCommand<BootstrapSubCommand>,
App: CanRunCommand<BootstrapSubCommand> + CanRunCommand<QuerySubCommand>,
{
async fn run_command(
app: &App,
subcommand: &AllSubCommands,
) -> Result<App::Output, App::Error> {
match subcommand {
AllSubCommands::Bootstrap(args) => app.run_command(args).await,
AllSubCommands::Query(args) => app.run_command(args).await,
}
}
}
1 change: 1 addition & 0 deletions relayer/crates/starknet-cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
extern crate alloc;

pub mod commands;
pub mod contexts;
pub mod impls;

0 comments on commit c47d9c3

Please sign in to comment.