Skip to content

Commit 231cfc6

Browse files
Merge branch 'main' into ledger-entry-get
2 parents bd05406 + a41f513 commit 231cfc6

File tree

18 files changed

+321
-44
lines changed

18 files changed

+321
-44
lines changed

.github/copilot-instructions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Stellar CLI is a Rust-based command-line tool for interacting with the Stellar n
2424

2525
- Test main soroban-cli library: `cargo test --package soroban-cli --lib` -- takes 52 seconds. NEVER CANCEL.
2626
- Test individual crates: `cargo test --package <crate-name>` -- typically takes 40 seconds per crate.
27+
- Test soroban-test integration tests: `cargo test --features it --test it -- integration` -- tests the commands of the cli and is where the bulk of the tests live for this repository. All new commands and changes to commands should include updates or additions to tests in soroban-test.
2728
- **WARNING**: Full test suite via `make test` requires building WebAssembly test fixtures and consumes significant memory and disk space. It may fail with "No space left on device" in constrained environments.
2829

2930
### CLI Usage and Validation

.github/workflows/action.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
name: Action
3+
4+
on:
5+
pull_request:
6+
7+
concurrency:
8+
group:
9+
${{ github.workflow }}-${{ github.ref_protected == 'true' && github.sha ||
10+
github.ref }}-{{ github.event_name }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
action:
15+
strategy:
16+
matrix:
17+
image: [macos-13, ubuntu-latest, windows-latest]
18+
runs-on: ${{ matrix.image }}
19+
20+
steps:
21+
- uses: stellar/stellar-cli@main
22+
with:
23+
version: v23.1.4

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ version = "23.0.1"
7373
# Dependencies from the rs-stellar-rpc-client repo:
7474
[workspace.dependencies.soroban-rpc]
7575
package = "stellar-rpc-client"
76-
version = "23.1.0"
76+
version = "23.2.0"
7777

7878
# Dependencies from elsewhere shared by crates:
7979
[workspace.dependencies]

cmd/crates/soroban-test/tests/it/build.rs

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,13 @@ fn build_with_metadata_rewrite() {
163163
.success();
164164

165165
let entries = get_entries(&dir_path, &outdir);
166+
167+
// Filter out CLI version for comparison
168+
let filtered_entries: Vec<_> = entries
169+
.into_iter()
170+
.filter(|entry| !matches!(entry, ScMetaEntry::ScMetaV0(ScMetaV0 { key, .. }) if key.to_string() == "cliver"))
171+
.collect();
172+
166173
let expected_entries = vec![
167174
ScMetaEntry::ScMetaV0(ScMetaV0 {
168175
key: "Description".try_into().unwrap(),
@@ -174,7 +181,7 @@ fn build_with_metadata_rewrite() {
174181
}),
175182
];
176183

177-
assert_eq!(entries, expected_entries);
184+
assert_eq!(filtered_entries, expected_entries);
178185
}
179186

180187
#[test]
@@ -212,6 +219,20 @@ fn build_with_metadata_diff_dir() {
212219
.success();
213220

214221
let entries_dir1 = get_entries(&dir_path, &outdir1);
222+
223+
let entries_dir2 = get_entries(&dir_path, &outdir2);
224+
225+
// Filter out CLI version for comparison
226+
let filtered_entries_dir1: Vec<_> = entries_dir1
227+
.into_iter()
228+
.filter(|entry| !matches!(entry, ScMetaEntry::ScMetaV0(ScMetaV0 { key, .. }) if key.to_string() == "cliver"))
229+
.collect();
230+
231+
let filtered_entries_dir2: Vec<_> = entries_dir2
232+
.into_iter()
233+
.filter(|entry| !matches!(entry, ScMetaEntry::ScMetaV0(ScMetaV0 { key, .. }) if key.to_string() == "cliver"))
234+
.collect();
235+
215236
let expected_entries_dir1 = vec![
216237
ScMetaEntry::ScMetaV0(ScMetaV0 {
217238
key: "Description".try_into().unwrap(),
@@ -223,7 +244,6 @@ fn build_with_metadata_diff_dir() {
223244
}),
224245
];
225246

226-
let entries_dir2 = get_entries(&dir_path, &outdir2);
227247
let expected_entries_dir2 = vec![
228248
ScMetaEntry::ScMetaV0(ScMetaV0 {
229249
key: "Description".try_into().unwrap(),
@@ -235,8 +255,8 @@ fn build_with_metadata_diff_dir() {
235255
}),
236256
];
237257

238-
assert_eq!(entries_dir1, expected_entries_dir1);
239-
assert_eq!(entries_dir2, expected_entries_dir2);
258+
assert_eq!(filtered_entries_dir1, expected_entries_dir1);
259+
assert_eq!(filtered_entries_dir2, expected_entries_dir2);
240260
}
241261

242262
fn get_entries(fixture_path: &Path, outdir: &Path) -> Vec<ScMetaEntry> {
@@ -380,3 +400,44 @@ fn remap_absolute_paths() {
380400
assert!(!remap_has_abs_paths);
381401
assert!(noremap_has_abs_paths);
382402
}
403+
404+
#[test]
405+
fn build_always_injects_cli_version() {
406+
let sandbox = TestEnv::default();
407+
let outdir = sandbox.dir().join("out");
408+
let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
409+
let fixture_path = cargo_dir.join("tests/fixtures/workspace/contracts/add");
410+
let temp = TempDir::new().unwrap();
411+
let dir_path = temp.path();
412+
fs_extra::dir::copy(fixture_path, dir_path, &CopyOptions::new()).unwrap();
413+
let dir_path = dir_path.join("add");
414+
415+
// Build contract without any metadata args
416+
sandbox
417+
.new_assert_cmd("contract")
418+
.current_dir(&dir_path)
419+
.arg("build")
420+
.arg("--out-dir")
421+
.arg(&outdir)
422+
.assert()
423+
.success();
424+
425+
let entries = get_entries(&dir_path, &outdir);
426+
427+
// Verify that CLI version is present
428+
let cli_version_entry = entries
429+
.iter()
430+
.find(|entry| matches!(entry, ScMetaEntry::ScMetaV0(ScMetaV0 { key, .. }) if key.to_string() == "cliver"))
431+
.expect("CLI version metadata entry should be present");
432+
433+
let ScMetaEntry::ScMetaV0(ScMetaV0 { val, .. }) = cli_version_entry;
434+
let version_string = val.to_string();
435+
assert!(
436+
version_string.contains('#'),
437+
"CLI version should be in format 'version#git'"
438+
);
439+
assert!(
440+
!version_string.is_empty(),
441+
"CLI version should not be empty"
442+
);
443+
}

cmd/soroban-cli/src/assembled.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub async fn simulate_and_assemble_transaction(
2929
);
3030

3131
let sim_res = client
32-
.simulate_transaction_envelope(&envelope, None, resource_config)
32+
.next_simulate_transaction_envelope(&envelope, None, resource_config)
3333
.await?;
3434
tracing::trace!("{sim_res:#?}");
3535

cmd/soroban-cli/src/commands/contract/build.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::{
1818
use stellar_xdr::curr::{Limited, Limits, ScMetaEntry, ScMetaV0, StringM, WriteXdr};
1919

2020
use crate::{
21-
commands::{contract::optimize, global},
21+
commands::{contract::optimize, global, version},
2222
print::Print,
2323
wasm,
2424
};
@@ -245,7 +245,7 @@ impl Cmd {
245245
.join(&self.profile)
246246
.join(&file);
247247

248-
self.handle_contract_metadata_args(&target_file_path)?;
248+
self.inject_meta(&target_file_path)?;
249249

250250
let final_path = if let Some(out_dir) = &self.out_dir {
251251
fs::create_dir_all(out_dir).map_err(Error::CreatingOutDir)?;
@@ -343,11 +343,7 @@ impl Cmd {
343343
cmd.exec()
344344
}
345345

346-
fn handle_contract_metadata_args(&self, target_file_path: &PathBuf) -> Result<(), Error> {
347-
if self.meta.is_empty() {
348-
return Ok(());
349-
}
350-
346+
fn inject_meta(&self, target_file_path: &PathBuf) -> Result<(), Error> {
351347
let mut wasm_bytes = fs::read(target_file_path).map_err(Error::ReadingWasmFile)?;
352348
let xdr = self.encoded_new_meta()?;
353349
wasm_gen::write_custom_section(&mut wasm_bytes, META_CUSTOM_SECTION_NAME, &xdr);
@@ -360,6 +356,15 @@ impl Cmd {
360356

361357
fn encoded_new_meta(&self) -> Result<Vec<u8>, Error> {
362358
let mut new_meta: Vec<ScMetaEntry> = Vec::new();
359+
360+
// Always inject CLI version
361+
let cli_meta_entry = ScMetaEntry::ScMetaV0(ScMetaV0 {
362+
key: "cliver".to_string().try_into().unwrap(),
363+
val: version::one_line().clone().try_into().unwrap(),
364+
});
365+
new_meta.push(cli_meta_entry);
366+
367+
// Add args provided meta
363368
for (k, v) in self.meta.clone() {
364369
let key: StringM = k
365370
.clone()

cmd/soroban-cli/src/commands/contract/deploy/asset.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use clap::{arg, command, Parser};
1010
use std::convert::Infallible;
1111
use std::{array::TryFromSliceError, fmt::Debug, num::ParseIntError};
1212

13+
use crate::commands::tx::fetch;
1314
use crate::{
1415
assembled::simulate_and_assemble_transaction,
1516
commands::{
@@ -29,24 +30,39 @@ use crate::commands::contract::deploy::utils::alias_validator;
2930
pub enum Error {
3031
#[error("error parsing int: {0}")]
3132
ParseIntError(#[from] ParseIntError),
33+
3234
#[error(transparent)]
3335
Client(#[from] SorobanRpcError),
36+
3437
#[error("internal conversion error: {0}")]
3538
TryFromSliceError(#[from] TryFromSliceError),
39+
3640
#[error("xdr processing error: {0}")]
3741
Xdr(#[from] XdrError),
42+
3843
#[error(transparent)]
3944
Config(#[from] config::Error),
45+
4046
#[error(transparent)]
4147
Data(#[from] data::Error),
48+
4249
#[error(transparent)]
4350
Network(#[from] network::Error),
51+
4452
#[error(transparent)]
4553
Builder(#[from] builder::Error),
54+
4655
#[error(transparent)]
4756
Asset(#[from] builder::asset::Error),
57+
4858
#[error(transparent)]
4959
Locator(#[from] locator::Error),
60+
61+
#[error(transparent)]
62+
Fee(#[from] fetch::fee::Error),
63+
64+
#[error(transparent)]
65+
Fetch(#[from] fetch::Error),
5066
}
5167

5268
impl From<Infallible> for Error {
@@ -152,16 +168,19 @@ impl NetworkRunnable for Cmd {
152168
return Ok(TxnResult::Txn(Box::new(tx)));
153169
}
154170

155-
let txn =
171+
let assembled =
156172
simulate_and_assemble_transaction(&client, &tx, self.fee.resource_config()).await?;
157-
let txn = self.fee.apply_to_assembled_txn(txn).transaction().clone();
173+
let assembled = self.fee.apply_to_assembled_txn(assembled);
174+
175+
let txn = assembled.transaction().clone();
158176
let get_txn_resp = client
159177
.send_transaction_polling(&self.config.sign(txn).await?)
160-
.await?
161-
.try_into()?;
178+
.await?;
179+
180+
self.fee.print_cost_info(&get_txn_resp)?;
162181

163182
if args.is_none_or(|a| !a.no_cache) {
164-
data::write(get_txn_resp, &network.rpc_uri()?)?;
183+
data::write(get_txn_resp.clone().try_into()?, &network.rpc_uri()?)?;
165184
}
166185

167186
Ok(TxnResult::Res(stellar_strkey::Contract(contract_id.0)))

0 commit comments

Comments
 (0)