Skip to content

Commit

Permalink
Add debug CLI methods (#1254)
Browse files Browse the repository at this point in the history
  • Loading branch information
neekolas authored Nov 12, 2024
1 parent d750ad7 commit f37234a
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 30 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.

30 changes: 19 additions & 11 deletions deny.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[advisories]
ignore = [
{ id = "RUSTSEC-2024-0384", reason = "migration to alloy is underway which will resolve this advisory" },
]

# This rustsec can be added to ignore list if using mls `test_utils` for tests
# {
# id="RUSTSEC-2021-0139",
# reason="The maintainer has advised that this crate is deprecated and will not receive any maintenance. https://rustsec.org/advisories/RUSTSEC-2021-0139.html"
# },
ignore = []

[licenses]
allow = [
"Apache-2.0",
Expand All @@ -17,21 +19,27 @@ allow = [
"GPL-3.0",
"CC0-1.0",
"BSD-2-Clause",
"Unicode-3.0"
"Unicode-3.0",
]
confidence-threshold = 1.0

exceptions = [
{ allow = ["OpenSSL"], name = "ring", version = "*" },
{ allow = ["Unlicense"], name = "pharos", version = "0.5.3" },
{ allow = ["Unlicense"], name = "async_io_stream", version = "0.3.3" },
{ allow = ["Unlicense"], name = "ws_stream_wasm", version = "0.7.4" },
{ allow = [
"OpenSSL",
], name = "ring", version = "*" },
{ allow = [
"Unlicense",
], name = "pharos", version = "0.5.3" },
{ allow = [
"Unlicense",
], name = "async_io_stream", version = "0.3.3" },
{ allow = [
"Unlicense",
], name = "ws_stream_wasm", version = "0.7.4" },
]

[[licenses.clarify]]
expression = "MIT AND ISC AND OpenSSL"
license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }]
name = "ring"
version = "*"
expression = "MIT AND ISC AND OpenSSL"
license-files = [
{ path = "LICENSE", hash = 0xbd0eed23 }
]
22 changes: 15 additions & 7 deletions examples/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,43 @@
default-run = "xmtp_cli"
edition = "2021"
keywords = ["xmtp", "messaging", "web3", "group-chat"]
license.workspace = true
name = "xmtp_cli"
readme = "README.md"
repository = "https://github.com/xmtp/libxmtp"
version.workspace = true
license.workspace = true

[[bin]]
name = "xmtp_cli"
path = "cli-client.rs"

[dependencies]
tracing = { workspace = true, features = ["valuable"] }
tracing-subscriber = { workspace = true, features = ["json", "valuable", "env-filter", "ansi", "chrono"] }
valuable = { version = "0.1", features = ["derive"] }
valuable-serde = "0.1"
chrono.workspace = true
clap = { version = "4.4.6", features = ["derive"] }
color-eyre = "0.6"
ethers.workspace = true
futures.workspace = true
hex.workspace = true
openmls = { workspace = true }
owo-colors = "4.1"
prost.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
thiserror.workspace = true
timeago = "0.4.1"
tokio.workspace = true
tracing = { workspace = true, features = ["valuable"] }
tracing-subscriber = { workspace = true, features = [
"json",
"valuable",
"env-filter",
"ansi",
"chrono",
] }
valuable = { version = "0.1", features = ["derive"] }
valuable-serde = "0.1"
xmtp_api_grpc = { path = "../../xmtp_api_grpc" }
xmtp_cryptography = { path = "../../xmtp_cryptography" }
xmtp_id = { path = "../../xmtp_id" }
xmtp_mls = { path = "../../xmtp_mls" }
xmtp_proto = { path = "../../xmtp_proto", features = ["proto_full"] }
color-eyre = "0.6"
owo-colors = "4.1"
46 changes: 34 additions & 12 deletions examples/cli/cli-client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
XLI is a Commandline client using XMTPv3.
*/

mod debug;
mod pretty;
mod serializable;

Expand All @@ -12,6 +13,7 @@ use std::{fs, path::PathBuf, time::Duration};
use crate::serializable::{SerializableGroup, SerializableMessage};
use clap::{Parser, Subcommand, ValueEnum};
use color_eyre::eyre::eyre;
use debug::DebugCommands;
use ethers::signers::{coins_bip39::English, LocalWallet, MnemonicBuilder};
use futures::future::join_all;
use owo_colors::OwoColorize;
Expand Down Expand Up @@ -61,6 +63,15 @@ extern crate tracing;
type Client = xmtp_mls::client::Client<Box<dyn XmtpApi>>;
type MlsGroup = xmtp_mls::groups::MlsGroup<Client>;

#[derive(clap::ValueEnum, Clone, Default, Debug, serde::Serialize, PartialEq)]
#[serde(rename_all = "kebab-case")]
enum Env {
#[default]
Local,
Dev,
Production,
}

/// A fictional versioning CLI
#[derive(Debug, Parser)] // requires `derive` feature
#[command(name = "xli")]
Expand All @@ -71,8 +82,8 @@ struct Cli {
/// Sets a custom config file
#[arg(long, value_name = "FILE", global = true)]
db: Option<PathBuf>,
#[clap(long, default_value_t = false)]
local: bool,
#[clap(long, value_enum, default_value_t)]
env: Env,
#[clap(long, default_value_t = false)]
json: bool,
#[clap(long, default_value_t = false)]
Expand Down Expand Up @@ -130,6 +141,8 @@ enum Commands {
/// Information about the account that owns the DB
Info {},
Clear {},
#[command(subcommand)]
Debug(DebugCommands),
}

#[derive(Debug, Error)]
Expand Down Expand Up @@ -211,27 +224,33 @@ async fn main() -> color_eyre::eyre::Result<()> {
}
info!("Starting CLI Client....");

let grpc = match (cli.testnet, cli.local) {
(true, true) => Box::new(
let grpc: Box<dyn XmtpApi> = match (cli.testnet, &cli.env) {
(true, Env::Local) => Box::new(
ClientV4::create("http://localhost:5050".into(), false)
.await
.unwrap(),
) as Box<dyn XmtpApi>,
(true, false) => Box::new(
),
(true, Env::Dev) => Box::new(
ClientV4::create("https://grpc.testnet.xmtp.network:443".into(), true)
.await
.unwrap(),
) as Box<dyn XmtpApi>,
(false, true) => Box::new(
),
(false, Env::Local) => Box::new(
ClientV3::create("http://localhost:5556".into(), false)
.await
.unwrap(),
) as Box<dyn XmtpApi>,
(false, false) => Box::new(
),
(false, Env::Dev) => Box::new(
ClientV3::create("https://grpc.dev.xmtp.network:443".into(), true)
.await
.unwrap(),
) as Box<dyn XmtpApi>,
),
(false, Env::Production) => Box::new(
ClientV3::create("https://grpc.production.xmtp.network:443".into(), true)
.await
.unwrap(),
),
(true, Env::Production) => todo!("not supported"),
};

if let Commands::Register { seed_phrase } = &cli.command {
Expand Down Expand Up @@ -456,6 +475,9 @@ async fn main() -> color_eyre::eyre::Result<()> {
Commands::Clear {} => {
fs::remove_file(cli.db.ok_or(eyre!("DB Missing"))?)?;
}
Commands::Debug(debug_commands) => {
debug::handle_debug(&client, debug_commands).await.unwrap();
}
}

Ok(())
Expand All @@ -471,7 +493,7 @@ async fn create_client<C: XmtpApi + 'static>(

builder = builder.api_client(grpc);

if cli.local {
if cli.env == Env::Local {
builder = builder.history_sync_url(MessageHistoryUrls::LOCAL_ADDRESS);
} else {
builder = builder.history_sync_url(MessageHistoryUrls::DEV_ADDRESS);
Expand Down
62 changes: 62 additions & 0 deletions examples/cli/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use chrono::{DateTime, Utc};
use clap::Subcommand;
use openmls::prelude::{tls_codec::Deserialize, MlsMessageBodyIn, MlsMessageIn};
use xmtp_mls::groups::scoped_client::ScopedGroupClient;
use xmtp_mls::{Client, XmtpApi};
use xmtp_proto::xmtp::mls::api::v1::group_message::Version as GroupMessageVersion;

#[derive(Debug, Subcommand)]
pub enum DebugCommands {
GroupMessages {
#[arg(short, long)]
group_id: String,
},
}

fn format_timestamp(timestamp_ns: u64) -> String {
let datetime: DateTime<Utc> = DateTime::from_timestamp_nanos(timestamp_ns as i64);
datetime.format("%Y-%m-%d %H:%M:%S%.3f UTC").to_string()
}

pub async fn debug_group_messages(
client: &Client<Box<dyn XmtpApi>>,
group_id: Vec<u8>,
) -> Result<(), String> {
let api_client = client.api();
let envelopes = api_client
.query_group_messages(group_id, None)
.await
.unwrap();
for envelope in envelopes {
let msgv1 = match &envelope.version {
Some(GroupMessageVersion::V1(value)) => value,
_ => return Err("Invalid group message version".to_string()),
};
let body = match MlsMessageIn::tls_deserialize_exact(&msgv1.data)
.map_err(|e| e.to_string())?
.extract()
{
MlsMessageBodyIn::PrivateMessage(message) => message,
_ => return Err("Unsupported message type".to_string()),
};
let timestamp = format_timestamp(msgv1.created_ns);
let sequence_id = msgv1.id;
let epoch = body.epoch().as_u64();
let content_type = body.content_type();
info!("[{timestamp}] [Epoch {epoch}] [Seq {sequence_id}] {content_type:?}");
}

Ok(())
}

pub async fn handle_debug(
client: &Client<Box<dyn XmtpApi>>,
command: &DebugCommands,
) -> Result<(), String> {
match command {
DebugCommands::GroupMessages { group_id } => {
info!("Querying group messages for group id: {}", group_id);
debug_group_messages(client, hex::decode(group_id).expect("group id decode")).await
}
}
}

0 comments on commit f37234a

Please sign in to comment.