Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add no-build option for fee::Args #1267

Merged
merged 10 commits into from
May 9, 2024
3 changes: 1 addition & 2 deletions cmd/crates/soroban-spec-tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1137,8 +1137,7 @@ impl Spec {
ScSpecEntry::UdtStructV0(ScSpecUdtStructV0 { fields, .. })
if fields
.first()
.map(|f| f.name.to_utf8_string_lossy() == "0")
.unwrap_or_default() =>
.is_some_and(|f| f.name.to_utf8_string_lossy() == "0") =>
{
let fields = fields
.iter()
Expand Down
4 changes: 3 additions & 1 deletion cmd/crates/soroban-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,9 @@ impl TestEnv {
source: &str,
) -> Result<String, invoke::Error> {
let cmd = self.cmd_with_config::<I, invoke::Cmd>(command_str);
self.run_cmd_with(cmd, source).await
self.run_cmd_with(cmd, source)
.await
.map(|r| r.into_result().unwrap())
}

/// A convenience method for using the invoke command.
Expand Down
27 changes: 22 additions & 5 deletions cmd/crates/soroban-test/tests/it/integration/hello_world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use predicates::boolean::PredicateBooleanExt;
use soroban_cli::commands::{
config::{locator, secret},
contract::{self, fetch},
txn_result::TxnResult,
};
use soroban_rpc::GetLatestLedgerResponse;
use soroban_test::{AssertExt, TestEnv, LOCAL_NETWORK_PASSPHRASE};
Expand All @@ -11,6 +12,18 @@ use crate::integration::util::extend_contract;
use super::util::{deploy_hello, extend, HELLO_WORLD};

#[allow(clippy::too_many_lines)]
#[tokio::test]
async fn invoke_view_with_non_existent_source_account() {
let sandbox = &TestEnv::new();
let id = deploy_hello(sandbox).await;
let world = "world";
let mut cmd = hello_world_cmd(&id, world);
cmd.config.source_account = String::new();
cmd.is_view = true;
let res = sandbox.run_cmd_with(cmd, "test").await.unwrap();
assert_eq!(res, TxnResult::Res(format!(r#"["Hello",{world:?}]"#)));
}

#[tokio::test]
async fn invoke() {
let sandbox = &TestEnv::new();
Expand Down Expand Up @@ -140,14 +153,18 @@ fn invoke_hello_world(sandbox: &TestEnv, id: &str) {
.success();
}

async fn invoke_hello_world_with_lib(e: &TestEnv, id: &str) {
let cmd = contract::invoke::Cmd {
fn hello_world_cmd(id: &str, arg: &str) -> contract::invoke::Cmd {
contract::invoke::Cmd {
contract_id: id.to_string(),
slop: vec!["hello".into(), "--world=world".into()],
slop: vec!["hello".into(), format!("--world={arg}").into()],
..Default::default()
};
}
}

async fn invoke_hello_world_with_lib(e: &TestEnv, id: &str) {
let cmd = hello_world_cmd(id, "world");
let res = e.run_cmd_with(cmd, "test").await.unwrap();
assert_eq!(res, r#"["Hello","world"]"#);
assert_eq!(res, TxnResult::Res(r#"["Hello","world"]"#.to_string()));
}

fn invoke_auth(sandbox: &TestEnv, id: &str, addr: &str) {
Expand Down
7 changes: 6 additions & 1 deletion cmd/crates/soroban-test/tests/it/integration/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ pub async fn deploy_contract(sandbox: &TestEnv, wasm: &Wasm<'static>) -> String
TEST_SALT,
"--ignore-checks",
]);
sandbox.run_cmd_with(cmd, "test").await.unwrap()
sandbox
.run_cmd_with(cmd, "test")
.await
.unwrap()
.into_result()
.unwrap()
}

pub async fn extend_contract(sandbox: &TestEnv, id: &str) {
Expand Down
5 changes: 4 additions & 1 deletion cmd/crates/soroban-test/tests/it/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ pub async fn invoke_custom(
) -> Result<String, contract::invoke::Error> {
let mut i: contract::invoke::Cmd = sandbox.cmd_with_config(&["--id", id, "--", func, arg]);
i.wasm = Some(wasm.to_path_buf());
sandbox.run_cmd_with(i, TEST_ACCOUNT).await
sandbox
.run_cmd_with(i, TEST_ACCOUNT)
.await
.map(|r| r.into_result().unwrap())
}

pub const DEFAULT_CONTRACT_ID: &str = "CDR6QKTWZQYW6YUJ7UP7XXZRLWQPFRV6SWBLQS4ZQOSAF4BOUD77OO5Z";
16 changes: 12 additions & 4 deletions cmd/soroban-cli/src/commands/contract/deploy/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use std::{array::TryFromSliceError, fmt::Debug, num::ParseIntError};
use crate::{
commands::{
config::{self, data},
global, network, NetworkRunnable,
global, network,
txn_result::TxnResult,
NetworkRunnable,
},
rpc::{Client, Error as SorobanRpcError},
utils::{contract_id_hash_from_asset, parsing::parse_asset},
Expand Down Expand Up @@ -74,13 +76,13 @@ impl Cmd {
#[async_trait::async_trait]
impl NetworkRunnable for Cmd {
type Error = Error;
type Result = String;
type Result = TxnResult<stellar_strkey::Contract>;
willemneal marked this conversation as resolved.
Show resolved Hide resolved

async fn run_against_rpc_server(
&self,
args: Option<&global::Args>,
config: Option<&config::Args>,
) -> Result<String, Error> {
) -> Result<Self::Result, Error> {
let config = config.unwrap_or(&self.config);
// Parse asset
let asset = parse_asset(&self.asset)?;
Expand Down Expand Up @@ -108,8 +110,14 @@ impl NetworkRunnable for Cmd {
network_passphrase,
&key,
)?;
if self.fee.build_only {
return Ok(TxnResult::Txn(tx));
}
let txn = client.create_assembled_transaction(&tx).await?;
let txn = self.fee.apply_to_assembled_txn(txn);
if self.fee.sim_only {
return Ok(TxnResult::Txn(txn.transaction().clone()));
}
willemneal marked this conversation as resolved.
Show resolved Hide resolved
let get_txn_resp = client
.send_assembled_transaction(txn, &key, &[], network_passphrase, None, None)
.await?
Expand All @@ -118,7 +126,7 @@ impl NetworkRunnable for Cmd {
data::write(get_txn_resp, &network.rpc_uri()?)?;
}

Ok(stellar_strkey::Contract(contract_id.0).to_string())
Ok(TxnResult::Res(stellar_strkey::Contract(contract_id.0)))
}
}

Expand Down
43 changes: 31 additions & 12 deletions cmd/soroban-cli/src/commands/contract/deploy/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ use soroban_env_host::{
use crate::commands::{
config::data,
contract::{self, id::wasm::get_contract_id},
global, network, NetworkRunnable,
global, network,
txn_result::TxnResult,
NetworkRunnable,
};
use crate::{
commands::{config, contract::install, HEADING_RPC},
Expand Down Expand Up @@ -96,6 +98,8 @@ pub enum Error {
Data(#[from] data::Error),
#[error(transparent)]
Network(#[from] network::Error),
#[error(transparent)]
Wasm(#[from] wasm::Error),
}

impl Cmd {
Expand All @@ -109,23 +113,29 @@ impl Cmd {
#[async_trait::async_trait]
impl NetworkRunnable for Cmd {
type Error = Error;
type Result = String;
type Result = TxnResult<String>;

async fn run_against_rpc_server(
&self,
global_args: Option<&global::Args>,
config: Option<&config::Args>,
) -> Result<String, Error> {
) -> Result<TxnResult<String>, Error> {
let config = config.unwrap_or(&self.config);
let wasm_hash = if let Some(wasm) = &self.wasm {
let hash = install::Cmd {
wasm: wasm::Args { wasm: wasm.clone() },
config: config.clone(),
fee: self.fee.clone(),
ignore_checks: self.ignore_checks,
}
.run_against_rpc_server(global_args, Some(config))
.await?;
let hash = if self.fee.build_only {
wasm::Args { wasm: wasm.clone() }.hash()?
} else {
install::Cmd {
wasm: wasm::Args { wasm: wasm.clone() },
config: config.clone(),
fee: self.fee.clone(),
ignore_checks: self.ignore_checks,
}
.run_against_rpc_server(global_args, Some(config))
.await?
.into_result()
.expect("the value (hash) is expected because it should always be available since build-only is a shared parameter")
};
hex::encode(hash)
} else {
self.wasm_hash
Expand Down Expand Up @@ -169,16 +179,25 @@ impl NetworkRunnable for Cmd {
salt,
&key,
)?;
if self.fee.build_only {
return Ok(TxnResult::Txn(txn));
}

let txn = client.create_assembled_transaction(&txn).await?;
let txn = self.fee.apply_to_assembled_txn(txn);
if self.fee.sim_only {
return Ok(TxnResult::Txn(txn.transaction().clone()));
}
let get_txn_resp = client
.send_assembled_transaction(txn, &key, &[], &network.network_passphrase, None, None)
.await?
.try_into()?;
if global_args.map_or(true, |a| !a.no_cache) {
data::write(get_txn_resp, &network.rpc_uri()?)?;
}
Ok(stellar_strkey::Contract(contract_id.0).to_string())
Ok(TxnResult::Res(
stellar_strkey::Contract(contract_id.0).to_string(),
))
}
}

Expand Down
37 changes: 23 additions & 14 deletions cmd/soroban-cli/src/commands/contract/extend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ use std::{fmt::Debug, path::Path, str::FromStr};
use clap::{command, Parser};
use soroban_env_host::xdr::{
Error as XdrError, ExtendFootprintTtlOp, ExtensionPoint, LedgerEntry, LedgerEntryChange,
LedgerEntryData, LedgerFootprint, Memo, MuxedAccount, Operation, OperationBody, Preconditions,
SequenceNumber, SorobanResources, SorobanTransactionData, Transaction, TransactionExt,
TransactionMeta, TransactionMetaV3, TtlEntry, Uint256,
LedgerEntryData, LedgerFootprint, Limits, Memo, MuxedAccount, Operation, OperationBody,
Preconditions, SequenceNumber, SorobanResources, SorobanTransactionData, Transaction,
TransactionExt, TransactionMeta, TransactionMetaV3, TtlEntry, Uint256, WriteXdr,
};

use crate::{
commands::{
config::{self, data},
global, network, NetworkRunnable,
global, network,
txn_result::TxnResult,
NetworkRunnable,
},
key,
rpc::{self, Client},
Expand Down Expand Up @@ -87,11 +89,16 @@ pub enum Error {
impl Cmd {
#[allow(clippy::too_many_lines)]
pub async fn run(&self) -> Result<(), Error> {
let ttl_ledger = self.run_against_rpc_server(None, None).await?;
if self.ttl_ledger_only {
println!("{ttl_ledger}");
} else {
println!("New ttl ledger: {ttl_ledger}");
let res = self.run_against_rpc_server(None, None).await?;
match res {
TxnResult::Txn(tx) => println!("{}", tx.to_xdr_base64(Limits::none())?),
TxnResult::Res(ttl_ledger) => {
if self.ttl_ledger_only {
println!("{ttl_ledger}");
} else {
println!("New ttl ledger: {ttl_ledger}");
}
}
}

Ok(())
Expand All @@ -111,13 +118,13 @@ impl Cmd {
#[async_trait::async_trait]
impl NetworkRunnable for Cmd {
type Error = Error;
type Result = u32;
type Result = TxnResult<u32>;

async fn run_against_rpc_server(
&self,
args: Option<&global::Args>,
config: Option<&config::Args>,
) -> Result<u32, Self::Error> {
) -> Result<TxnResult<u32>, Self::Error> {
let config = config.unwrap_or(&self.config);
let network = config.get_network()?;
tracing::trace!(?network);
Expand Down Expand Up @@ -161,7 +168,9 @@ impl NetworkRunnable for Cmd {
resource_fee: 0,
}),
};

if self.fee.build_only {
return Ok(TxnResult::Txn(tx));
}
let res = client
.prepare_and_send_transaction(&tx, &key, &[], &network.network_passphrase, None, None)
.await?;
Expand Down Expand Up @@ -194,7 +203,7 @@ impl NetworkRunnable for Cmd {
let entry = client.get_full_ledger_entries(&keys).await?;
let extension = entry.entries[0].live_until_ledger_seq;
if entry.latest_ledger + i64::from(extend_to) < i64::from(extension) {
return Ok(extension);
return Ok(TxnResult::Res(extension));
}
}

Expand All @@ -209,7 +218,7 @@ impl NetworkRunnable for Cmd {
}),
..
}),
) => Ok(*live_until_ledger_seq),
) => Ok(TxnResult::Res(*live_until_ledger_seq)),
_ => Err(Error::LedgerEntryNotFound),
}
}
Expand Down
1 change: 0 additions & 1 deletion cmd/soroban-cli/src/commands/contract/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ impl NetworkRunnable for Cmd {
client
.verify_network_passphrase(Some(&network.network_passphrase))
.await?;
// async closures are not yet stable
Ok(client.get_remote_wasm(&contract_id).await?)
}
}
Expand Down
9 changes: 6 additions & 3 deletions cmd/soroban-cli/src/commands/contract/id/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@ pub enum Error {
}
impl Cmd {
pub fn run(&self) -> Result<(), Error> {
println!("{}", self.contract_address()?);
Ok(())
}

pub fn contract_address(&self) -> Result<stellar_strkey::Contract, Error> {
let asset = parse_asset(&self.asset)?;
let network = self.config.get_network()?;
let contract_id = contract_id_hash_from_asset(&asset, &network.network_passphrase)?;
let strkey_contract_id = stellar_strkey::Contract(contract_id.0).to_string();
println!("{strkey_contract_id}");
Ok(())
Ok(stellar_strkey::Contract(contract_id.0))
}
}
Loading
Loading