Skip to content

Commit

Permalink
Merge branch 'main' into feat/sign_and_send
Browse files Browse the repository at this point in the history
  • Loading branch information
elizabethengelman committed Sep 3, 2024
2 parents 349ba49 + bb36419 commit 315aca2
Show file tree
Hide file tree
Showing 11 changed files with 393 additions and 3 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.

14 changes: 14 additions & 0 deletions FULL_HELP_DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ Utilities to manage contract aliases
* `remove` — Remove contract alias
* `add` — Add contract alias
* `show` — Show the contract id associated with a given alias
* `ls` — List all aliases



Expand Down Expand Up @@ -232,6 +233,19 @@ Show the contract id associated with a given alias



## `stellar contract alias ls`

List all aliases

**Usage:** `stellar contract alias ls [OPTIONS]`

###### **Options:**

* `--global` — Use global config
* `--config-dir <CONFIG_DIR>` — Location of config directory, default is "."



## `stellar contract bindings`

Generate code client bindings for a contract
Expand Down
5 changes: 4 additions & 1 deletion cmd/soroban-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ hyper-tls = "0.5"
http = "0.2.9"
regex = "1.6.0"
wasm-opt = { version = "0.114.0", optional = true }
chrono = "0.4.27"
chrono = { version = "0.4.27", features = ["serde"]}
rpassword = "7.2.0"
dirs = "4.0.0"
toml = "0.5.9"
Expand Down Expand Up @@ -123,6 +123,9 @@ bytesize = "1.3.0"
humantime = "2.1.0"
phf = { version = "0.11.2", features = ["macros"] }
crossterm = "0.27.0"
semver = "1.0.0"
glob = "0.3.1"

# For hyper-tls
[target.'cfg(unix)'.dependencies]
openssl = { version = "=0.10.55", features = ["vendored"] }
Expand Down
9 changes: 9 additions & 0 deletions cmd/soroban-cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use clap::CommandFactory;
use dotenvy::dotenv;
use std::thread;
use tracing_subscriber::{fmt, EnvFilter};

use crate::upgrade_check::upgrade_check;
use crate::{commands, Root};

#[tokio::main]
Expand Down Expand Up @@ -70,6 +72,13 @@ pub async fn main() {
.expect("Failed to set the global tracing subscriber");
}

// Spawn a thread to check if a new version exists.
// It depends on logger, so we need to place it after
// the code block that initializes the logger.
thread::spawn(move || {
upgrade_check(root.global_args.quiet);
});

if let Err(e) = root.run().await {
eprintln!("error: {e}");
std::process::exit(1);
Expand Down
8 changes: 8 additions & 0 deletions cmd/soroban-cli/src/commands/contract/alias.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::commands::global;

pub mod add;
pub mod ls;
pub mod remove;
pub mod show;

Expand All @@ -14,6 +15,9 @@ pub enum Cmd {

/// Show the contract id associated with a given alias
Show(show::Cmd),

/// List all aliases
Ls(ls::Cmd),
}

#[derive(thiserror::Error, Debug)]
Expand All @@ -26,6 +30,9 @@ pub enum Error {

#[error(transparent)]
Show(#[from] show::Error),

#[error(transparent)]
Ls(#[from] ls::Error),
}

impl Cmd {
Expand All @@ -34,6 +41,7 @@ impl Cmd {
Cmd::Remove(remove) => remove.run(global_args)?,
Cmd::Add(add) => add.run(global_args)?,
Cmd::Show(show) => show.run(global_args)?,
Cmd::Ls(ls) => ls.run()?,
}
Ok(())
}
Expand Down
104 changes: 104 additions & 0 deletions cmd/soroban-cli/src/commands/contract/alias/ls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use std::collections::HashMap;
use std::fmt::Debug;
use std::{fs, process};

use clap::{command, Parser};

use crate::commands::config::network;
use crate::config::{alias, locator};

#[derive(Parser, Debug, Clone)]
#[group(skip)]
pub struct Cmd {
#[command(flatten)]
pub config_locator: locator::Args,
}

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
Locator(#[from] locator::Error),

#[error(transparent)]
Network(#[from] network::Error),

#[error(transparent)]
PatternError(#[from] glob::PatternError),

#[error(transparent)]
GlobError(#[from] glob::GlobError),

#[error(transparent)]
IoError(#[from] std::io::Error),
}

#[derive(Debug, Clone)]
struct AliasEntry {
alias: String,
contract: String,
}

impl Cmd {
pub fn run(&self) -> Result<(), Error> {
let config_dir = self.config_locator.config_dir()?;
let pattern = config_dir
.join("contract-ids")
.join("*.json")
.to_string_lossy()
.into_owned();

let paths = glob::glob(&pattern)?;
let mut found = false;
let mut map: HashMap<String, Vec<AliasEntry>> = HashMap::new();

for path in paths {
let path = path?;

if let Some(alias) = path.file_stem() {
let alias = alias.to_string_lossy().into_owned();
let content = fs::read_to_string(path)?;
let data: alias::Data = serde_json::from_str(&content).unwrap_or_default();

for network_passphrase in data.ids.keys() {
let network_passphrase = network_passphrase.to_string();
let contract = data
.ids
.get(&network_passphrase)
.map(ToString::to_string)
.unwrap_or_default();
let entry = AliasEntry {
alias: alias.clone(),
contract,
};

let list = map.entry(network_passphrase.clone()).or_default();

list.push(entry.clone());
}
}
}

for network_passphrase in map.keys() {
if let Some(list) = map.clone().get_mut(network_passphrase) {
println!("ℹ️ Aliases available for network '{network_passphrase}'");

list.sort_by(|a, b| a.alias.cmp(&b.alias));

for entry in list {
found = true;
println!("{}: {}", entry.alias, entry.contract);
}

println!();
}
}

if !found {
eprintln!("⚠️ No aliases defined for network");

process::exit(1);
}

Ok(())
}
}
8 changes: 6 additions & 2 deletions cmd/soroban-cli/src/config/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ pub enum Error {
CannotAccessAliasConfigFile,
#[error("cannot parse contract ID {0}: {1}")]
CannotParseContractId(String, DecodeError),
#[error("Failed to read upgrade check file: {path}: {error}")]
UpgradeCheckReadFailed { path: PathBuf, error: io::Error },
#[error("Failed to write upgrade check file: {path}: {error}")]
UpgradeCheckWriteFailed { path: PathBuf, error: io::Error },
}

#[derive(Debug, clap::Args, Default, Clone)]
Expand Down Expand Up @@ -338,7 +342,7 @@ impl Args {
}
}

fn ensure_directory(dir: PathBuf) -> Result<PathBuf, Error> {
pub fn ensure_directory(dir: PathBuf) -> Result<PathBuf, Error> {
let parent = dir.parent().ok_or(Error::HomeDirNotFound)?;
std::fs::create_dir_all(parent).map_err(|_| dir_creation_failed(parent))?;
Ok(dir)
Expand Down Expand Up @@ -461,7 +465,7 @@ impl KeyType {
}
}

fn global_config_path() -> Result<PathBuf, Error> {
pub fn global_config_path() -> Result<PathBuf, Error> {
Ok(if let Ok(config_home) = std::env::var("XDG_CONFIG_HOME") {
PathBuf::from_str(&config_home).map_err(|_| Error::XdgConfigHome(config_home))?
} else {
Expand Down
1 change: 1 addition & 0 deletions cmd/soroban-cli/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub mod locator;
pub mod network;
pub mod secret;
pub mod sign_with;
pub mod upgrade_check;

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down
86 changes: 86 additions & 0 deletions cmd/soroban-cli/src/config/upgrade_check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use crate::config::locator;
use chrono::{DateTime, Utc};
use jsonrpsee_core::Serialize;
use semver::Version;
use serde::Deserialize;
use serde_json;
use std::fs;

const FILE_NAME: &str = "upgrade_check.json";

/// The `UpgradeCheck` struct represents the state of the upgrade check.
/// This state is global and stored in the `upgrade_check.json` file in
/// the global configuration directory.
#[derive(Serialize, Deserialize, Debug, PartialEq)]
pub struct UpgradeCheck {
/// The time of the latest check for a new version of the CLI.
pub latest_check_time: DateTime<Utc>,
/// The latest stable version of the CLI available on crates.io.
pub max_stable_version: Version,
/// The latest version of the CLI available on crates.io, including pre-releases.
pub max_version: Version,
}

impl Default for UpgradeCheck {
fn default() -> Self {
Self {
latest_check_time: DateTime::<Utc>::UNIX_EPOCH,
max_stable_version: Version::new(0, 0, 0),
max_version: Version::new(0, 0, 0),
}
}
}

impl UpgradeCheck {
/// Loads the state of the upgrade check from the global configuration directory.
/// If the file doesn't exist, returns a default instance of `UpgradeCheck`.
pub fn load() -> Result<Self, locator::Error> {
let path = locator::global_config_path()?.join(FILE_NAME);
if !path.exists() {
return Ok(Self::default());
}
let data = fs::read(&path)
.map_err(|error| locator::Error::UpgradeCheckReadFailed { path, error })?;
Ok(serde_json::from_slice(data.as_slice())?)
}

/// Saves the state of the upgrade check to the `upgrade_check.json` file in the global configuration directory.
pub fn save(&self) -> Result<(), locator::Error> {
let path = locator::global_config_path()?.join(FILE_NAME);
let path = locator::ensure_directory(path)?;
let data = serde_json::to_string(self).map_err(|_| locator::Error::ConfigSerialization)?;
fs::write(&path, data)
.map_err(|error| locator::Error::UpgradeCheckWriteFailed { path, error })
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::env;

#[test]
fn test_upgrade_check_load_save() {
// Set the `XDG_CONFIG_HOME` environment variable to a temporary directory
let temp_dir = tempfile::tempdir().unwrap();
env::set_var("XDG_CONFIG_HOME", temp_dir.path());
// Test default loading
let default_check = UpgradeCheck::load().unwrap();
assert_eq!(default_check, UpgradeCheck::default());
assert_eq!(
default_check.latest_check_time,
DateTime::<Utc>::from_timestamp_millis(0).unwrap()
);
assert_eq!(default_check.max_stable_version, Version::new(0, 0, 0));

// Test saving and loading
let saved_check = UpgradeCheck {
latest_check_time: DateTime::<Utc>::from_timestamp(1_234_567_890, 0).unwrap(),
max_stable_version: Version::new(1, 2, 3),
max_version: Version::parse("1.2.4-rc.1").unwrap(),
};
saved_check.save().unwrap();
let loaded_check = UpgradeCheck::load().unwrap();
assert_eq!(loaded_check, saved_check);
}
}
1 change: 1 addition & 0 deletions cmd/soroban-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod log;
pub mod print;
pub mod signer;
pub mod toid;
pub mod upgrade_check;
pub mod utils;
pub mod wasm;

Expand Down
Loading

0 comments on commit 315aca2

Please sign in to comment.