Skip to content

Commit

Permalink
refactor: Refactor contract ID handling in Args module.
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal authored and gitbutler-client committed Nov 1, 2024
1 parent 122df31 commit 90287f8
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ pub(crate) fn invoke_hello_world(sandbox: &TestEnv, id: &str) {

fn hello_world_cmd(id: &str, arg: &str) -> contract::invoke::Cmd {
contract::invoke::Cmd {
contract_id: id.to_string(),
contract_id: id.parse().unwrap(),
slop: vec!["hello".into(), format!("--world={arg}").into()],
..Default::default()
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/soroban-cli/src/commands/contract/alias/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub struct Cmd {
#[command(flatten)]
network: network::Args,

/// The contract alias that will be removed.
/// The contract alias that will be used.
pub alias: String,

/// Overwrite the contract alias if it already exists.
Expand All @@ -41,7 +41,7 @@ pub enum Error {
AlreadyExist {
alias: String,
network_passphrase: String,
contract: String,
contract: stellar_strkey::Contract,
},
}

Expand Down
12 changes: 9 additions & 3 deletions cmd/soroban-cli/src/commands/contract/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use clap::{arg, command, Parser};
use crate::{
commands::{global, NetworkRunnable},
config::{
self, locator,
self, alias, locator,
network::{self, Network},
},
wasm, Pwd,
Expand All @@ -22,7 +22,7 @@ use crate::{
pub struct Cmd {
/// Contract ID to fetch
#[arg(long = "id", env = "STELLAR_CONTRACT_ID")]
pub contract_id: String,
pub contract_id: config::ContractAddress,
/// Where to write output otherwise stdout is used
#[arg(long, short = 'o')]
pub out_file: Option<std::path::PathBuf>,
Expand Down Expand Up @@ -111,6 +111,12 @@ impl NetworkRunnable for Cmd {
config: Option<&config::Args>,
) -> Result<Vec<u8>, Error> {
let network = config.map_or_else(|| self.network(), |c| Ok(c.get_network()?))?;
return Ok(wasm::fetch_from_contract(&self.contract_id, &network, &self.locator).await?);
Ok(wasm::fetch_from_contract(
&self
.contract_id
.resolve_contract_id(&self.locator, &network.network_passphrase)?,
&network,
)
.await?)
}
}
15 changes: 8 additions & 7 deletions cmd/soroban-cli/src/commands/contract/info/shared.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::path::PathBuf;

use crate::xdr;
use clap::arg;

use crate::{
commands::contract::info::shared::Error::InvalidWasmHash,
config::{locator, network},
config::{self, locator, network},
utils::rpc::get_remote_wasm_from_hash,
wasm::{self, Error::ContractIsStellarAsset},
xdr,
};

#[derive(Debug, clap::Args, Clone, Default)]
Expand All @@ -26,7 +26,7 @@ pub struct Args {
pub wasm_hash: Option<String>,
/// Contract id or contract alias to get the data for
#[arg(long = "id", env = "STELLAR_CONTRACT_ID", group = "Source")]
pub contract_id: Option<String>,
pub contract_id: Option<config::ContractAddress>,
#[command(flatten)]
pub network: network::Args,
#[command(flatten)]
Expand Down Expand Up @@ -56,6 +56,8 @@ pub enum Error {
InvalidWasmHash(String),
#[error(transparent)]
Rpc(#[from] soroban_rpc::Error),
#[error(transparent)]
Locator(#[from] locator::Error),
}

pub async fn fetch_wasm(args: &Args) -> Result<Option<Vec<u8>>, Error> {
Expand All @@ -79,10 +81,9 @@ pub async fn fetch_wasm(args: &Args) -> Result<Option<Vec<u8>>, Error> {

get_remote_wasm_from_hash(&client, &hash).await?
} else if let Some(contract_id) = &args.contract_id {
let contract_id = args
.locator
.resolve_contract_id(contract_id, &network.network_passphrase)?;
let res = wasm::fetch_from_contract(contract_id, network, &args.locator).await;
let contract_id =
contract_id.resolve_contract_id(&args.locator, &network.network_passphrase)?;
let res = wasm::fetch_from_contract(&contract_id, network).await;
if let Some(ContractIsStellarAsset) = res.as_ref().err() {
return Ok(None);
}
Expand Down
10 changes: 6 additions & 4 deletions cmd/soroban-cli/src/commands/contract/invoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use soroban_spec::read::FromWasmError;

use super::super::events;
use super::arg_parsing;
use crate::config::alias;
use crate::{
assembled::simulate_and_assemble_transaction,
commands::{
Expand Down Expand Up @@ -40,7 +41,7 @@ use soroban_spec_tools::contract;
pub struct Cmd {
/// Contract ID to invoke
#[arg(long = "id", env = "STELLAR_CONTRACT_ID")]
pub contract_id: String,
pub contract_id: config::ContractAddress,
// For testing only
#[arg(skip)]
pub wasm: Option<std::path::PathBuf>,
Expand Down Expand Up @@ -123,6 +124,8 @@ pub enum Error {
GetSpecError(#[from] get_spec::Error),
#[error(transparent)]
ArgParsing(#[from] arg_parsing::Error),
#[error(transparent)]
ContractAddress(#[from] alias::Error),
}

impl From<Infallible> for Error {
Expand Down Expand Up @@ -195,9 +198,8 @@ impl NetworkRunnable for Cmd {
let network = config.get_network()?;
tracing::trace!(?network);
let contract_id = self
.config
.locator
.resolve_contract_id(&self.contract_id, &network.network_passphrase)?;
.contract_id
.resolve_contract_id(&config.locator, &network.network_passphrase)?;

let spec_entries = self.spec_entries()?;
if let Some(spec_entries) = &spec_entries {
Expand Down
14 changes: 9 additions & 5 deletions cmd/soroban-cli/src/commands/events.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use clap::{arg, command, Parser};
use std::io;

use crate::xdr::{self, Limits, ReadXdr};
use crate::{
config::alias,
xdr::{self, Limits, ReadXdr},
};

use super::{global, NetworkRunnable};
use crate::{
Expand Down Expand Up @@ -42,7 +45,7 @@ pub struct Cmd {
num_args = 1..=6,
help_heading = "FILTERS"
)]
contract_ids: Vec<String>,
contract_ids: Vec<config::ContractAddress>,
/// A set of (up to 4) topic filters to filter event topics on. A single
/// topic filter can contain 1-4 different segment filters, separated by
/// commas, with an asterisk (`*` character) indicating a wildcard segment.
Expand Down Expand Up @@ -121,6 +124,8 @@ pub enum Error {
Locator(#[from] locator::Error),
#[error(transparent)]
Config(#[from] config::Error),
#[error(transparent)]
ContractId(#[from] alias::Error),
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, clap::ValueEnum)]
Expand Down Expand Up @@ -218,9 +223,8 @@ impl NetworkRunnable for Cmd {
.contract_ids
.iter()
.map(|id| {
Ok(self
.locator
.resolve_contract_id(id, &network.network_passphrase)?
Ok(id
.resolve_contract_id(&self.locator, &network.network_passphrase)?
.to_string())
})
.collect::<Result<Vec<_>, Error>>()?;
Expand Down
43 changes: 42 additions & 1 deletion cmd/soroban-cli/src/config/alias.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,49 @@
use std::collections::HashMap;
use std::{collections::HashMap, convert::Infallible, str::FromStr};

use serde::{Deserialize, Serialize};

use super::locator;

#[derive(Serialize, Deserialize, Default)]
pub struct Data {
pub ids: HashMap<String, String>,
}

/// Address can be either a contract address, C.. or eventually an alias of a contract address.
#[derive(Clone, Debug)]
pub enum ContractAddress {
ContractId(stellar_strkey::Contract),
Alias(String),
}

impl Default for ContractAddress {
fn default() -> Self {
ContractAddress::Alias(String::default())
}
}

impl FromStr for ContractAddress {
type Err = Infallible;

fn from_str(value: &str) -> Result<Self, Self::Err> {
Ok(stellar_strkey::Contract::from_str(value).map_or_else(
|_| ContractAddress::Alias(value.to_string()),
ContractAddress::ContractId,
))
}
}

impl ContractAddress {
pub fn resolve_contract_id(
&self,
locator: &locator::Args,
network_passphrase: &str,
) -> Result<stellar_strkey::Contract, locator::Error> {
match self {
ContractAddress::ContractId(muxed_account) => Ok(*muxed_account),
ContractAddress::Alias(alias) => locator
.get_contract_id(alias, network_passphrase)?
.ok_or_else(|| locator::Error::ContractNotFound(alias.to_owned())),
}
}
}
25 changes: 15 additions & 10 deletions cmd/soroban-cli/src/config/locator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ pub enum Error {
CannotAccessAliasConfigFile,
#[error("cannot parse contract ID {0}: {1}")]
CannotParseContractId(String, DecodeError),
#[error("contract not found: {0}")]
ContractNotFound(String),
#[error("Failed to read upgrade check file: {path}: {error}")]
UpgradeCheckReadFailed { path: PathBuf, error: io::Error },
#[error("Failed to write upgrade check file: {path}: {error}")]
Expand Down Expand Up @@ -320,27 +322,30 @@ impl Args {
&self,
alias: &str,
network_passphrase: &str,
) -> Result<Option<String>, Error> {
) -> Result<Option<Contract>, Error> {
let Some(alias_data) = self.load_contract_from_alias(alias)? else {
return Ok(None);
};

Ok(alias_data.ids.get(network_passphrase).cloned())
alias_data
.ids
.get(network_passphrase)
.map(|id| id.parse())
.transpose()
.map_err(|e| Error::CannotParseContractId(alias.to_owned(), e))
}

pub fn resolve_contract_id(
&self,
alias_or_contract_id: &str,
network_passphrase: &str,
) -> Result<Contract, Error> {
let contract_id = self
.get_contract_id(alias_or_contract_id, network_passphrase)?
.unwrap_or_else(|| alias_or_contract_id.to_string());

Ok(Contract(
soroban_spec_tools::utils::contract_id_from_str(&contract_id)
.map_err(|e| Error::CannotParseContractId(contract_id.clone(), e))?,
))
let Some(contract) = self.get_contract_id(alias_or_contract_id, network_passphrase)? else {
return alias_or_contract_id
.parse()
.map_err(|e| Error::CannotParseContractId(alias_or_contract_id.to_owned(), e));
};
Ok(contract)
}
}

Expand Down
2 changes: 2 additions & 0 deletions cmd/soroban-cli/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub mod secret;
pub mod sign_with;
pub mod upgrade_check;

pub use alias::ContractAddress;

#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error(transparent)]
Expand Down
13 changes: 9 additions & 4 deletions cmd/soroban-cli/src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::xdr::{
};
use crate::{
commands::contract::Durability,
config::{locator, network::Network},
config::{alias, locator, network::Network},
wasm,
};
use clap::arg;
Expand All @@ -22,6 +22,8 @@ pub enum Error {
Wasm(#[from] wasm::Error),
#[error(transparent)]
Locator(#[from] locator::Error),
#[error(transparent)]
ContractId(#[from] alias::Error),
}

#[derive(Debug, clap::Args, Clone)]
Expand All @@ -34,7 +36,7 @@ pub struct Args {
required_unless_present = "wasm",
required_unless_present = "wasm_hash"
)]
pub contract_id: Option<String>,
pub contract_id: Option<config::ContractAddress>,
/// Storage key (symbols only)
#[arg(long = "key", conflicts_with = "key_xdr")]
pub key: Option<Vec<String>>,
Expand Down Expand Up @@ -97,8 +99,11 @@ impl Args {
} else {
vec![ScVal::LedgerKeyContractInstance]
};
let contract =
locator.resolve_contract_id(self.contract_id.as_ref().unwrap(), network_passphrase)?;
let contract = self
.contract_id
.as_ref()
.unwrap()
.resolve_contract_id(locator, network_passphrase)?;

Ok(keys
.into_iter()
Expand Down
8 changes: 1 addition & 7 deletions cmd/soroban-cli/src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,10 @@ pub fn len(p: &Path) -> Result<u64, Error> {
}

pub async fn fetch_from_contract(
contract_id: &str,
stellar_strkey::Contract(contract_id): &stellar_strkey::Contract,
network: &Network,
locator: &locator::Args,
) -> Result<Vec<u8>, Error> {
tracing::trace!(?network);

let contract_id = &locator
.resolve_contract_id(contract_id, &network.network_passphrase)?
.0;

let client = network.rpc_client()?;
client
.verify_network_passphrase(Some(&network.network_passphrase))
Expand Down

0 comments on commit 90287f8

Please sign in to comment.