Skip to content

Commit

Permalink
initial refactor, blockheight and nonce commands
Browse files Browse the repository at this point in the history
  • Loading branch information
sambukowski committed Sep 25, 2024
1 parent 0e889ef commit 2c34ae9
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 4 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

4 changes: 3 additions & 1 deletion crates/astria-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ name = "astria-cli"

[dependencies]
color-eyre = "0.6"
home = "0.5"
toml = "0.7"

astria-bridge-contracts = { path = "../astria-bridge-contracts" }
astria-core = { path = "../astria-core", features = ["serde"] }

clap = { workspace = true, features = ["derive", "env"] }
clap = { workspace = true, features = ["derive", "env", "string"] }
ethers = { workspace = true, features = ["ws"] }
hex = { workspace = true }
ibc-types = { workspace = true }
Expand Down
50 changes: 50 additions & 0 deletions crates/astria-cli/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::{
collections::HashMap,
fs,
path::Path,
};

use color_eyre::eyre;
use serde::{
Deserialize,
Serialize,
};
use toml;

pub const DEFAULT_SEQUENCER_URL: &str = "https://rpc.sequencer.dawn-0.astria.org";

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct NetworkConfig {
pub sequencer_chain_id: String,
pub sequencer_url: String,
pub asset: String,
pub fee_asset: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct SequencerNetworksConfig {
networks: HashMap<String, NetworkConfig>,
}

impl SequencerNetworksConfig {
/// Load the config from a file
pub fn load<P: AsRef<Path>>(path: P) -> eyre::Result<Self> {
let toml_str = fs::read_to_string(path)?;
let config: SequencerNetworksConfig = toml::from_str(&toml_str)?;
return Ok(config);
}

/// Get the network config for the selected network
pub fn get_network(&self, network: &String) -> eyre::Result<&NetworkConfig> {
if let Some(network_config) = self.networks.get(network) {
Ok(network_config)
} else {
let keys = self.networks.keys().collect::<Vec<&String>>();
Err(eyre::eyre!(
"'{}' not found: Expected one of the following: {:?}",
network,
keys
))
}
}
}
1 change: 1 addition & 0 deletions crates/astria-cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod cli;
pub mod commands;
pub mod config;
22 changes: 19 additions & 3 deletions crates/astria-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,36 @@ use astria_cli::{
cli::Cli,
commands,
};
use clap::Command;
use color_eyre::eyre;

mod query;

#[tokio::main]
async fn main() -> ExitCode {
tracing_subscriber::fmt()
.pretty()
.with_writer(std::io::stderr)
.init();

if let Err(err) = run().await {
eprintln!("{err:?}");
return ExitCode::FAILURE;
let matches = Command::new("astria-cli")
.subcommand(query::command())
// .subcommand(command2::command(&config))
.get_matches();

match matches.subcommand() {
Some(("query", args)) => query::run(args).await.expect("Could not run query command"),
// Some(("command2", sub_matches)) => command2::run(sub_matches, &config),
_ => {
return ExitCode::FAILURE;
}
}

// if let Err(err) = run().await {
// eprintln!("{err:?}");
// return ExitCode::FAILURE;
// }

ExitCode::SUCCESS
}

Expand Down
109 changes: 109 additions & 0 deletions crates/astria-cli/src/query/blockheight.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use astria_cli::config::{
SequencerNetworksConfig,
DEFAULT_SEQUENCER_URL,
};
use astria_sequencer_client::{
Client,
HttpClient,
};
use clap::{
builder::Str,
Arg,
ArgAction,
ArgMatches,
Command,
};
use color_eyre::{
eyre,
eyre::Context,
};
use home::home_dir;

pub(crate) fn command() -> Command {
let mut path = home_dir().expect("Could not determine the home directory.");
path.push(".astria");
path.push("sequencer-networks-config.toml");

Command::new("blockheight")
.about("Get the current blockheight from the sequencer")
.arg(
// flag input
Arg::new("sequencer-url")
.long("sequencer-url")
.help("URL of the sequencer")
.action(ArgAction::Set)
.default_value(DEFAULT_SEQUENCER_URL)
.env("SEQUENCER_URL"),
)
.arg(
// count bool flag
Arg::new("verbose")
.short('v')
.long("verbose")
.action(ArgAction::Count)
.help("Print debug information verbosely"),
)
.arg(
// flag input
Arg::new("network")
.long("network")
.action(ArgAction::Set)
.help("Select a network config preset"),
)
.arg(
// flag input
Arg::new("config")
.long("config")
.action(ArgAction::Set)
.help("Specify a network config file")
.default_value(Str::from(path.display().to_string())),
)
}

pub(crate) async fn run(matches: &ArgMatches) -> eyre::Result<()> {
// load and parse the config file
let config: SequencerNetworksConfig = {
let config_path = matches.get_one::<String>("config");
if let Some(path) = config_path {
SequencerNetworksConfig::load(path).expect("Could not load config file")
} else {
let mut path = home_dir().expect("Could not determine the home directory.");
path.push(".astria");
path.push("sequencer-networks-config.toml");
SequencerNetworksConfig::load(path).expect("Could not load config file")
}
};

// get verbosity cound (currently unused)
let verbose = matches.get_count("verbose");
println!("verbose count: {:?}", verbose);

// get the chosen network config
let network = matches.get_one::<String>("network");
println!("network: {:?}", network);

// get the correct sequencer_url based on all inputs
let sequenecer_url = if let Some(chosen_network) = network {
let net_config = config
.get_network(chosen_network)
.expect("network not found");
net_config.sequencer_url.clone()
} else {
let seq_url = matches.get_one::<String>("sequencer-url");
seq_url.unwrap().clone()
};

// submit the query to the sequencer
let sequencer_client = HttpClient::new(sequenecer_url.as_str())
.wrap_err("failed constructing http sequencer client")?;

let res = sequencer_client
.latest_block()
.await
.wrap_err("failed to get cometbft block")?;

println!("Block Height:");
println!(" {}", res.block.header.height);

Ok(())
}
24 changes: 24 additions & 0 deletions crates/astria-cli/src/query/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
mod blockheight;
mod nonce;

use clap::{
ArgMatches,
Command,
};
use color_eyre::eyre;

pub(crate) fn command() -> Command {
Command::new("query")
.about("Query the sequencer")
.subcommand(blockheight::command())
.subcommand(nonce::command())
}

pub(crate) async fn run(matches: &ArgMatches) -> eyre::Result<()> {
match matches.subcommand() {
Some(("blockheight", args)) => blockheight::run(args).await,
Some(("nonce", args)) => nonce::run(args).await,
// Some(("subcommand2", sub_matches)) => subcommand2::run(sub_matches, config),
_ => Err(eyre::eyre!("Unknown subcommand")),
}
}
125 changes: 125 additions & 0 deletions crates/astria-cli/src/query/nonce.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use astria_cli::config::{
SequencerNetworksConfig,
DEFAULT_SEQUENCER_URL,
};
use astria_core::primitive::v1::Address;
use astria_sequencer_client::{
HttpClient,
SequencerClientExt,
};
use clap::{
builder::Str,
Arg,
ArgAction,
ArgMatches,
Command,
};
use color_eyre::{
eyre,
eyre::Context,
};
use home::home_dir;

pub(crate) fn command() -> Command {
// Create default path to the config file
let mut path = home_dir().expect("Could not determine the home directory.");
path.push(".astria");
path.push("sequencer-networks-config.toml");

Command::new("nonce")
.about("Get the nonce of an account")
.arg(
// flag input
Arg::new("sequencer-url")
.long("sequencer-url")
.help("URL of the sequencer")
.action(ArgAction::Set)
.default_value(DEFAULT_SEQUENCER_URL)
.env("SEQUENCER_URL"),
)
.arg(
// count bool flag
Arg::new("verbose")
.short('v')
.long("verbose")
.action(ArgAction::Count)
.help("Print debug information verbosely"),
)
.arg(
// flag input
Arg::new("network")
.long("network")
.action(ArgAction::Set)
.help("Select a network config preset"),
)
.arg(
// flag input
Arg::new("config")
.long("config")
.action(ArgAction::Set)
.help("Specify a network config file")
.default_value(Str::from(path.display().to_string())),
)
.arg(
// postional argument
Arg::new("address")
.action(ArgAction::Set)
.help("Specify a network config file")
.required(true),
)
}

pub(crate) async fn run(matches: &ArgMatches) -> eyre::Result<()> {
// load and parse the config file
let config: SequencerNetworksConfig = {
let config_path = matches.get_one::<String>("config");
if let Some(path) = config_path {
SequencerNetworksConfig::load(path).expect("Could not load config file")
} else {
let mut path = home_dir().expect("Could not determine the home directory.");
path.push(".astria");
path.push("sequencer-networks-config.toml");
SequencerNetworksConfig::load(path).expect("Could not load config file")
}
};

// get verbosity cound (currently unused)
let verbose = matches.get_count("verbose");
println!("verbose count: {:?}", verbose);

// get the chosen network config
let network = matches.get_one::<String>("network");
println!("network: {:?}", network);

// parse the input address
let address = matches
.get_one::<String>("address")
.expect("could not unwrap address");
println!("network: {:?}", address);
let address: Address = address.as_str().parse()?;

// get the correct sequencer_url based on all inputs
let sequenecer_url = if let Some(chosen_network) = network {
let net_config = config
.get_network(chosen_network)
.expect("network not found");
net_config.sequencer_url.clone()
} else {
let seq_url = matches.get_one::<String>("sequencer-url");
seq_url.unwrap().clone()
};

// submit the query to the sequencer
let sequencer_client = HttpClient::new(sequenecer_url.as_str())
.wrap_err("failed constructing http sequencer client")?;

let res = sequencer_client
.get_latest_nonce(address)
.await
.wrap_err("failed to get nonce")?;

println!("Nonce for address {}", address);
println!(" {} at height {}", res.nonce, res.height);

Ok(())
}
4 changes: 4 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,7 @@ _lint-proto:
buf breaking proto/sequencerblockapis --against 'buf.build/astria/sequencerblock-apis'
buf breaking proto/protocolapis --against 'buf.build/astria/protocol-apis'
buf breaking proto/composerapis --against 'buf.build/astria/composer-apis'

defaultargs := ''
cli *args=defaultargs:
cargo run -p astria-cli -- {{args}}

0 comments on commit 2c34ae9

Please sign in to comment.