Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions cmd/soroban-cli/src/commands/contract/arg_parsing.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::commands::contract::arg_parsing::Error::HelpMessage;
use crate::commands::contract::arg_parsing::Error::{CannotParseXDR, HelpMessage};
use crate::commands::contract::deploy::wasm::CONSTRUCTOR_FUNCTION_NAME;
use crate::commands::txn_result::TxnResult;
use crate::config::{self, sc_address, UnresolvedScAddress};
Expand All @@ -16,8 +16,10 @@ use std::convert::TryInto;
use std::env;
use std::ffi::OsString;
use std::fmt::Debug;
use std::path::PathBuf;
use stellar_xdr::curr::ContractId;
use std::fs::File;
use std::io::{Cursor, Read};
use std::path::{Path, PathBuf};
use stellar_xdr::curr::{ContractId, Limited, Limits, ReadXdr, SkipWhitespace};

#[derive(thiserror::Error, Debug)]
pub enum Error {
Expand Down Expand Up @@ -77,6 +79,10 @@ pub enum Error {
HelpMessage(String),
#[error(transparent)]
Signer(#[from] signer::Error),
#[error(transparent)]
Io(#[from] std::io::Error),
#[error("cannot parse XDR: {error}")]
CannotParseXDR { error: xdr::Error },
}

pub type HostFunctionParameters = (String, Spec, InvokeContractArgs, Vec<Signer>);
Expand Down Expand Up @@ -126,6 +132,50 @@ async fn build_host_function_parameters_with_filter(
Ok((function, spec, invoke_args, signers))
}

pub async fn build_host_function_parameters_from_string_xdr(
string_xdr: &OsString,
spec_entries: &[ScSpecEntry],
config: &config::Args,
) -> Result<HostFunctionParameters, Error> {
let spec = Spec(Some(spec_entries.to_vec()));
let invoke_args = invoke_contract_args_from_input(string_xdr)?;
let mut signers = Vec::<Signer>::new();
let args = invoke_args.args.to_vec();
for x in args {
let signer = match x {
ScVal::Address(addr) => {
let resolved = resolve_address(addr.to_string().as_str(), config)?;
resolve_signer(resolved.as_str(), config).await
}
_ => None,
};
if let Some(signer) = signer {
signers.push(signer);
}
}

Ok((
invoke_args.function_name.to_string(),
spec,
invoke_args,
signers,
))
}

fn invoke_contract_args_from_input(input: &OsString) -> Result<InvokeContractArgs, Error> {
let read: &mut dyn Read = {
let exist = Path::new(input).try_exists();
if let Ok(true) = exist {
&mut File::open(input)?
} else {
&mut Cursor::new(input.clone().into_encoded_bytes())
}
};

let mut lim = Limited::new(SkipWhitespace::new(read), Limits::none());
Comment thread
ifropc marked this conversation as resolved.
InvokeContractArgs::read_xdr_base64_to_end(&mut lim).map_err(|e| CannotParseXDR { error: e })
}

Comment thread
ifropc marked this conversation as resolved.
fn build_clap_command(spec: &Spec, filter_constructor: bool) -> Result<clap::Command, Error> {
let mut cmd = clap::Command::new(running_cmd())
.no_binary_name(true)
Expand Down
36 changes: 30 additions & 6 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::assembled::Assembled;
use crate::commands::contract::arg_parsing::build_host_function_parameters_from_string_xdr;
use crate::commands::tx::fetch;
use crate::log::extract_events;
use crate::print::Print;
Expand Down Expand Up @@ -55,9 +56,16 @@ pub struct Cmd {
#[arg(long, env = "STELLAR_INVOKE_VIEW")]
pub is_view: bool,

Comment thread
ifropc marked this conversation as resolved.
#[arg(long, conflicts_with = "CONTRACT_FN_AND_ARGS")]
pub invoke_contract_args: Option<OsString>,

/// Function name as subcommand, then arguments for that function as `--arg-name value`
#[arg(last = true, id = "CONTRACT_FN_AND_ARGS")]
pub slop: Vec<OsString>,
#[arg(
last = true,
id = "CONTRACT_FN_AND_ARGS",
conflicts_with = "invoke_contract_args"
)]
pub slop: Option<Vec<OsString>>,
Comment thread
ifropc marked this conversation as resolved.
Outdated

#[command(flatten)]
pub config: config::Args,
Expand Down Expand Up @@ -268,8 +276,13 @@ impl Cmd {
let spec_entries = self.spec_entries()?;

if let Some(spec_entries) = &spec_entries {
// For testing wasm arg parsing
build_host_function_parameters(&contract_id, &self.slop, spec_entries, config).await?;
if let Some(slop) = &self.slop {
// For testing wasm arg parsing
build_host_function_parameters(&contract_id, slop, spec_entries, config).await?;
} else if self.invoke_contract_args.is_none() {
// For giving a nice error message if --invoke-contract-args was not provided and slop not used
build_host_function_parameters(&contract_id, &[], spec_entries, config).await?;
}
}

let client = network.rpc_client()?;
Expand All @@ -294,8 +307,19 @@ impl Cmd {
.await
.map_err(Error::from)?;

let params =
build_host_function_parameters(&contract_id, &self.slop, &spec_entries, config).await?;
let params = if let Some(slop) = &self.slop {
build_host_function_parameters(&contract_id, slop, &spec_entries, config).await?
} else if let Some(invoke_contract_args) = &self.invoke_contract_args {
build_host_function_parameters_from_string_xdr(
invoke_contract_args,
&spec_entries,
config,
)
.await?
} else {
// For giving a nice error message if --invoke-contract-args was not provided and slop not used
build_host_function_parameters(&contract_id, &[], &spec_entries, config).await?
};

let (function, spec, host_function_params, signers) = params;

Expand Down
30 changes: 1 addition & 29 deletions cmd/soroban-cli/src/commands/tx/xdr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::fs::File;
use std::io::{stdin, Read};
use std::io::{Cursor, IsTerminal};
use std::path::Path;
use stellar_xdr::curr::Limited;
use stellar_xdr::curr::{Limited, SkipWhitespace};

#[derive(Debug, thiserror::Error)]
pub enum Error {
Expand Down Expand Up @@ -41,34 +41,6 @@ pub fn tx_envelope_from_input(input: &Option<OsString>) -> Result<TransactionEnv
Ok(TransactionEnvelope::read_xdr_base64_to_end(&mut lim)?)
}

// TODO: use SkipWhitespace from rs-stellar-xdr once it's updated to 23.0
pub struct SkipWhitespace<R: Read> {
pub inner: R,
}

impl<R: Read> SkipWhitespace<R> {
pub fn new(inner: R) -> Self {
SkipWhitespace { inner }
}
}

impl<R: Read> Read for SkipWhitespace<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let n = self.inner.read(buf)?;

let mut written = 0;
for read in 0..n {
if !buf[read].is_ascii_whitespace() {
buf[written] = buf[read];
written += 1;
}
}

Ok(written)
}
}
//

pub fn unwrap_envelope_v1(tx_env: TransactionEnvelope) -> Result<Transaction, Error> {
let TransactionEnvelope::Tx(TransactionV1Envelope { tx, .. }) = tx_env else {
return Err(Error::OnlyTransactionV1Supported);
Expand Down
Loading