From 4b2738e96f955904a9cf815e0a0bb947bf8201eb Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 16 Oct 2024 09:22:13 +1000 Subject: [PATCH 01/77] Use attestation in install action (#1675) --- action.yml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index 3ed6af8e7..9b1426d94 100644 --- a/action.yml +++ b/action.yml @@ -15,12 +15,15 @@ runs: run: | mkdir -p $HOME/.local/bin echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Determine version to install + id: version + shell: bash + run: | + echo "version=${{ inputs.version || github.action_ref }}" >> "$GITHUB_OUTPUT" - name: Copy binary to install location shell: bash - env: - REF: ${{ github.action_ref }} run: | - version="${{ inputs.version || env.REF }}" + version="${{ steps.version.outputs.version }}" case "${{ runner.os }}-${{ runner.arch }}" in 'Linux-X64') os_arch=x86_64-unknown-linux-gnu @@ -45,3 +48,17 @@ runs: url="https://github.com/stellar/stellar-cli/releases/download/v$version/$file" echo "$url" curl -fL "$url" | tar xvz -C $HOME/.local/bin + - name: Verify binary against attestation + shell: bash + env: + GH_TOKEN: ${{ github.token }} + run: | + version="${{ steps.version.outputs.version }}" + subject="$(gh attestation verify ~/.local/bin/stellar --repo stellar/stellar-cli --format json -q '.[].verificationResult.signature.certificate.subjectAlternativeName')" + echo "Found subject: $subject" >&2 + expected_subject="https://github.com/stellar/stellar-cli/.github/workflows/binaries.yml@refs/tags/v$version" + echo "Expected subject: $expected_subject" >&2 + if [[ "$subject" != "$expected_subject" ]]; then + echo "Attestation verification found unexpected subject" >&2 + exit 1 + fi From 8b58676d48b71099ccfd7a6efd030d70596ec4ae Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:42:14 +1000 Subject: [PATCH 02/77] Update install instructions to match stellar-docs (#1679) * Update install instructions to match stellar-docs * undo --- README.md | 24 +++++------------------- cmd/stellar-cli/README.md | 7 ++++--- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index c39d883c2..8fadb6740 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,13 @@ This repo is home to the Stellar CLI, the command-line multi-tool for running an - [Documentation](#documentation) - [Cookbook](#cookbook) -- [Installation](#installation) -- [Installation with Experimental Features](#installation-with-experimental-features) +- [Install](#install) - [Autocomplete](#autocomplete) - [Latest Release](#latest-release) - [Upcoming Features](#upcoming-features) - [To Contribute](#to-contribute) - [Additional Developer Resources](#additional-developer-resources) - - ## Documentation For installation options see below, for usage instructions [see the full help docs](FULL_HELP_DOCS.md). @@ -27,28 +24,17 @@ For installation options see below, for usage instructions [see the full help do ## Cookbook To understand how to get the most of the Stellar CLI, see the [Stellar CLI Cookbook](https://github.com/stellar/stellar-cli/tree/main/cookbook) for recipes and a collection of resources to teach you how to use the CLI. Examples of recipes included in the CLI cookbook include: send payments, manage contract lifecycle, extend contract instance/storage/wasm, and more. -## Installation -Install the latest version from source: -``` -cargo install --locked stellar-cli --features opt -``` +## Install -Install with `cargo-binstall`: -``` -cargo install --locked cargo-binstall -cargo binstall -y stellar-cli -``` - -Install with Homebrew: +Install with Homebrew (macOS, Linux): ``` brew install stellar-cli ``` -## Installation with Experimental Features -To use the potentially unreleased bleeding edge CLI functionalities, install from git: +Install the latest version from source: ``` -cargo install --locked stellar-cli --features opt --git https://github.com/stellar/stellar-cli.git +cargo install --locked stellar-cli --features opt ``` ## Autocomplete diff --git a/cmd/stellar-cli/README.md b/cmd/stellar-cli/README.md index 9b95e474a..48be33da7 100644 --- a/cmd/stellar-cli/README.md +++ b/cmd/stellar-cli/README.md @@ -6,12 +6,13 @@ Docs: https://developers.stellar.org ## Install +Install with Homebrew (macOS, Linux): + ``` -cargo install --locked stellar-cli +brew install stellar-cli ``` -To install with the `opt` feature, which includes a WASM optimization feature and wasm-opt built in: - +Install the latest version from source: ``` cargo install --locked stellar-cli --features opt ``` From 3f06e1dd23fd1b892dc1d1fac2cd406dee4fabf4 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:18:11 +1000 Subject: [PATCH 03/77] Remove the `soroban` binary from prebuilt binaries in the release (#1680) --- .github/workflows/binaries.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 08641b9ad..f2f53bd78 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -27,8 +27,6 @@ jobs: crate: - name: stellar-cli binary: stellar - - name: soroban-cli - binary: soroban sys: - os: ubuntu-20.04 # Use 20.04 to get an older version of glibc for increased compat target: x86_64-unknown-linux-gnu From fb6be3131eded3d90f308d0cffd1263dcdb74a56 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Tue, 22 Oct 2024 13:27:08 -0700 Subject: [PATCH 04/77] Add support for plugins using stellar prefix. (#1683) --- Cargo.lock | 4 +++ Cargo.toml | 3 +- Makefile | 1 + .../tests/fixtures/bye/Cargo.lock | 7 ++++ .../tests/fixtures/bye/Cargo.toml | 9 +++++ .../tests/fixtures/bye/src/main.rs | 3 ++ cmd/crates/soroban-test/tests/it/plugin.rs | 34 +++++++++++++------ cmd/soroban-cli/src/commands/plugin.rs | 23 ++++++++++--- 8 files changed, 68 insertions(+), 16 deletions(-) create mode 100644 cmd/crates/soroban-test/tests/fixtures/bye/Cargo.lock create mode 100644 cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml create mode 100644 cmd/crates/soroban-test/tests/fixtures/bye/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 55ebf62a2..e3916c5f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4974,6 +4974,10 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "stellar-bye" +version = "21.5.0" + [[package]] name = "stellar-cli" version = "21.5.0" diff --git a/Cargo.toml b/Cargo.toml index ef052c569..8b10f373d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,9 +6,10 @@ members = [ "cmd/crates/*", "cmd/crates/soroban-test/tests/fixtures/test-wasms/*", "cmd/crates/soroban-test/tests/fixtures/hello", + "cmd/crates/soroban-test/tests/fixtures/bye", ] default-members = ["cmd/soroban-cli", "cmd/crates/soroban-spec-tools", "cmd/crates/soroban-test"] -exclude = ["cmd/crates/soroban-test/tests/fixtures/hello"] +exclude = ["cmd/crates/soroban-test/tests/fixtures/hello", "cmd/crates/soroban-test/tests/fixtures/bye"] [workspace.package] version = "21.5.0" diff --git a/Makefile b/Makefile index 4db0946ce..8a1333bd9 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,7 @@ install_rust: install install: cargo install --force --locked --path ./cmd/stellar-cli --debug cargo install --force --locked --path ./cmd/crates/soroban-test/tests/fixtures/hello --root ./target --debug --quiet + cargo install --force --locked --path ./cmd/crates/soroban-test/tests/fixtures/bye --root ./target --debug --quiet # regenerate the example lib in `cmd/crates/soroban-spec-typsecript/fixtures/ts` build-snapshot: typescript-bindings-fixtures diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.lock b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.lock new file mode 100644 index 000000000..59924f294 --- /dev/null +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "stellar-bye" +version = "0.1.0" diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml new file mode 100644 index 000000000..7678eee5e --- /dev/null +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "stellar-bye" +version = "21.5.0" +edition = "2021" +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/src/main.rs b/cmd/crates/soroban-test/tests/fixtures/bye/src/main.rs new file mode 100644 index 000000000..5fb678863 --- /dev/null +++ b/cmd/crates/soroban-test/tests/fixtures/bye/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Bye, world!"); +} diff --git a/cmd/crates/soroban-test/tests/it/plugin.rs b/cmd/crates/soroban-test/tests/it/plugin.rs index 450902d65..5e5eabee9 100644 --- a/cmd/crates/soroban-test/tests/it/plugin.rs +++ b/cmd/crates/soroban-test/tests/it/plugin.rs @@ -1,7 +1,7 @@ /* -This function calls the soroban executable via cargo and checks that the output +This function calls the stellar executable via cargo and checks that the output is correct. The PATH environment variable is set to include the target/bin -directory, so that the soroban executable can be found. +directory, so that the stellar executable can be found. */ use std::{ffi::OsString, path::PathBuf}; @@ -11,7 +11,7 @@ fn soroban_hello() { // Add the target/bin directory to the iterator of paths let paths = get_paths(); // Call soroban with the PATH variable set to include the target/bin directory - assert_cmd::Command::cargo_bin("soroban") + assert_cmd::Command::cargo_bin("stellar") .unwrap_or_else(|_| assert_cmd::Command::new("soroban")) .arg("hello") .env("PATH", &paths) @@ -19,23 +19,37 @@ fn soroban_hello() { .stdout("Hello, world!\n"); } +#[test] +fn stellar_bye() { + // Add the target/bin directory to the iterator of paths + let paths = get_paths(); + // Call soroban with the PATH variable set to include the target/bin directory + assert_cmd::Command::cargo_bin("stellar") + .unwrap_or_else(|_| assert_cmd::Command::new("stellar")) + .arg("bye") + .env("PATH", &paths) + .assert() + .stdout("Bye, world!\n"); +} + #[test] fn list() { // Call `soroban --list` with the PATH variable set to include the target/bin directory - assert_cmd::Command::cargo_bin("soroban") - .unwrap_or_else(|_| assert_cmd::Command::new("soroban")) + assert_cmd::Command::cargo_bin("stellar") + .unwrap_or_else(|_| assert_cmd::Command::new("stellar")) .arg("--list") .env("PATH", get_paths()) .assert() - .stdout(predicates::str::contains("hello")); + .stdout(predicates::str::contains("hello")) + .stdout(predicates::str::contains("bye")); } #[test] #[cfg(not(unix))] fn has_no_path() { // Call soroban with the PATH variable set to include just target/bin directory - assert_cmd::Command::cargo_bin("soroban") - .unwrap_or_else(|_| assert_cmd::Command::new("soroban")) + assert_cmd::Command::cargo_bin("stellar") + .unwrap_or_else(|_| assert_cmd::Command::new("stellar")) .arg("hello") .env("PATH", target_bin()) .assert() @@ -45,8 +59,8 @@ fn has_no_path() { #[test] fn has_no_path_failure() { // Call soroban with the PATH variable set to include just target/bin directory - assert_cmd::Command::cargo_bin("soroban") - .unwrap_or_else(|_| assert_cmd::Command::new("soroban")) + assert_cmd::Command::cargo_bin("stellar") + .unwrap_or_else(|_| assert_cmd::Command::new("stellar")) .arg("hello") .assert() .stderr(predicates::str::contains("error: no such command: `hello`")); diff --git a/cmd/soroban-cli/src/commands/plugin.rs b/cmd/soroban-cli/src/commands/plugin.rs index 2fa028d5c..d933564f2 100644 --- a/cmd/soroban-cli/src/commands/plugin.rs +++ b/cmd/soroban-cli/src/commands/plugin.rs @@ -1,4 +1,4 @@ -use std::process::Command; +use std::{path::PathBuf, process::Command}; use clap::CommandFactory; use which::which; @@ -44,7 +44,7 @@ pub fn run() -> Result<(), Error> { return Ok(()); } - let bin = which(format!("soroban-{name}")).map_err(|_| { + let bin = find_bin(&name).map_err(|_| { let suggestion = if let Ok(bins) = list() { let suggested_name = bins .iter() @@ -53,6 +53,7 @@ pub fn run() -> Result<(), Error> { .min_by(|a, b| a.1.total_cmp(&b.1)) .map(|(a, _)| a.to_string()) .unwrap_or_default(); + if suggested_name.is_empty() { suggested_name } else { @@ -64,8 +65,10 @@ pub fn run() -> Result<(), Error> { } else { String::new() }; + Error::ExecutableNotFound(name, suggestion) })?; + std::process::exit( Command::new(bin) .args(args) @@ -78,19 +81,29 @@ pub fn run() -> Result<(), Error> { const MAX_HEX_LENGTH: usize = 10; +fn find_bin(name: &str) -> Result { + if let Ok(path) = which(format!("stellar-{name}")) { + Ok(path) + } else { + which(format!("soroban-{name}")) + } +} + pub fn list() -> Result, Error> { let re_str = if cfg!(target_os = "windows") { - r"^soroban-.*.exe$" + r"^(soroban|stellar)-.*.exe$" } else { - r"^soroban-.*" + r"^(soroban|stellar)-.*" }; + let re = regex::Regex::new(re_str)?; + Ok(which::which_re(re)? .filter_map(|b| { let s = b.file_name()?.to_str()?; Some(s.strip_suffix(".exe").unwrap_or(s).to_string()) }) .filter(|s| !(utils::is_hex_string(s) && s.len() > MAX_HEX_LENGTH)) - .map(|s| s.replace("soroban-", "")) + .map(|s| s.replace("soroban-", "").replace("stellar-", "")) .collect()) } From d16fcf1d6dff3d80a1135bce69f33fbb9c10f47b Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Thu, 24 Oct 2024 14:26:32 -0700 Subject: [PATCH 05/77] Favor stellar config dir. (#1681) --- cmd/crates/soroban-test/tests/it/config.rs | 52 +++++++++++++++++++ .../tests/it/integration/hello_world.rs | 4 +- cmd/soroban-cli/src/cli.rs | 6 ++- cmd/soroban-cli/src/config/locator.rs | 24 +++++++-- cmd/soroban-cli/src/print.rs | 1 + cmd/soroban-cli/src/utils.rs | 2 + .../contract-workspace-template/.gitignore | 3 +- 7 files changed, 84 insertions(+), 8 deletions(-) diff --git a/cmd/crates/soroban-test/tests/it/config.rs b/cmd/crates/soroban-test/tests/it/config.rs index 70dfaa693..31d60e116 100644 --- a/cmd/crates/soroban-test/tests/it/config.rs +++ b/cmd/crates/soroban-test/tests/it/config.rs @@ -1,4 +1,5 @@ use assert_fs::TempDir; +use predicates::prelude::predicate; use soroban_test::{AssertExt, TestEnv}; use std::{fs, path::Path}; @@ -288,3 +289,54 @@ fn use_env() { .success() .stdout("SDIY6AQQ75WMD4W46EYB7O6UYMHOCGQHLAQGQTKHDX4J2DYQCHVCQYFD\n"); } + +#[test] +fn config_dirs_precedence() { + let sandbox = TestEnv::default(); + + sandbox + .new_assert_cmd("keys") + .env( + "SOROBAN_SECRET_KEY", + "SC4ZPYELVR7S7EE7KZDZN3ETFTNQHHLTUL34NUAAWZG5OK2RGJ4V2U3Z", + ) + .arg("add") + .arg("alice") + .assert() + .success(); + + fs::rename( + sandbox.dir().join(".stellar"), + sandbox.dir().join("_soroban"), + ) + .unwrap(); + + sandbox + .new_assert_cmd("keys") + .env( + "SOROBAN_SECRET_KEY", + "SAQMV6P3OWM2SKCK3OEWNXSRYWK5RNNUL5CPHQGIJF2WVT4EI2BZ63GG", + ) + .arg("add") + .arg("alice") + .assert() + .success(); + + fs::rename( + sandbox.dir().join("_soroban"), + sandbox.dir().join(".soroban"), + ) + .unwrap(); + + sandbox + .new_assert_cmd("keys") + .arg("show") + .arg("alice") + .arg("--verbose") + .assert() + .success() + .stderr(predicate::str::contains( + "WARN soroban_cli::utils: the .stellar and .soroban config directories exist at path", + )) + .stdout("SAQMV6P3OWM2SKCK3OEWNXSRYWK5RNNUL5CPHQGIJF2WVT4EI2BZ63GG\n"); +} diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index 767c9a07c..272587c53 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -74,7 +74,7 @@ async fn invoke() { .assert() .stdout_as_str(); let dir = sandbox.dir(); - let seed_phrase = std::fs::read_to_string(dir.join(".soroban/identity/test.toml")).unwrap(); + let seed_phrase = std::fs::read_to_string(dir.join(".stellar/identity/test.toml")).unwrap(); let s = toml::from_str::(&seed_phrase).unwrap(); let secret::Secret::SeedPhrase { seed_phrase } = s else { panic!("Expected seed phrase") @@ -113,7 +113,7 @@ async fn invoke() { }, ) .unwrap(); - let sk_from_file = std::fs::read_to_string(dir.join(".soroban/identity/testone.toml")).unwrap(); + let sk_from_file = std::fs::read_to_string(dir.join(".stellar/identity/testone.toml")).unwrap(); assert_eq!(sk_from_file, format!("secret_key = \"{secret_key_1}\"\n")); let secret_key_1_readin = sandbox diff --git a/cmd/soroban-cli/src/cli.rs b/cmd/soroban-cli/src/cli.rs index 5470562db..9183d0e30 100644 --- a/cmd/soroban-cli/src/cli.rs +++ b/cmd/soroban-cli/src/cli.rs @@ -2,8 +2,9 @@ use clap::CommandFactory; use dotenvy::dotenv; use tracing_subscriber::{fmt, EnvFilter}; +use crate::print::Print; use crate::upgrade_check::upgrade_check; -use crate::{commands, print, Root}; +use crate::{commands, Root}; #[tokio::main] pub async fn main() { @@ -42,6 +43,7 @@ pub async fn main() { std::process::exit(1); } }); + // Now use root to setup the logger if let Some(level) = root.global_args.log_level() { let mut e_filter = EnvFilter::from_default_env() @@ -78,7 +80,7 @@ pub async fn main() { upgrade_check(root.global_args.quiet).await; }); - let printer = print::Print::new(root.global_args.quiet); + let printer = Print::new(root.global_args.quiet); if let Err(e) = root.run().await { printer.errorln(format!("error: {e}")); std::process::exit(1); diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 2fad2bb62..70b4f75f8 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -145,7 +145,7 @@ impl Args { pub fn local_config(&self) -> Result { let pwd = self.current_dir()?; - Ok(find_config_dir(pwd.clone()).unwrap_or_else(|_| pwd.join(".soroban"))) + Ok(find_config_dir(pwd.clone()).unwrap_or_else(|_| pwd.join(".stellar"))) } pub fn current_dir(&self) -> Result { @@ -468,14 +468,32 @@ impl KeyType { } pub fn global_config_path() -> Result { - Ok(if let Ok(config_home) = std::env::var("XDG_CONFIG_HOME") { + let config_dir = if let Ok(config_home) = std::env::var("XDG_CONFIG_HOME") { PathBuf::from_str(&config_home).map_err(|_| Error::XdgConfigHome(config_home))? } else { dirs::home_dir() .ok_or(Error::HomeDirNotFound)? .join(".config") + }; + + let soroban_dir = config_dir.join("soroban"); + let stellar_dir = config_dir.join("stellar"); + let soroban_exists = soroban_dir.exists(); + let stellar_exists = stellar_dir.exists(); + + if stellar_exists && soroban_exists { + tracing::warn!("the .stellar and .soroban config directories exist at path {config_dir:?}, using the .stellar"); + } + + if stellar_exists { + return Ok(stellar_dir); } - .join("soroban")) + + if soroban_exists { + return Ok(soroban_dir); + } + + Ok(stellar_dir) } impl Pwd for Args { diff --git a/cmd/soroban-cli/src/print.rs b/cmd/soroban-cli/src/print.rs index 5b8ca2bd2..ca66cdc50 100644 --- a/cmd/soroban-cli/src/print.rs +++ b/cmd/soroban-cli/src/print.rs @@ -8,6 +8,7 @@ use crate::{ const TERMS: &[&str] = &["Apple_Terminal", "vscode"]; +#[derive(Clone)] pub struct Print { pub quiet: bool, } diff --git a/cmd/soroban-cli/src/utils.rs b/cmd/soroban-cli/src/utils.rs index 6e87d15a6..0c4207a4e 100644 --- a/cmd/soroban-cli/src/utils.rs +++ b/cmd/soroban-cli/src/utils.rs @@ -95,10 +95,12 @@ pub fn find_config_dir(mut pwd: std::path::PathBuf) -> std::io::Result Date: Mon, 28 Oct 2024 17:14:51 -0400 Subject: [PATCH 06/77] fix: default value for starting balance in create_account (#1688) The default value parser failed when the string contained underscores. --- FULL_HELP_DOCS.md | 2 +- cmd/soroban-cli/src/commands/tx/new/create_account.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 41575aea0..b3724b98b 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1517,7 +1517,7 @@ Creates and funds a new account with the specified starting balance * `--destination ` — Account Id to create, e.g. `GBX...` * `--starting-balance ` — Initial balance in stroops of the account, default 1 XLM - Default value: `10_000_000` + Default value: `10000000` diff --git a/cmd/soroban-cli/src/commands/tx/new/create_account.rs b/cmd/soroban-cli/src/commands/tx/new/create_account.rs index 967c0cf43..9cc3a62ff 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -11,7 +11,7 @@ pub struct Cmd { #[arg(long)] pub destination: xdr::AccountId, /// Initial balance in stroops of the account, default 1 XLM - #[arg(long, default_value = "10_000_000")] + #[arg(long, default_value = "10000000")] pub starting_balance: i64, } From 1c3f4d274265180217aa348bca2f54e7cbf78cbd Mon Sep 17 00:00:00 2001 From: Gleb Date: Tue, 29 Oct 2024 14:48:45 -0700 Subject: [PATCH 07/77] Enable unit tests for all platforms (#1689) * Test * Comment out flows * rust workflow * fix * fix * Update dependencies and uncomment arm linux * publish dry run test * cleanup * Comment ARM back * undo diff * PR comments --------- Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- .github/workflows/rust.yml | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 048015009..9ae750a77 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -44,7 +44,7 @@ jobs: fail-fast: false matrix: rust: [msrv, latest] - include: + sys: - os: ubuntu-latest-16-cores target: x86_64-unknown-linux-gnu - os: ubuntu-latest-16-cores @@ -55,7 +55,7 @@ jobs: target: aarch64-apple-darwin - os: windows-latest-8-cores target: x86_64-pc-windows-msvc - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.sys.os }} env: CI_TESTS: true steps: @@ -74,17 +74,18 @@ jobs: run: echo RUSTFLAGS='-Dwarnings -Dclippy::all -Dclippy::pedantic' >> $GITHUB_ENV - run: rustup update - run: cargo version - - run: rustup target add ${{ matrix.target }} + - run: rustup target add ${{ matrix.sys.target }} - run: rustup target add wasm32-unknown-unknown - - if: matrix.target == 'aarch64-unknown-linux-gnu' - run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu - - run: cargo clippy --all-targets --target ${{ matrix.target }} + - if: runner.os == 'Linux' + run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev + - run: cargo clippy --all-targets --target ${{ matrix.sys.target }} - run: make build-test - - if: startsWith(matrix.target, 'x86_64') + # TODO: enable ARM linux + - if: startsWith(matrix.sys.target, 'x86_64') || runner.os == 'macOS' # specify directories explicitly (otherwise it will fail with missing symbols) run: | for I in cmd/soroban-cli cmd/crates/* cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world ; do - cargo test --target ${{ matrix.target }} --manifest-path $I/Cargo.toml + cargo test --target ${{ matrix.sys.target }} --manifest-path $I/Cargo.toml done publish-dry-run: @@ -97,10 +98,11 @@ jobs: target: x86_64-unknown-linux-gnu cargo-hack-feature-options: --feature-powerset additional-deb-packages: libudev-dev - # - os: ubuntu-latest-16-cores - # target: aarch64-unknown-linux-gnu - # cargo-hack-feature-options: --feature-powerset - # additional-deb-packages: libudev-dev libssl-dev + # TODO: add back ARM support + #- os: ubuntu-latest-16-cores + # target: aarch64-unknown-linux-gnu + # cargo-hack-feature-options: --feature-powerset + # additional-deb-packages: libudev-dev libssl-dev - os: macos-latest target: x86_64-apple-darwin cargo-hack-feature-options: --feature-powerset From 1fb8559106640a67cfeb2a782e455e25c22ec44e Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:34:39 -0400 Subject: [PATCH 08/77] Feat/add meta on build (#1684) * Refactor to use wasmgen and not re-parse entire wasm file when adding new meta * Add metadata arg to build command --------- Co-authored-by: Willem Wyndham Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- Cargo.lock | 71 ++++++++++++------- FULL_HELP_DOCS.md | 1 + cmd/crates/soroban-spec-tools/src/contract.rs | 20 ++++-- .../workspace/contracts/add/src/lib.rs | 4 +- cmd/crates/soroban-test/tests/it/build.rs | 34 +++++++++ cmd/soroban-cli/Cargo.toml | 1 + .../src/commands/contract/build.rs | 71 ++++++++++++++++--- 7 files changed, 161 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e3916c5f9..ac115d89a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -727,6 +727,12 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" + [[package]] name = "byteorder" version = "1.5.0" @@ -1084,7 +1090,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ - "byteorder", + "byteorder 1.5.0", "digest 0.9.0", "rand_core 0.5.1", "subtle", @@ -2692,6 +2698,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "leb128" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" + [[package]] name = "ledger-apdu" version = "0.10.0" @@ -2719,7 +2731,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45ba81a1f5f24396b37211478aff7fbcd605dd4544df8dbed07b9da3c2057aee" dependencies = [ - "byteorder", + "byteorder 1.5.0", "cfg-if", "hex", "hidapi", @@ -4507,6 +4519,7 @@ dependencies = [ "ulid", "url", "walkdir", + "wasm-gen", "wasm-opt", "wasmparser 0.90.0", "which", @@ -4674,9 +4687,9 @@ version = "21.5.0" [[package]] name = "soroban-ledger-snapshot" -version = "21.7.3" +version = "21.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84589856911dfd6731695c9b51c858aed6d4540118c0a1e5c4c858ea13bc744c" +checksum = "9cf596b2083946a95914a55d7d29cee6a8095b515fd06211851f45bf6af5a496" dependencies = [ "serde", "serde_json", @@ -4715,8 +4728,8 @@ dependencies = [ "serde_json", "soroban-env-guest 21.2.1", "soroban-env-host 21.2.1", - "soroban-ledger-snapshot 21.7.3", - "soroban-sdk-macros 21.7.3", + "soroban-ledger-snapshot 21.7.2", + "soroban-sdk-macros 21.7.2", "stellar-strkey 0.0.8", ] @@ -4739,9 +4752,9 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "21.7.3" +version = "21.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c2173f1aacd56b4405eed71cb2a9694dff99d51ba72d4f0cbc5e4961fdabf4" +checksum = "da03fa00b8ca6e392f013359c06d790d2d379f9c8d6f8a6dfe563ec64311e5d3" dependencies = [ "crate-git-revision 0.0.6", "darling", @@ -4751,8 +4764,8 @@ dependencies = [ "rustc_version", "sha2 0.10.8", "soroban-env-common 21.2.1", - "soroban-spec 21.7.3", - "soroban-spec-rust 21.7.3", + "soroban-spec 21.7.2", + "soroban-spec-rust 21.7.2", "stellar-xdr 21.2.0", "syn 2.0.77", ] @@ -4779,9 +4792,9 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "21.7.3" +version = "21.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7705bffbcc747c08e81698b87b4a787f8b268c25d88f777160091dc1ee8121cb" +checksum = "64c723195463d8742bcb481520bd8b8325da66c39ea236ad46261e6af992e8a8" dependencies = [ "base64 0.13.1", "stellar-xdr 21.2.0", @@ -4817,15 +4830,15 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "21.7.3" +version = "21.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48207ebc8616c2804a17203d1d86c53c3d3c804b682cbab011a135893db1cf78" +checksum = "c0f1b0ec2af54e38f138910f09e101b100130efe625f69ece51c76dd4f06f8b2" dependencies = [ "prettyplease", "proc-macro2", "quote", "sha2 0.10.8", - "soroban-spec 21.7.3", + "soroban-spec 21.7.2", "stellar-xdr 21.2.0", "syn 2.0.77", "thiserror", @@ -4948,7 +4961,7 @@ dependencies = [ "smallvec", "spin", "wasmi_collections", - "wasmi_core 0.36.3", + "wasmi_core 0.36.5", "wasmparser-nostd", ] @@ -4991,7 +5004,7 @@ version = "21.5.0" dependencies = [ "async-trait", "bollard", - "byteorder", + "byteorder 1.5.0", "ed25519-dalek 2.1.1", "env_logger", "futures", @@ -6014,6 +6027,16 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "wasm-gen" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b854b1461005a7b3365742310f7faa3cac3add809d66928c64a40c7e9e842ebb" +dependencies = [ + "byteorder 0.5.3", + "leb128", +] + [[package]] name = "wasm-opt" version = "0.114.2" @@ -6056,9 +6079,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" dependencies = [ "futures-util", "js-sys", @@ -6075,9 +6098,9 @@ checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" [[package]] name = "wasmi_collections" -version = "0.36.3" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1ee1cf2328e7fbb8654fda8449395c64c36ef5a30511e79fae0265a96e1a446" +checksum = "8eddc10bfb0069e913399ebd66c5a72c7d9aceabddcaa0296f062a55ab61d404" dependencies = [ "ahash", "hashbrown 0.14.5", @@ -6098,9 +6121,9 @@ dependencies = [ [[package]] name = "wasmi_core" -version = "0.36.3" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e77c1e701d21edfd263e5c6c940861202c6b840c715040cfdca6211bf8857aa" +checksum = "f08b12621457c17cfd5349cce25029eeac3769b63b1b02bd850d595a00f375ff" dependencies = [ "downcast-rs", "libm", @@ -6442,7 +6465,7 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "byteorder", + "byteorder 1.5.0", "zerocopy-derive", ] diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index b3724b98b..8c151cb84 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -334,6 +334,7 @@ To view the commands that will be executed, without executing them, use the --pr If ommitted, wasm files are written only to the cargo target directory. * `--print-commands-only` — Print commands to build without executing them +* `--meta ` — Add key-value to contract meta (adds the meta to the `contractmetav0` custom section) diff --git a/cmd/crates/soroban-spec-tools/src/contract.rs b/cmd/crates/soroban-spec-tools/src/contract.rs index 9984a19d1..501609111 100644 --- a/cmd/crates/soroban-spec-tools/src/contract.rs +++ b/cmd/crates/soroban-spec-tools/src/contract.rs @@ -40,9 +40,9 @@ pub enum Error { impl Spec { pub fn new(bytes: &[u8]) -> Result { - let mut env_meta: Option<&[u8]> = None; - let mut meta: Option<&[u8]> = None; - let mut spec: Option<&[u8]> = None; + let mut env_meta: Option> = None; + let mut meta: Option> = None; + let mut spec: Option> = None; for payload in wasmparser::Parser::new(0).parse_all(bytes) { let payload = payload?; if let wasmparser::Payload::CustomSection(section) = payload { @@ -52,13 +52,19 @@ impl Spec { "contractspecv0" => &mut spec, _ => continue, }; - *out = Some(section.data()); + + if let Some(existing_data) = out { + let combined_data = [existing_data, section.data()].concat(); + *out = Some(combined_data); + } else { + *out = Some(section.data().to_vec()); + } }; } let mut env_meta_base64 = None; let env_meta = if let Some(env_meta) = env_meta { - env_meta_base64 = Some(base64.encode(env_meta)); + env_meta_base64 = Some(base64.encode(&env_meta)); let cursor = Cursor::new(env_meta); let mut read = Limited::new(cursor, Limits::none()); ScEnvMetaEntry::read_xdr_iter(&mut read).collect::, xdr::Error>>()? @@ -68,7 +74,7 @@ impl Spec { let mut meta_base64 = None; let meta = if let Some(meta) = meta { - meta_base64 = Some(base64.encode(meta)); + meta_base64 = Some(base64.encode(&meta)); let cursor = Cursor::new(meta); let mut depth_limit_read = Limited::new(cursor, Limits::none()); ScMetaEntry::read_xdr_iter(&mut depth_limit_read) @@ -78,7 +84,7 @@ impl Spec { }; let (spec_base64, spec) = if let Some(spec) = spec { - let (spec_base64, spec) = Spec::spec_to_base64(spec)?; + let (spec_base64, spec) = Spec::spec_to_base64(&spec)?; (Some(spec_base64), spec) } else { (None, vec![]) diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/src/lib.rs index 1552f5855..d04162b5a 100644 --- a/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/src/lib.rs +++ b/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/src/lib.rs @@ -1,9 +1,11 @@ #![no_std] -use soroban_sdk::{contract, contractimpl}; +use soroban_sdk::{contract, contractimpl, contractmeta}; #[contract] pub struct Contract; +contractmeta!(key = "Description", val = "A test add contract"); + #[contractimpl] impl Contract { pub fn add(x: u64, y: u64) -> u128 { diff --git a/cmd/crates/soroban-test/tests/it/build.rs b/cmd/crates/soroban-test/tests/it/build.rs index aba6aadf5..925d88df1 100644 --- a/cmd/crates/soroban-test/tests/it/build.rs +++ b/cmd/crates/soroban-test/tests/it/build.rs @@ -116,3 +116,37 @@ cargo rustc --manifest-path=contracts/add/Cargo.toml --crate-type=cdylib --targe ", )); } + +#[test] +fn build_with_metadata() { + let sandbox = TestEnv::default(); + let cargo_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let fixture_path = cargo_dir.join("tests/fixtures/workspace/contracts/add"); + let outdir = sandbox.dir().join("out"); + + sandbox + .new_assert_cmd("contract") + .current_dir(&fixture_path) + .arg("build") + .arg("--meta") + .arg("contract meta=added on build") + .arg("--out-dir") + .arg(&outdir) + .assert() + .success(); + + // verify that the metadata added in the contract code via contractmetadata! macro is present + // as well as the meta that is included on build + let wasm_path = fixture_path.join(&outdir).join("add.wasm"); + sandbox + .new_assert_cmd("contract") + .current_dir(&fixture_path) + .arg("info") + .arg("meta") + .arg("--wasm") + .arg(wasm_path) + .assert() + .success() + .stdout(predicate::str::contains("Description: A test add contract")) + .stdout(predicate::str::contains("contract meta: added on build")); +} diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 0cc12e74f..78c3974f3 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -124,6 +124,7 @@ glob = "0.3.1" fqdn = "0.3.12" open = "5.3.0" url = "2.5.2" +wasm-gen = "0.1.4" [build-dependencies] crate-git-revision = "0.0.4" diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index c71327a38..01ccce311 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -1,3 +1,4 @@ +use cargo_metadata::{Metadata, MetadataCommand, Package}; use clap::Parser; use itertools::Itertools; use std::{ @@ -9,8 +10,7 @@ use std::{ path::{self, Path, PathBuf}, process::{Command, ExitStatus, Stdio}, }; - -use cargo_metadata::{Metadata, MetadataCommand, Package}; +use stellar_xdr::curr::{Limits, ScMetaEntry, ScMetaV0, StringM, WriteXdr}; /// Build a contract from source /// @@ -62,6 +62,20 @@ pub struct Cmd { /// Print commands to build without executing them #[arg(long, conflicts_with = "out_dir", help_heading = "Other")] pub print_commands_only: bool, + /// Add key-value to contract meta (adds the meta to the `contractmetav0` custom section) + #[arg(long, num_args=1, value_parser=parse_meta_arg, action=clap::ArgAction::Append, help_heading = "Metadata")] + pub meta: Vec<(String, String)>, +} + +fn parse_meta_arg(s: &str) -> Result<(String, String), Error> { + let parts = s.splitn(2, '='); + + let (key, value) = parts + .map(str::trim) + .next_tuple() + .ok_or_else(|| Error::MetaArg("must be in the form 'key=value'".to_string()))?; + + Ok((key.to_string(), value.to_string())) } #[derive(thiserror::Error, Debug)] @@ -82,8 +96,17 @@ pub enum Error { CopyingWasmFile(io::Error), #[error("getting the current directory: {0}")] GettingCurrentDir(io::Error), + #[error("reading wasm file: {0}")] + ReadingWasmFile(io::Error), + #[error("writing wasm file: {0}")] + WritingWasmFile(io::Error), + #[error("invalid meta entry: {0}")] + MetaArg(String), } +const WASM_TARGET: &str = "wasm32-unknown-unknown"; +const META_CUSTOM_SECTION_NAME: &str = "contractmetav0"; + impl Cmd { pub fn run(&self) -> Result<(), Error> { let working_dir = env::current_dir().map_err(Error::GettingCurrentDir)?; @@ -111,7 +134,7 @@ impl Cmd { manifest_path.to_string_lossy() )); cmd.arg("--crate-type=cdylib"); - cmd.arg("--target=wasm32-unknown-unknown"); + cmd.arg(format!("--target={WASM_TARGET}")); if self.profile == "release" { cmd.arg("--release"); } else { @@ -145,14 +168,16 @@ impl Cmd { return Err(Error::Exit(status)); } + let file = format!("{}.wasm", p.name.replace('-', "_")); + let target_file_path = Path::new(target_dir) + .join(WASM_TARGET) + .join(&self.profile) + .join(&file); + + self.handle_contract_metadata_args(&target_file_path)?; + if let Some(out_dir) = &self.out_dir { fs::create_dir_all(out_dir).map_err(Error::CreatingOutDir)?; - - let file = format!("{}.wasm", p.name.replace('-', "_")); - let target_file_path = Path::new(target_dir) - .join("wasm32-unknown-unknown") - .join(&self.profile) - .join(&file); let out_file_path = Path::new(out_dir).join(&file); fs::copy(target_file_path, out_file_path).map_err(Error::CopyingWasmFile)?; } @@ -228,4 +253,32 @@ impl Cmd { // the output. cmd.exec() } + + fn handle_contract_metadata_args(&self, target_file_path: &PathBuf) -> Result<(), Error> { + if self.meta.is_empty() { + return Ok(()); + } + + let mut wasm_bytes = fs::read(target_file_path).map_err(Error::ReadingWasmFile)?; + + for (k, v) in self.meta.clone() { + let key: StringM = k + .clone() + .try_into() + .map_err(|e| Error::MetaArg(format!("{k} is an invalid metadata key: {e}")))?; + + let val: StringM = v + .clone() + .try_into() + .map_err(|e| Error::MetaArg(format!("{v} is an invalid metadata value: {e}")))?; + let meta_entry = ScMetaEntry::ScMetaV0(ScMetaV0 { key, val }); + let xdr: Vec = meta_entry + .to_xdr(Limits::none()) + .map_err(|e| Error::MetaArg(format!("failed to encode metadata entry: {e}")))?; + + wasm_gen::write_custom_section(&mut wasm_bytes, META_CUSTOM_SECTION_NAME, &xdr); + } + + fs::write(target_file_path, wasm_bytes).map_err(Error::WritingWasmFile) + } } From 519c6fa373ddc50e030fb3e49f91f3eae8b00aff Mon Sep 17 00:00:00 2001 From: "Thomas M. DuBuisson" Date: Wed, 30 Oct 2024 15:56:48 -0700 Subject: [PATCH 09/77] Make flake install work (#1686) * Do not use SHELL (default shell) but $0 (current shell) * Cleanup shell hook * Update flake to support profile install * Update stellar rpc hash * Make name match binary for easy execution * Add nix to readme * Remove 'NOREPO' git fallback * Add wasm to test dep, make wasm test files, ignore test not being in git repo * remove old comment * tweak README.md * Revert "Add wasm to test dep, make wasm test files, ignore test not being in git repo" This reverts commit b8268d9cda0def409a04d62cc5077f402d25748f. --------- Co-authored-by: Gleb Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- Makefile | 2 +- README.md | 7 +++++++ flake.lock | 12 ++++++------ flake.nix | 36 +++++++++++++++++++++++++++++------- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 8a1333bd9..f534410e0 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ endif # By default make `?=` operator will treat empty assignment as a set value and will not use the default value. # Both cases should fallback to default of getting the version from git tag. ifeq ($(strip $(REPOSITORY_VERSION)),) - override REPOSITORY_VERSION = "$(shell git describe --tags --always --abbrev=0 --match='v[0-9]*.[0-9]*.[0-9]*' 2> /dev/null | sed 's/^.//')" + override REPOSITORY_VERSION = "$(shell ( git describe --tags --always --abbrev=0 --match='v[0-9]*.[0-9]*.[0-9]*' 2> /dev/null | sed 's/^.//' ) )" endif REPOSITORY_BRANCH := "$(shell git rev-parse --abbrev-ref HEAD)" BUILD_TIMESTAMP ?= $(shell date '+%Y-%m-%dT%H:%M:%S') diff --git a/README.md b/README.md index 8fadb6740..381f5a3dd 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,13 @@ Install the latest version from source: cargo install --locked stellar-cli --features opt ``` +Install or run the unreleased main branch with nix: +``` +% nix run 'github:stellar/stellar-cli' -- --help +or install +% nix profile install github:stellar/stellar-cli +``` + ## Autocomplete The Stellar CLI supports some autocompletion. To set up, run the following commands: diff --git a/flake.lock b/flake.lock index fef18714e..fd92bacb2 100644 --- a/flake.lock +++ b/flake.lock @@ -36,11 +36,11 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1718428119, - "narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=", + "lastModified": 1728538411, + "narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5", + "rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221", "type": "github" }, "original": { @@ -62,11 +62,11 @@ "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1727144949, - "narHash": "sha256-uMZMjoCS2nf40TAE1686SJl3OXWfdfM+BDEfRdr+uLc=", + "lastModified": 1729823394, + "narHash": "sha256-RiinJqorqSLKh1oSpiMHnBe6nQdJzE45lX6fSnAuDnI=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "2e19799819104b46019d339e78d21c14372d3666", + "rev": "7e52e80f5faa374ad4c607d62c6d362589cb523f", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 1923d75bb..0a30ea556 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "stellar-cli development shell"; + description = "stellar-cli"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; @@ -14,14 +14,13 @@ pkgs = import nixpkgs { inherit system overlays; }; - in - with pkgs; - { - devShells.default = mkShell { - nativeBuildInputs = lib.optionals (stdenv.isDarwin) [ + stellardev = { + name = "stellar"; + src = ./.; + nativeBuildInputs = pkgs.lib.optionals (pkgs.stdenv.isDarwin) [ pkgs.darwin.apple_sdk.frameworks.SystemConfiguration ]; - buildInputs = [ + buildInputs = with pkgs; [ openssl pkg-config jq @@ -31,6 +30,29 @@ }) ] ++ lib.optionals (stdenv.isLinux) [libudev-zero]; }; + stellarcli = stellardev // { + cargoLock = { + lockFile = ./Cargo.lock; + }; + + cargoLock.outputHashes = { + # The only git+https dependency in Cargo.lock + "stellar-rpc-client-21.4.0" = "sha256-ue7Ynux9YaDP3f/XkHz2OPd2g0iCX5R0yS5SaVHEYxQ"; + }; + + doCheck = false; + + GIT_REVISION = "${self.rev or self.dirtyRev or "unknown"}"; + }; + rustPlatformMod = pkgs.makeRustPlatform { + cargo = pkgs.rust-bin.stable.latest.default; + rustc = pkgs.rust-bin.stable.latest.default; + }; + in + with pkgs; + { + devShells.default = mkShell stellardev; + packages.default = rustPlatformMod.buildRustPackage stellarcli; } ); } From bd1ef305d226c2151cf186b95fa33b6a891c28dd Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 1 Nov 2024 12:13:30 -0400 Subject: [PATCH 10/77] feat: add help headings for global command options (#1696) --- cmd/soroban-cli/src/commands/global.rs | 12 ++++++------ cmd/soroban-cli/src/commands/mod.rs | 1 + cmd/soroban-cli/src/config/locator.rs | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cmd/soroban-cli/src/commands/global.rs b/cmd/soroban-cli/src/commands/global.rs index be883b6fd..02c0b3b58 100644 --- a/cmd/soroban-cli/src/commands/global.rs +++ b/cmd/soroban-cli/src/commands/global.rs @@ -4,7 +4,7 @@ use clap::{ }; use std::path::PathBuf; -use super::config; +use super::{config, HEADING_GLOBAL}; const USAGE_STYLES: Styles = Styles::styled() .header(AnsiColor::Green.on_default().effects(Effects::BOLD)) @@ -24,19 +24,19 @@ pub struct Args { pub locator: config::locator::Args, /// Filter logs output. To turn on `stellar_cli::log::footprint=debug` or off `=off`. Can also use env var `RUST_LOG`. - #[arg(long, short = 'f', global = true)] + #[arg(long, short = 'f', global = true, help_heading = HEADING_GLOBAL)] pub filter_logs: Vec, /// Do not write logs to stderr including `INFO` - #[arg(long, short = 'q', global = true)] + #[arg(long, short = 'q', global = true, help_heading = HEADING_GLOBAL)] pub quiet: bool, /// Log DEBUG events - #[arg(long, short = 'v', global = true)] + #[arg(long, short = 'v', global = true, help_heading = HEADING_GLOBAL)] pub verbose: bool, /// Log DEBUG and TRACE events - #[arg(long, visible_alias = "vv", global = true)] + #[arg(long, visible_alias = "vv", global = true, help_heading = HEADING_GLOBAL)] pub very_verbose: bool, /// List installed plugins. E.g. `stellar-hello` @@ -44,7 +44,7 @@ pub struct Args { pub list: bool, /// Do not cache your simulations and transactions - #[arg(long, env = "STELLAR_NO_CACHE", global = true)] + #[arg(long, env = "STELLAR_NO_CACHE", global = true, help_heading = HEADING_GLOBAL)] pub no_cache: bool, } diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index 0a1d4629b..a6a85e816 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -20,6 +20,7 @@ pub mod version; pub mod txn_result; pub const HEADING_RPC: &str = "Options (RPC)"; +pub const HEADING_GLOBAL: &str = "Options (Global)"; const ABOUT: &str = "Work seamlessly with Stellar accounts, contracts, and assets from the command line. diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 70b4f75f8..0a13c4cc3 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -12,7 +12,7 @@ use std::{ }; use stellar_strkey::{Contract, DecodeError}; -use crate::{utils::find_config_dir, Pwd}; +use crate::{commands::HEADING_GLOBAL, utils::find_config_dir, Pwd}; use super::{ alias, @@ -82,11 +82,11 @@ pub enum Error { #[group(skip)] pub struct Args { /// Use global config - #[arg(long, global = true)] + #[arg(long, global = true, help_heading = HEADING_GLOBAL)] pub global: bool, /// Location of config directory, default is "." - #[arg(long, global = true)] + #[arg(long, global = true, help_heading = HEADING_GLOBAL)] pub config_dir: Option, } From caf6e43bd593de790538e5fd43b73690d5c8ae38 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 1 Nov 2024 20:10:54 -0400 Subject: [PATCH 11/77] fix: update stellar dependencies (#1695) Still need to update soroban client to a released version. Otherwise just updating to newest release candidates --- Cargo.lock | 171 +++++++++++++++++------------------------------------ Cargo.toml | 12 ++-- 2 files changed, 59 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac115d89a..4e292f191 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -241,12 +241,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - [[package]] name = "ascii-canvas" version = "3.0.0" @@ -1948,9 +1942,6 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", -] [[package]] name = "heck" @@ -2896,12 +2887,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "multi-stash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685a9ac4b61f4e728e1d2c6a7844609c16527aeb5e6c865915c08e619c16410f" - [[package]] name = "native-tls" version = "0.2.12" @@ -3794,9 +3779,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -4429,9 +4414,9 @@ dependencies = [ [[package]] name = "soroban-builtin-sdk-macros" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4c8668199d95e3061cd42e1b96a91451c656a238a607fa53f96f0a3fdcf5f3" +checksum = "c45d2492cd44f05cc79eeb857985f153f12a4423ce51b4b746b5925024c473b1" dependencies = [ "itertools 0.10.5", "proc-macro2", @@ -4492,11 +4477,11 @@ dependencies = [ "serde_json", "sha2 0.10.8", "shlex", - "soroban-ledger-snapshot 22.0.0-rc.1.1", - "soroban-sdk 22.0.0-rc.1.1", - "soroban-spec 22.0.0-rc.1.1", + "soroban-ledger-snapshot 22.0.0-rc.3", + "soroban-sdk 22.0.0-rc.3", + "soroban-spec 22.0.0-rc.3", "soroban-spec-json", - "soroban-spec-rust 22.0.0-rc.1.1", + "soroban-spec-rust 22.0.0-rc.3", "soroban-spec-tools", "soroban-spec-typescript", "stellar-rpc-client", @@ -4538,7 +4523,7 @@ dependencies = [ "num-traits", "serde", "soroban-env-macros 21.2.1", - "soroban-wasmi 0.31.1-soroban.20.0.1", + "soroban-wasmi", "static_assertions", "stellar-xdr 21.2.0", "wasmparser 0.116.1", @@ -4546,17 +4531,17 @@ dependencies = [ [[package]] name = "soroban-env-common" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdf1d66133d6b29e2834acea79decb57c47c71aa01885cae2b9ad621d67525c" +checksum = "39b6d2ec8955243394278e1fae88be3b367fcfed9cf74e5044799a90786a8642" dependencies = [ "crate-git-revision 0.0.6", "ethnum", "num-derive", "num-traits", "serde", - "soroban-env-macros 22.0.0-rc.1.1", - "soroban-wasmi 0.36.1-soroban.22.0.0", + "soroban-env-macros 22.0.0-rc.3", + "soroban-wasmi", "static_assertions", "stellar-xdr 22.0.0-rc.1.1", "wasmparser 0.116.1", @@ -4574,11 +4559,11 @@ dependencies = [ [[package]] name = "soroban-env-guest" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9610ac8a4a900e6f35b2ed171bc325c7e9883929f5e9da758e85f1226dd284" +checksum = "4002fc582cd20cc9b9fbb73959bc5d6b5b15feda11485cbfab0c28e78ecbab3e" dependencies = [ - "soroban-env-common 22.0.0-rc.1.1", + "soroban-env-common 22.0.0-rc.3", "static_assertions", ] @@ -4609,7 +4594,7 @@ dependencies = [ "sha3", "soroban-builtin-sdk-macros 21.2.1", "soroban-env-common 21.2.1", - "soroban-wasmi 0.31.1-soroban.20.0.1", + "soroban-wasmi", "static_assertions", "stellar-strkey 0.0.8", "wasmparser 0.116.1", @@ -4617,9 +4602,9 @@ dependencies = [ [[package]] name = "soroban-env-host" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c695d22888ede1f98c016a4a690be307817d133be0e0f32a25fd6e53bb6c929" +checksum = "8cb9be0260d39a648db0d33e1c6f8f494ec0c4f5be2b8a0a4e15ed4b7c6a92b0" dependencies = [ "ark-bls12-381", "ark-ec", @@ -4643,9 +4628,9 @@ dependencies = [ "sec1", "sha2 0.10.8", "sha3", - "soroban-builtin-sdk-macros 22.0.0-rc.1.1", - "soroban-env-common 22.0.0-rc.1.1", - "soroban-wasmi 0.36.1-soroban.22.0.0", + "soroban-builtin-sdk-macros 22.0.0-rc.3", + "soroban-env-common 22.0.0-rc.3", + "soroban-wasmi", "static_assertions", "stellar-strkey 0.0.9", "wasmparser 0.116.1", @@ -4668,9 +4653,9 @@ dependencies = [ [[package]] name = "soroban-env-macros" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d926d0daa3ba798cd70ce962ea10012e630d75088352369a6d248b2644dd7a2c" +checksum = "a328297a568ae98999fdb06902e3362dfd8a2bfa9abea40beaeb7dc93a402fe7" dependencies = [ "itertools 0.10.5", "proc-macro2", @@ -4701,15 +4686,15 @@ dependencies = [ [[package]] name = "soroban-ledger-snapshot" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07ca63290730b803f0637e00994f803d2f24cc6383ac8680724050d07690a89" +checksum = "56375490f176006a636db0e50c2269c55626e0ff7222711bb78d77028376fe0d" dependencies = [ "serde", "serde_json", "serde_with", - "soroban-env-common 22.0.0-rc.1.1", - "soroban-env-host 22.0.0-rc.1.1", + "soroban-env-common 22.0.0-rc.3", + "soroban-env-host 22.0.0-rc.3", "thiserror", ] @@ -4735,18 +4720,19 @@ dependencies = [ [[package]] name = "soroban-sdk" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b715e15357dbdda2fe0626005b75c2253bb3786deec3001d4077462a9dadd3" +checksum = "6d063d0df000aaec20105aab3d743660322bc0269934ea95d79fa19aa8792385" dependencies = [ "bytes-lit", "rand", + "rustc_version", "serde", "serde_json", - "soroban-env-guest 22.0.0-rc.1.1", - "soroban-env-host 22.0.0-rc.1.1", - "soroban-ledger-snapshot 22.0.0-rc.1.1", - "soroban-sdk-macros 22.0.0-rc.1.1", + "soroban-env-guest 22.0.0-rc.3", + "soroban-env-host 22.0.0-rc.3", + "soroban-ledger-snapshot 22.0.0-rc.3", + "soroban-sdk-macros 22.0.0-rc.3", "stellar-strkey 0.0.9", ] @@ -4772,9 +4758,9 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00d1b8d96ccf53ea9c30d86352756cace630ca5c7e1200fff32ffc793bedd593" +checksum = "508c9d819a05109120664aab86c371e1b72c5bea20b1a13158b4ef7948d9f673" dependencies = [ "crate-git-revision 0.0.6", "darling", @@ -4783,9 +4769,9 @@ dependencies = [ "quote", "rustc_version", "sha2 0.10.8", - "soroban-env-common 22.0.0-rc.1.1", - "soroban-spec 22.0.0-rc.1.1", - "soroban-spec-rust 22.0.0-rc.1.1", + "soroban-env-common 22.0.0-rc.3", + "soroban-spec 22.0.0-rc.3", + "soroban-spec-rust 22.0.0-rc.3", "stellar-xdr 22.0.0-rc.1.1", "syn 2.0.77", ] @@ -4804,9 +4790,9 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4603430fd36848da7189e758d7f3fe1d7bbfef024e8aad2230a8be8252a583c1" +checksum = "69001c97783ed3ce197eac2404e7beeabedd16e40e6f0aa210d1bc6a13063c33" dependencies = [ "base64 0.13.1", "stellar-xdr 22.0.0-rc.1.1", @@ -4823,7 +4809,7 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.9.9", - "soroban-spec 22.0.0-rc.1.1", + "soroban-spec 22.0.0-rc.3", "stellar-xdr 22.0.0-rc.1.1", "thiserror", ] @@ -4846,15 +4832,15 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "22.0.0-rc.1.1" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d5f3fe5b27e0b1c1d9ecdff04c4e31f5cd4d12cdc052d54f0e4995cf637b9c" +checksum = "a45dbf346f91ed23ea63b1c256c522da9e6f0e2db1887b990a8f0f1d842a3093" dependencies = [ "prettyplease", "proc-macro2", "quote", "sha2 0.10.8", - "soroban-spec 22.0.0-rc.1.1", + "soroban-spec 22.0.0-rc.3", "stellar-xdr 22.0.0-rc.1.1", "syn 2.0.77", "thiserror", @@ -4869,7 +4855,7 @@ dependencies = [ "hex", "itertools 0.10.5", "serde_json", - "soroban-spec 22.0.0-rc.1.1", + "soroban-spec 22.0.0-rc.3", "stellar-strkey 0.0.11", "stellar-xdr 22.0.0-rc.1.1", "thiserror", @@ -4892,7 +4878,7 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.9.9", - "soroban-spec 22.0.0-rc.1.1", + "soroban-spec 22.0.0-rc.3", "stellar-xdr 22.0.0-rc.1.1", "temp-dir", "thiserror", @@ -4913,8 +4899,8 @@ dependencies = [ "serde_json", "sha2 0.10.8", "soroban-cli", - "soroban-ledger-snapshot 22.0.0-rc.1.1", - "soroban-spec 22.0.0-rc.1.1", + "soroban-ledger-snapshot 22.0.0-rc.3", + "soroban-spec 22.0.0-rc.3", "soroban-spec-tools", "stellar-rpc-client", "stellar-strkey 0.0.11", @@ -4944,24 +4930,7 @@ dependencies = [ "smallvec", "spin", "wasmi_arena", - "wasmi_core 0.13.0", - "wasmparser-nostd", -] - -[[package]] -name = "soroban-wasmi" -version = "0.36.1-soroban.22.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7044ea0ee6ff67039df1f232f0d3d98121f69a0409e944774912fc5f043c280f" -dependencies = [ - "arrayvec", - "multi-stash", - "num-derive", - "num-traits", - "smallvec", - "spin", - "wasmi_collections", - "wasmi_core 0.36.5", + "wasmi_core", "wasmparser-nostd", ] @@ -5025,7 +4994,7 @@ dependencies = [ "serial_test", "sha2 0.9.9", "slip10", - "soroban-spec 22.0.0-rc.1.1", + "soroban-spec 22.0.0-rc.3", "stellar-rpc-client", "stellar-strkey 0.0.11", "stellar-xdr 22.0.0-rc.1.1", @@ -5039,7 +5008,7 @@ dependencies = [ [[package]] name = "stellar-rpc-client" version = "21.4.0" -source = "git+https://github.com/stellar/rs-stellar-rpc-client?branch=main#7554d4c87c026313a1f5b3c7ae66a92b5ff7e091" +source = "git+https://github.com/stellar/rs-stellar-rpc-client?rev=7554d4c87c026313a1f5b3c7ae66a92b5ff7e091#7554d4c87c026313a1f5b3c7ae66a92b5ff7e091" dependencies = [ "clap", "hex", @@ -5128,17 +5097,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "string-interner" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c6a0d765f5807e98a091107bae0a56ea3799f66a5de47b2c84c94a39c09974e" -dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "serde", -] - [[package]] name = "string_cache" version = "0.8.7" @@ -6096,17 +6054,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" -[[package]] -name = "wasmi_collections" -version = "0.36.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eddc10bfb0069e913399ebd66c5a72c7d9aceabddcaa0296f062a55ab61d404" -dependencies = [ - "ahash", - "hashbrown 0.14.5", - "string-interner", -] - [[package]] name = "wasmi_core" version = "0.13.0" @@ -6119,18 +6066,6 @@ dependencies = [ "paste", ] -[[package]] -name = "wasmi_core" -version = "0.36.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f08b12621457c17cfd5349cce25029eeac3769b63b1b02bd850d595a00f375ff" -dependencies = [ - "downcast-rs", - "libm", - "num-traits", - "paste", -] - [[package]] name = "wasmparser" version = "0.90.0" diff --git a/Cargo.toml b/Cargo.toml index 8b10f373d..58caad196 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,26 +39,26 @@ default-features = true # Dependencies from the rs-soroban-sdk repo: [workspace.dependencies.soroban-spec] -version = "=22.0.0-rc.1.1" +version = "=22.0.0-rc.3" [workspace.dependencies.soroban-spec-rust] -version = "=22.0.0-rc.1.1" +version = "=22.0.0-rc.3" [workspace.dependencies.soroban-sdk] -version = "=22.0.0-rc.1.1" +version = "=22.0.0-rc.3" [workspace.dependencies.soroban-token-sdk] -version = "=22.0.0-rc.1.1" +version = "=22.0.0-rc.3" [workspace.dependencies.soroban-ledger-snapshot] -version = "=22.0.0-rc.1.1" +version = "=22.0.0-rc.3" # Dependencies from the rs-stellar-rpc-client repo: [workspace.dependencies.soroban-rpc] package = "stellar-rpc-client" version = "21.4.0" git = "https://github.com/stellar/rs-stellar-rpc-client" -branch = "main" +rev = "7554d4c87c026313a1f5b3c7ae66a92b5ff7e091" # Dependencies from elsewhere shared by crates: [workspace.dependencies] From e44b89f946aed2e8cf63eb1acd077a95810c0547 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 3 Nov 2024 16:58:48 -0700 Subject: [PATCH 12/77] Remove absolute registry paths from panic messages in wasm (#1594) --- Cargo.lock | 37 +++-- cmd/soroban-cli/Cargo.toml | 2 +- .../src/commands/contract/build.rs | 131 +++++++++++++++++- cmd/soroban-cli/src/commands/contract/mod.rs | 2 +- 4 files changed, 150 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e292f191..6fdf9ee5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4278,6 +4278,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-escape" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" + [[package]] name = "shlex" version = "1.3.0" @@ -4476,6 +4482,7 @@ dependencies = [ "serde-aux", "serde_json", "sha2 0.10.8", + "shell-escape", "shlex", "soroban-ledger-snapshot 22.0.0-rc.3", "soroban-sdk 22.0.0-rc.3", @@ -4672,9 +4679,9 @@ version = "21.5.0" [[package]] name = "soroban-ledger-snapshot" -version = "21.7.2" +version = "21.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf596b2083946a95914a55d7d29cee6a8095b515fd06211851f45bf6af5a496" +checksum = "84589856911dfd6731695c9b51c858aed6d4540118c0a1e5c4c858ea13bc744c" dependencies = [ "serde", "serde_json", @@ -4713,8 +4720,8 @@ dependencies = [ "serde_json", "soroban-env-guest 21.2.1", "soroban-env-host 21.2.1", - "soroban-ledger-snapshot 21.7.2", - "soroban-sdk-macros 21.7.2", + "soroban-ledger-snapshot 21.7.3", + "soroban-sdk-macros 21.7.3", "stellar-strkey 0.0.8", ] @@ -4738,9 +4745,9 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "21.7.2" +version = "21.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da03fa00b8ca6e392f013359c06d790d2d379f9c8d6f8a6dfe563ec64311e5d3" +checksum = "63c2173f1aacd56b4405eed71cb2a9694dff99d51ba72d4f0cbc5e4961fdabf4" dependencies = [ "crate-git-revision 0.0.6", "darling", @@ -4750,8 +4757,8 @@ dependencies = [ "rustc_version", "sha2 0.10.8", "soroban-env-common 21.2.1", - "soroban-spec 21.7.2", - "soroban-spec-rust 21.7.2", + "soroban-spec 21.7.3", + "soroban-spec-rust 21.7.3", "stellar-xdr 21.2.0", "syn 2.0.77", ] @@ -4778,9 +4785,9 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "21.7.2" +version = "21.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c723195463d8742bcb481520bd8b8325da66c39ea236ad46261e6af992e8a8" +checksum = "7705bffbcc747c08e81698b87b4a787f8b268c25d88f777160091dc1ee8121cb" dependencies = [ "base64 0.13.1", "stellar-xdr 21.2.0", @@ -4816,15 +4823,15 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "21.7.2" +version = "21.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f1b0ec2af54e38f138910f09e101b100130efe625f69ece51c76dd4f06f8b2" +checksum = "48207ebc8616c2804a17203d1d86c53c3d3c804b682cbab011a135893db1cf78" dependencies = [ "prettyplease", "proc-macro2", "quote", "sha2 0.10.8", - "soroban-spec 21.7.2", + "soroban-spec 21.7.3", "stellar-xdr 21.2.0", "syn 2.0.77", "thiserror", @@ -6037,9 +6044,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" dependencies = [ "futures-util", "js-sys", diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 78c3974f3..efef18e0f 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -107,7 +107,7 @@ ulid = { workspace = true, features = ["serde"] } strum = "0.17.1" strum_macros = "0.17.1" async-compression = { version = "0.4.12", features = ["tokio", "gzip"] } - +shell-escape = "0.1.5" tempfile = "3.8.1" toml_edit = "0.21.0" rust-embed = { version = "8.2.0", features = ["debug-embed"] } diff --git a/cmd/soroban-cli/src/commands/contract/build.rs b/cmd/soroban-cli/src/commands/contract/build.rs index 01ccce311..ac1aa1302 100644 --- a/cmd/soroban-cli/src/commands/contract/build.rs +++ b/cmd/soroban-cli/src/commands/contract/build.rs @@ -2,6 +2,7 @@ use cargo_metadata::{Metadata, MetadataCommand, Package}; use clap::Parser; use itertools::Itertools; use std::{ + borrow::Cow, collections::HashSet, env, ffi::OsStr, @@ -12,6 +13,8 @@ use std::{ }; use stellar_xdr::curr::{Limits, ScMetaEntry, ScMetaV0, StringM, WriteXdr}; +use crate::{commands::global, print::Print}; + /// Build a contract from source /// /// Builds all crates that are referenced by the cargo manifest (Cargo.toml) @@ -96,6 +99,8 @@ pub enum Error { CopyingWasmFile(io::Error), #[error("getting the current directory: {0}")] GettingCurrentDir(io::Error), + #[error("retreiving CARGO_HOME: {0}")] + CargoHome(io::Error), #[error("reading wasm file: {0}")] ReadingWasmFile(io::Error), #[error("writing wasm file: {0}")] @@ -108,7 +113,9 @@ const WASM_TARGET: &str = "wasm32-unknown-unknown"; const META_CUSTOM_SECTION_NAME: &str = "contractmetav0"; impl Cmd { - pub fn run(&self) -> Result<(), Error> { + pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let print = Print::new(global_args.quiet); + let working_dir = env::current_dir().map_err(Error::GettingCurrentDir)?; let metadata = self.metadata()?; @@ -154,15 +161,31 @@ impl Cmd { cmd.arg(format!("--features={activate}")); } } - let cmd_str = format!( - "cargo {}", - cmd.get_args().map(OsStr::to_string_lossy).join(" ") + + if let Some(rustflags) = make_rustflags_to_remap_absolute_paths(&print)? { + cmd.env("CARGO_BUILD_RUSTFLAGS", rustflags); + } + + let mut cmd_str_parts = Vec::::new(); + cmd_str_parts.extend(cmd.get_envs().map(|(key, val)| { + format!( + "{}={}", + key.to_string_lossy(), + shell_escape::escape(val.unwrap_or_default().to_string_lossy()) + ) + })); + cmd_str_parts.push("cargo".to_string()); + cmd_str_parts.extend( + cmd.get_args() + .map(OsStr::to_string_lossy) + .map(Cow::into_owned), ); + let cmd_str = cmd_str_parts.join(" "); if self.print_commands_only { println!("{cmd_str}"); } else { - eprintln!("{cmd_str}"); + print.infoln(cmd_str); let status = cmd.status().map_err(Error::CargoCmd)?; if !status.success() { return Err(Error::Exit(status)); @@ -282,3 +305,101 @@ impl Cmd { fs::write(target_file_path, wasm_bytes).map_err(Error::WritingWasmFile) } } + +/// Configure cargo/rustc to replace absolute paths in panic messages / debuginfo +/// with relative paths. +/// +/// This is required for reproducible builds. +/// +/// This works for paths to crates in the registry. The compiler already does +/// something similar for standard library paths and local paths. It may not +/// work for crates that come from other sources, including the standard library +/// compiled from source, though it may be possible to accomodate such cases in +/// the future. +/// +/// This in theory breaks the ability of debuggers to find source code, but +/// since we are only targetting wasm, which is not typically run in a debugger, +/// and stellar-cli only compiles contracts in release mode, the impact is on +/// debugging is expected to be minimal. +/// +/// This works by setting the `CARGO_BUILD_RUSTFLAGS` environment variable, +/// with appropriate `--remap-path-prefix` option. It preserves the values of an +/// existing `CARGO_BUILD_RUSTFLAGS` environment variable. +/// +/// This must be done some via some variation of `RUSTFLAGS` and not as +/// arguments to `cargo rustc` because the latter only applies to the crate +/// directly being compiled, while `RUSTFLAGS` applies to all crates, including +/// dependencies. +/// +/// `CARGO_BUILD_RUSTFLAGS` is an alias for the `build.rustflags` configuration +/// variable. Cargo automatically merges the contents of the environment variable +/// and the variables from config files; and `build.rustflags` has the lowest +/// priority of all the variations of rustflags that Cargo accepts. And because +/// we merge our values with an existing `CARGO_BUILD_RUSTFLAGS`, +/// our setting of this environment variable should not interfere with the +/// user's ability to set rustflags in any way they want, but it does mean +/// that if the user sets a higher-priority rustflags that our path remapping +/// will be ignored. +/// +/// The major downside of using `CARGO_BUILD_RUSTFLAGS` is that it is whitespace +/// separated, which means we cannot support paths with spaces. If we encounter +/// such paths we will emit a warning. Spaces could be accomodated by using +/// `CARGO_ENCODED_RUSTFLAGS`, but that has high precedence over other rustflags, +/// so we could be interfering with the user's own use of rustflags. There is +/// no "encoded" variant of `CARGO_BUILD_RUSTFLAGS` at time of writing. +/// +/// This assumes that paths are Unicode and that any existing `CARGO_BUILD_RUSTFLAGS` +/// variables are Unicode. Non-Unicode paths will fail to correctly perform the +/// the absolute path replacement. Non-Unicode `CARGO_BUILD_RUSTFLAGS` will result in the +/// existing rustflags being ignored, which is also the behavior of +/// Cargo itself. +fn make_rustflags_to_remap_absolute_paths(print: &Print) -> Result, Error> { + let cargo_home = home::cargo_home().map_err(Error::CargoHome)?; + let cargo_home = format!("{}", cargo_home.display()); + + if cargo_home.find(|c: char| c.is_whitespace()).is_some() { + print.warnln("Cargo home directory contains whitespace. Dependency paths will not be remapped; builds may not be reproducible."); + return Ok(None); + } + + if env::var("RUSTFLAGS").is_ok() { + print.warnln("`RUSTFLAGS` set. Dependency paths will not be remapped; builds may not be reproducible."); + return Ok(None); + } + + if env::var("CARGO_ENCODED_RUSTFLAGS").is_ok() { + print.warnln("`CARGO_ENCODED_RUSTFLAGS` set. Dependency paths will not be remapped; builds may not be reproducible."); + return Ok(None); + } + + if env::var("TARGET_wasm32-unknown-unknown_RUSTFLAGS").is_ok() { + print.warnln("`TARGET_wasm32-unknown-unknown_RUSTFLAGS` set. Dependency paths will not be remapped; builds may not be reproducible."); + return Ok(None); + } + + let registry_prefix = format!("{cargo_home}/registry/src/"); + let new_rustflag = format!("--remap-path-prefix={registry_prefix}="); + + let mut rustflags = get_rustflags().unwrap_or_default(); + rustflags.push(new_rustflag); + + let rustflags = rustflags.join(" "); + + Ok(Some(rustflags)) +} + +/// Get any existing `CARGO_BUILD_RUSTFLAGS`, split on whitespace. +/// +/// This conveniently ignores non-Unicode values, as does Cargo. +fn get_rustflags() -> Option> { + if let Ok(a) = env::var("CARGO_BUILD_RUSTFLAGS") { + let args = a + .split_whitespace() + .map(str::trim) + .filter(|s| !s.is_empty()) + .map(str::to_string); + return Some(args.collect()); + } + + None +} diff --git a/cmd/soroban-cli/src/commands/contract/mod.rs b/cmd/soroban-cli/src/commands/contract/mod.rs index d0524e82b..d72ce62b6 100644 --- a/cmd/soroban-cli/src/commands/contract/mod.rs +++ b/cmd/soroban-cli/src/commands/contract/mod.rs @@ -146,7 +146,7 @@ impl Cmd { match &self { Cmd::Asset(asset) => asset.run().await?, Cmd::Bindings(bindings) => bindings.run().await?, - Cmd::Build(build) => build.run()?, + Cmd::Build(build) => build.run(global_args)?, Cmd::Extend(extend) => extend.run().await?, Cmd::Alias(alias) => alias.run(global_args)?, Cmd::Deploy(deploy) => deploy.run(global_args).await?, From c873f9f6e281124c147f169d4f9b11b5a0abecf1 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Tue, 5 Nov 2024 13:40:02 -0500 Subject: [PATCH 13/77] fix: remove clap from enforcing network args and update error message (#1698) --- cmd/soroban-cli/src/config/network.rs | 46 ++++++++++++++++----------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/cmd/soroban-cli/src/config/network.rs b/cmd/soroban-cli/src/config/network.rs index ac7dc04bc..829716753 100644 --- a/cmd/soroban-cli/src/config/network.rs +++ b/cmd/soroban-cli/src/config/network.rs @@ -22,8 +22,23 @@ pub mod passphrase; pub enum Error { #[error(transparent)] Config(#[from] locator::Error), - #[error("network arg or rpc url and network passphrase are required if using the network")] + #[error( + r#"Access to the network is required +`--network` or `--rpc-url` and `--network-passphrase` are required if using the network. +Alternatively you can use their corresponding environment variables: +STELLAR_NETWORK, STELLAR_RPC_URL and STELLAR_NETWORK_PASSPHRASE"# + )] Network, + #[error( + "rpc-url is used but network passphrase is missing, use `--network-passphrase` or `STELLAR_NETWORK_PASSPHRASE`" + )] + MissingNetworkPassphrase, + #[error( + "network passphrase is used but rpc-url is missing, use `--rpc-url` or `STELLAR_RPC_URL`" + )] + MissingRpcUrl, + #[error("cannot use both `--rpc-url` and `--network`")] + CannotUseBothRpcAndNetwork, #[error(transparent)] Rpc(#[from] rpc::Error), #[error(transparent)] @@ -48,8 +63,6 @@ pub struct Args { /// RPC server endpoint #[arg( long = "rpc-url", - requires = "network_passphrase", - required_unless_present = "network", env = "STELLAR_RPC_URL", help_heading = HEADING_RPC, )] @@ -68,8 +81,6 @@ pub struct Args { /// Network passphrase to sign the transaction sent to the rpc server #[arg( long = "network-passphrase", - requires = "rpc_url", - required_unless_present = "network", env = "STELLAR_NETWORK_PASSPHRASE", help_heading = HEADING_RPC, )] @@ -77,8 +88,6 @@ pub struct Args { /// Name of network to use from config #[arg( long, - required_unless_present = "rpc_url", - required_unless_present = "network_passphrase", env = "STELLAR_NETWORK", help_heading = HEADING_RPC, )] @@ -87,21 +96,20 @@ pub struct Args { impl Args { pub fn get(&self, locator: &locator::Args) -> Result { - if let Some(name) = self.network.as_deref() { - if let Ok(network) = locator.read_network(name) { - return Ok(network); - } - } - if let (Some(rpc_url), Some(network_passphrase)) = - (self.rpc_url.clone(), self.network_passphrase.clone()) - { - Ok(Network { + match ( + self.network.as_deref(), + self.rpc_url.clone(), + self.network_passphrase.clone(), + ) { + (None, None, None) => Err(Error::Network), + (_, Some(_), None) => Err(Error::MissingNetworkPassphrase), + (_, None, Some(_)) => Err(Error::MissingRpcUrl), + (Some(network), None, None) => Ok(locator.read_network(network)?), + (_, Some(rpc_url), Some(network_passphrase)) => Ok(Network { rpc_url, rpc_headers: self.rpc_headers.clone(), network_passphrase, - }) - } else { - Err(Error::Network) + }), } } } From 3209130957a9f8b6c3385d8430b1b0870cf16e10 Mon Sep 17 00:00:00 2001 From: Dhanraj Avhad <95683132+Dhanraj30@users.noreply.github.com> Date: Wed, 6 Nov 2024 04:06:14 +0530 Subject: [PATCH 14/77] =?UTF-8?q?Fix:=20stellar=20contract=20info=20*=20co?= =?UTF-8?q?mmands=20require=20network=20when=20network=20no=E2=80=A6=20(#1?= =?UTF-8?q?676)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix: stellar contract info * commands require network when network not required * Added wasm field to Args struct and updated Cmd::run logic * fix: prevent network resolution when local wasm is provided in fetch_wasm * Update cmd/soroban-cli/src/commands/global.rs Co-authored-by: Willem Wyndham * Update cmd/soroban-cli/src/commands/network/mod.rs Co-authored-by: Willem Wyndham * Update cmd/soroban-cli/src/commands/global.rs Co-authored-by: Willem Wyndham * Update cmd/soroban-cli/src/commands/contract/info/shared.rs Co-authored-by: Willem Wyndham * fix: make network args optional and postpone error until resolution --------- Co-authored-by: Willem Wyndham Co-authored-by: Willem Wyndham Co-authored-by: Jane Wang --- .../src/commands/contract/info/shared.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/info/shared.rs b/cmd/soroban-cli/src/commands/contract/info/shared.rs index 0974632ae..b34ec7da8 100644 --- a/cmd/soroban-cli/src/commands/contract/info/shared.rs +++ b/cmd/soroban-cli/src/commands/contract/info/shared.rs @@ -59,11 +59,16 @@ pub enum Error { } pub async fn fetch_wasm(args: &Args) -> Result>, Error> { - let network = &args.network.get(&args.locator)?; + // Check if a local WASM file path is provided + if let Some(path) = &args.wasm { + // Read the WASM file and return its contents + let wasm_bytes = wasm::Args { wasm: path.clone() }.read()?; + return Ok(Some(wasm_bytes)); + } - let wasm = if let Some(path) = &args.wasm { - wasm::Args { wasm: path.clone() }.read()? - } else if let Some(wasm_hash) = &args.wasm_hash { + // If no local wasm, then check for wasm_hash and fetch from the network + let network = &args.network.get(&args.locator)?; + let wasm = if let Some(wasm_hash) = &args.wasm_hash { let hash = hex::decode(wasm_hash) .map_err(|_| InvalidWasmHash(wasm_hash.clone()))? .try_into() From 6e645f0109ad9c59fe7ccc87b12cc3a164994c87 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Tue, 5 Nov 2024 21:17:21 -0800 Subject: [PATCH 15/77] Add global config for default network and identity. (#1690) --- FULL_HELP_DOCS.md | 50 +++++++++++++++ cmd/crates/soroban-test/tests/it/config.rs | 53 +++++++++++++++ cmd/soroban-cli/src/commands/env/mod.rs | 64 +++++++++++++++++++ cmd/soroban-cli/src/commands/keys/default.rs | 35 ++++++++++ cmd/soroban-cli/src/commands/keys/mod.rs | 20 ++++++ cmd/soroban-cli/src/commands/mod.rs | 24 ++++++- .../src/commands/network/default.rs | 34 ++++++++++ cmd/soroban-cli/src/commands/network/mod.rs | 15 +++++ cmd/soroban-cli/src/config/locator.rs | 28 ++++++-- cmd/soroban-cli/src/config/mod.rs | 53 +++++++++++++-- 10 files changed, 365 insertions(+), 11 deletions(-) create mode 100644 cmd/soroban-cli/src/commands/env/mod.rs create mode 100644 cmd/soroban-cli/src/commands/keys/default.rs create mode 100644 cmd/soroban-cli/src/commands/network/default.rs diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 8c151cb84..aa2c8e865 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -45,6 +45,7 @@ Anything after the `--` double dash (the "slop") is parsed as arguments to the c * `contract` — Tools for smart contract developers * `events` — Watch the network for contract events +* `env` — Prints the current environment variables or defaults to the stdout, in a format that can be used as .env file. Environment variables have precedency over defaults * `keys` — Create and manage identities including keys and addresses * `network` — Start and configure networks * `snapshot` — Download a snapshot of a ledger from an archive @@ -897,6 +898,19 @@ Watch the network for contract events +## `stellar env` + +Prints the current environment variables or defaults to the stdout, in a format that can be used as .env file. Environment variables have precedency over defaults + +**Usage:** `stellar env [OPTIONS]` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + ## `stellar keys` Create and manage identities including keys and addresses @@ -912,6 +926,7 @@ Create and manage identities including keys and addresses * `ls` — List identities * `rm` — Remove an identity * `show` — Given an identity return its private key +* `use` — Set the default identity that will be used on all commands. This allows you to skip `--source-account` or setting a environment variable, while reusing this value in all commands that require it @@ -1052,6 +1067,23 @@ Given an identity return its private key +## `stellar keys use` + +Set the default identity that will be used on all commands. This allows you to skip `--source-account` or setting a environment variable, while reusing this value in all commands that require it + +**Usage:** `stellar keys use [OPTIONS] ` + +###### **Arguments:** + +* `` — Set the default network name + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + ## `stellar network` Start and configure networks @@ -1065,6 +1097,7 @@ Start and configure networks * `ls` — List networks * `start` — ⚠️ Deprecated: use `stellar container start` instead * `stop` — ⚠️ Deprecated: use `stellar container stop` instead +* `use` — Set the default network that will be used on all commands. This allows you to skip `--network` or setting a environment variable, while reusing this value in all commands that require it * `container` — Commands to start, stop and get logs for a quickstart container @@ -1174,6 +1207,23 @@ Stop a network started with `network start`. For example, if you ran `stellar ne +## `stellar network use` + +Set the default network that will be used on all commands. This allows you to skip `--network` or setting a environment variable, while reusing this value in all commands that require it + +**Usage:** `stellar network use [OPTIONS] ` + +###### **Arguments:** + +* `` — Set the default network name + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + ## `stellar network container` Commands to start, stop and get logs for a quickstart container diff --git a/cmd/crates/soroban-test/tests/it/config.rs b/cmd/crates/soroban-test/tests/it/config.rs index 31d60e116..b796910a8 100644 --- a/cmd/crates/soroban-test/tests/it/config.rs +++ b/cmd/crates/soroban-test/tests/it/config.rs @@ -340,3 +340,56 @@ fn config_dirs_precedence() { )) .stdout("SAQMV6P3OWM2SKCK3OEWNXSRYWK5RNNUL5CPHQGIJF2WVT4EI2BZ63GG\n"); } + +#[test] +fn set_default_identity() { + let sandbox = TestEnv::default(); + + sandbox + .new_assert_cmd("keys") + .env( + "SOROBAN_SECRET_KEY", + "SC4ZPYELVR7S7EE7KZDZN3ETFTNQHHLTUL34NUAAWZG5OK2RGJ4V2U3Z", + ) + .arg("add") + .arg("alice") + .assert() + .success(); + + sandbox + .new_assert_cmd("keys") + .arg("use") + .arg("alice") + .assert() + .stderr(predicate::str::contains( + "The default source account is set to `alice`", + )) + .success(); + + sandbox + .new_assert_cmd("env") + .assert() + .stdout(predicate::str::contains("STELLAR_ACCOUNT=alice")) + .success(); +} + +#[test] +fn set_default_network() { + let sandbox = TestEnv::default(); + + sandbox + .new_assert_cmd("network") + .arg("use") + .arg("testnet") + .assert() + .stderr(predicate::str::contains( + "The default network is set to `testnet`", + )) + .success(); + + sandbox + .new_assert_cmd("env") + .assert() + .stdout(predicate::str::contains("STELLAR_NETWORK=testnet")) + .success(); +} diff --git a/cmd/soroban-cli/src/commands/env/mod.rs b/cmd/soroban-cli/src/commands/env/mod.rs new file mode 100644 index 000000000..4d745400c --- /dev/null +++ b/cmd/soroban-cli/src/commands/env/mod.rs @@ -0,0 +1,64 @@ +use crate::{ + commands::global, + config::{ + locator::{self}, + Config, + }, + print::Print, +}; +use clap::Parser; + +#[derive(Debug, Parser)] +pub struct Cmd { + #[command(flatten)] + pub config_locator: locator::Args, +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Locator(#[from] locator::Error), +} + +impl Cmd { + pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let print = Print::new(global_args.quiet); + let config = Config::new()?; + let mut lines: Vec<(String, String)> = Vec::new(); + + if let Some(data) = get("STELLAR_NETWORK", config.defaults.network) { + lines.push(data); + } + + if let Some(data) = get("STELLAR_ACCOUNT", config.defaults.identity) { + lines.push(data); + } + + if lines.is_empty() { + print.warnln("No defaults or environment variables set".to_string()); + return Ok(()); + } + + let max_len = lines.iter().map(|l| l.0.len()).max().unwrap_or(0); + + lines.sort(); + + for (value, source) in lines { + println!("{value:max_len$} # {source}"); + } + + Ok(()) + } +} + +fn get(env_var: &str, default_value: Option) -> Option<(String, String)> { + if let Ok(value) = std::env::var(env_var) { + return Some((format!("{env_var}={value}"), "env".to_string())); + } + + if let Some(value) = default_value { + return Some((format!("{env_var}={value}"), "default".to_string())); + } + + None +} diff --git a/cmd/soroban-cli/src/commands/keys/default.rs b/cmd/soroban-cli/src/commands/keys/default.rs new file mode 100644 index 000000000..9aa180b6d --- /dev/null +++ b/cmd/soroban-cli/src/commands/keys/default.rs @@ -0,0 +1,35 @@ +use clap::command; + +use crate::{commands::global, config::locator, print::Print}; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Config(#[from] locator::Error), +} + +#[derive(Debug, clap::Parser, Clone)] +#[group(skip)] +pub struct Cmd { + /// Set the default network name. + pub name: String, + + #[command(flatten)] + pub config_locator: locator::Args, +} + +impl Cmd { + pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let printer = Print::new(global_args.quiet); + let _ = self.config_locator.read_identity(&self.name)?; + + self.config_locator.write_default_identity(&self.name)?; + + printer.infoln(format!( + "The default source account is set to `{}`", + self.name, + )); + + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/keys/mod.rs b/cmd/soroban-cli/src/commands/keys/mod.rs index 30df5ccee..8729ee9af 100644 --- a/cmd/soroban-cli/src/commands/keys/mod.rs +++ b/cmd/soroban-cli/src/commands/keys/mod.rs @@ -3,6 +3,7 @@ use clap::Parser; pub mod add; pub mod address; +pub mod default; pub mod fund; pub mod generate; pub mod ls; @@ -13,18 +14,30 @@ pub mod show; pub enum Cmd { /// Add a new identity (keypair, ledger, macOS keychain) Add(add::Cmd), + /// Given an identity return its address (public key) Address(address::Cmd), + /// Fund an identity on a test network Fund(fund::Cmd), + /// Generate a new identity with a seed phrase, currently 12 words Generate(generate::Cmd), + /// List identities Ls(ls::Cmd), + /// Remove an identity Rm(rm::Cmd), + /// Given an identity return its private key Show(show::Cmd), + + /// Set the default identity that will be used on all commands. + /// This allows you to skip `--source-account` or setting a environment + /// variable, while reusing this value in all commands that require it. + #[command(name = "use")] + Default(default::Cmd), } #[derive(thiserror::Error, Debug)] @@ -34,18 +47,24 @@ pub enum Error { #[error(transparent)] Address(#[from] address::Error), + #[error(transparent)] Fund(#[from] fund::Error), #[error(transparent)] Generate(#[from] generate::Error), + #[error(transparent)] Rm(#[from] rm::Error), + #[error(transparent)] Ls(#[from] ls::Error), #[error(transparent)] Show(#[from] show::Error), + + #[error(transparent)] + Default(#[from] default::Error), } impl Cmd { @@ -58,6 +77,7 @@ impl Cmd { Cmd::Ls(cmd) => cmd.run()?, Cmd::Rm(cmd) => cmd.run()?, Cmd::Show(cmd) => cmd.run()?, + Cmd::Default(cmd) => cmd.run(global_args)?, }; Ok(()) } diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index a6a85e816..f1febae27 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -8,6 +8,7 @@ use crate::config; pub mod cache; pub mod completion; pub mod contract; +pub mod env; pub mod events; pub mod global; pub mod keys; @@ -116,7 +117,8 @@ impl Root { Cmd::Version(version) => version.run(), Cmd::Keys(id) => id.run(&self.global_args).await?, Cmd::Tx(tx) => tx.run(&self.global_args).await?, - Cmd::Cache(data) => data.run()?, + Cmd::Cache(cache) => cache.run()?, + Cmd::Env(env) => env.run(&self.global_args)?, }; Ok(()) } @@ -135,9 +137,15 @@ pub enum Cmd { /// Tools for smart contract developers #[command(subcommand)] Contract(contract::Cmd), + /// Watch the network for contract events Events(events::Cmd), + /// Prints the current environment variables or defaults to the stdout, in + /// a format that can be used as .env file. Environment variables have + /// precedency over defaults. + Env(env::Cmd), + /// Create and manage identities including keys and addresses #[command(subcommand)] Keys(keys::Cmd), @@ -160,9 +168,11 @@ pub enum Cmd { /// Print shell completion code for the specified shell. #[command(long_about = completion::LONG_ABOUT)] Completion(completion::Cmd), + /// Cache for transactions and contract specs #[command(subcommand)] Cache(cache::Cmd), + /// Print version information Version(version::Cmd), } @@ -172,24 +182,36 @@ pub enum Error { // TODO: stop using Debug for displaying errors #[error(transparent)] Contract(#[from] contract::Error), + #[error(transparent)] Events(#[from] events::Error), + #[error(transparent)] Keys(#[from] keys::Error), + #[error(transparent)] Xdr(#[from] stellar_xdr::cli::Error), + #[error(transparent)] Clap(#[from] clap::error::Error), + #[error(transparent)] Plugin(#[from] plugin::Error), + #[error(transparent)] Network(#[from] network::Error), + #[error(transparent)] Snapshot(#[from] snapshot::Error), + #[error(transparent)] Tx(#[from] tx::Error), + #[error(transparent)] Cache(#[from] cache::Error), + + #[error(transparent)] + Env(#[from] env::Error), } #[async_trait] diff --git a/cmd/soroban-cli/src/commands/network/default.rs b/cmd/soroban-cli/src/commands/network/default.rs new file mode 100644 index 000000000..337e08a69 --- /dev/null +++ b/cmd/soroban-cli/src/commands/network/default.rs @@ -0,0 +1,34 @@ +use clap::command; + +use crate::{commands::global, print::Print}; + +use super::locator; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Config(#[from] locator::Error), +} + +#[derive(Debug, clap::Parser, Clone)] +#[group(skip)] +pub struct Cmd { + /// Set the default network name. + pub name: String, + + #[command(flatten)] + pub config_locator: locator::Args, +} + +impl Cmd { + pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let printer = Print::new(global_args.quiet); + let _ = self.config_locator.read_network(&self.name)?; + + self.config_locator.write_default_network(&self.name)?; + + printer.infoln(format!("The default network is set to `{}`", self.name)); + + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/network/mod.rs b/cmd/soroban-cli/src/commands/network/mod.rs index 8dd61b394..a7519bc83 100644 --- a/cmd/soroban-cli/src/commands/network/mod.rs +++ b/cmd/soroban-cli/src/commands/network/mod.rs @@ -6,6 +6,7 @@ use super::{config::locator, global}; pub mod add; pub mod container; +pub mod default; pub mod ls; pub mod rm; @@ -13,10 +14,13 @@ pub mod rm; pub enum Cmd { /// Add a new network Add(add::Cmd), + /// Remove a network Rm(rm::Cmd), + /// List networks Ls(ls::Cmd), + /// ⚠️ Deprecated: use `stellar container start` instead /// /// Start network @@ -29,11 +33,18 @@ pub enum Cmd { /// /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` Start(container::StartCmd), + /// ⚠️ Deprecated: use `stellar container stop` instead /// /// Stop a network started with `network start`. For example, if you ran `stellar network start local`, you can use `stellar network stop local` to stop it. Stop(container::StopCmd), + /// Set the default network that will be used on all commands. + /// This allows you to skip `--network` or setting a environment variable, + /// while reusing this value in all commands that require it. + #[command(name = "use")] + Default(default::Cmd), + /// Commands to start, stop and get logs for a quickstart container #[command(subcommand)] Container(container::Cmd), @@ -41,6 +52,9 @@ pub enum Cmd { #[derive(thiserror::Error, Debug)] pub enum Error { + #[error(transparent)] + Default(#[from] default::Error), + #[error(transparent)] Add(#[from] add::Error), @@ -81,6 +95,7 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match self { + Cmd::Default(cmd) => cmd.run(global_args)?, Cmd::Add(cmd) => cmd.run()?, Cmd::Rm(new) => new.run()?, Cmd::Ls(cmd) => cmd.run()?, diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 0a13c4cc3..60b7856a6 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -5,8 +5,7 @@ use std::{ ffi::OsStr, fmt::Display, fs::{self, create_dir_all, OpenOptions}, - io, - io::Write, + io::{self, Write}, path::{Path, PathBuf}, str::FromStr, }; @@ -18,10 +17,13 @@ use super::{ alias, network::{self, Network}, secret::Secret, + Config, }; #[derive(thiserror::Error, Debug)] pub enum Error { + #[error(transparent)] + TomlSerialize(#[from] toml::ser::Error), #[error("Failed to find home directory")] HomeDirNotFound, #[error("Failed read current directory")] @@ -34,6 +36,8 @@ pub enum Error { SecretFileRead { path: PathBuf }, #[error("Failed to read network file: {path};\nProbably need to use `stellar network add`")] NetworkFileRead { path: PathBuf }, + #[error("Failed to read file: {path}")] + FileRead { path: PathBuf }, #[error(transparent)] Toml(#[from] toml::de::Error), #[error("Secret file failed to deserialize")] @@ -163,6 +167,14 @@ impl Args { KeyType::Network.write(name, network, &self.config_dir()?) } + pub fn write_default_network(&self, name: &str) -> Result<(), Error> { + Config::new()?.set_network(name).save() + } + + pub fn write_default_identity(&self, name: &str) -> Result<(), Error> { + Config::new()?.set_identity(name).save() + } + pub fn list_identities(&self) -> Result, Error> { Ok(KeyType::Identity .list_paths(&self.local_and_global()?)? @@ -344,6 +356,12 @@ impl Args { } } +impl Pwd for Args { + fn set_pwd(&mut self, pwd: &Path) { + self.config_dir = Some(pwd.to_path_buf()); + } +} + pub fn ensure_directory(dir: PathBuf) -> Result { let parent = dir.parent().ok_or(Error::HomeDirNotFound)?; std::fs::create_dir_all(parent).map_err(|_| dir_creation_failed(parent))?; @@ -496,8 +514,6 @@ pub fn global_config_path() -> Result { Ok(stellar_dir) } -impl Pwd for Args { - fn set_pwd(&mut self, pwd: &Path) { - self.config_dir = Some(pwd.to_path_buf()); - } +pub fn config_file() -> Result { + Ok(global_config_path()?.join("config.toml")) } diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index b961f0f67..21ebb1fe9 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -1,6 +1,10 @@ use address::Address; use clap::{arg, command}; use serde::{Deserialize, Serialize}; +use std::{ + fs::{self, File}, + io::Write, +}; use crate::{ print::Print, @@ -8,7 +12,6 @@ use crate::{ xdr::{self, SequenceNumber, Transaction, TransactionEnvelope}, Pwd, }; - use network::Network; pub mod address; @@ -125,9 +128,6 @@ impl Pwd for Args { } } -#[derive(Default, Serialize, Deserialize)] -pub struct Config {} - #[derive(Debug, clap::Args, Clone, Default)] #[group(skip)] pub struct ArgsLocatorAndNetwork { @@ -143,3 +143,48 @@ impl ArgsLocatorAndNetwork { Ok(self.network.get(&self.locator)?) } } + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct Config { + pub defaults: Defaults, +} + +#[derive(Serialize, Deserialize, Debug, Default)] +pub struct Defaults { + pub network: Option, + pub identity: Option, +} + +impl Config { + pub fn new() -> Result { + let path = locator::config_file()?; + + if path.exists() { + let data = fs::read(&path).map_err(|_| locator::Error::FileRead { path })?; + + Ok(toml::from_slice(&data)?) + } else { + Ok(Config::default()) + } + } + + #[must_use] + pub fn set_network(mut self, s: &str) -> Self { + self.defaults.network = Some(s.to_string()); + self + } + + #[must_use] + pub fn set_identity(mut self, s: &str) -> Self { + self.defaults.identity = Some(s.to_string()); + self + } + + pub fn save(&self) -> Result<(), locator::Error> { + let toml_string = toml::to_string(&self)?; + let mut file = File::create(locator::config_file()?)?; + file.write_all(toml_string.as_bytes())?; + + Ok(()) + } +} From 8163f30785d66c83101cc4b4e1064374f57d9356 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Wed, 6 Nov 2024 02:42:27 -0500 Subject: [PATCH 16/77] feat: Add parsing to deploy to support new constructor feature (#1574) --- .github/workflows/rpc-tests.yml | 35 ++-- Cargo.lock | 12 ++ Cargo.toml | 11 +- FULL_HELP_DOCS.md | 6 +- .../test-wasms/constructor/Cargo.toml | 18 ++ .../test-wasms/constructor/src/lib.rs | 18 ++ .../soroban-test/tests/it/integration.rs | 1 + .../tests/it/integration/constructor.rs | 73 +++++++++ .../soroban-test/tests/it/integration/util.rs | 1 + .../src/commands/contract/deploy/asset.rs | 6 +- .../src/commands/contract/deploy/wasm.rs | 154 ++++++++++++------ .../src/commands/contract/extend.rs | 9 +- .../src/commands/contract/install.rs | 6 +- .../src/commands/contract/restore.rs | 7 +- cmd/soroban-cli/src/commands/tx/args.rs | 2 +- cmd/soroban-cli/src/config/data.rs | 2 +- cmd/soroban-cli/src/config/mod.rs | 13 +- 17 files changed, 289 insertions(+), 85 deletions(-) create mode 100644 cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml create mode 100644 cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/src/lib.rs create mode 100644 cmd/crates/soroban-test/tests/it/integration/constructor.rs diff --git a/.github/workflows/rpc-tests.yml b/.github/workflows/rpc-tests.yml index 769cd21f7..75b6d7760 100644 --- a/.github/workflows/rpc-tests.yml +++ b/.github/workflows/rpc-tests.yml @@ -1,4 +1,3 @@ - name: RPC Tests on: push: @@ -15,32 +14,32 @@ jobs: runs-on: ubuntu-22.04 services: rpc: - image: stellar/quickstart:v438-testing + image: stellar/quickstart:testing ports: - 8000:8000 env: ENABLE_LOGS: true ENABLE_SOROBAN_DIAGNOSTIC_EVENTS: true NETWORK: local + PROTOCOL_VERSION: 22 options: >- --health-cmd "curl --no-progress-meter --fail-with-body -X POST \"http://localhost:8000/soroban/rpc\" -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":8675309,\"method\":\"getNetwork\"}' && curl --no-progress-meter \"http://localhost:8000/friendbot\" | grep '\"invalid_field\": \"addr\"'" --health-interval 10s --health-timeout 5s --health-retries 50 steps: - - uses: actions/checkout@v4 - - uses: actions/cache@v4 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - run: rustup update - - run: cargo build - - run: rustup target add wasm32-unknown-unknown - - run: make build-test-wasms - - run: SOROBAN_PORT=8000 cargo test --features it --package soroban-test --test it -- integration - + - uses: actions/checkout@v4 + - uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - run: rustup update + - run: cargo build + - run: rustup target add wasm32-unknown-unknown + - run: make build-test-wasms + - run: SOROBAN_PORT=8000 cargo test --features it --package soroban-test --test it -- integration diff --git a/Cargo.lock b/Cargo.lock index 6fdf9ee5b..806e767ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4542,6 +4542,7 @@ version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39b6d2ec8955243394278e1fae88be3b367fcfed9cf74e5044799a90786a8642" dependencies = [ + "arbitrary", "crate-git-revision 0.0.6", "ethnum", "num-derive", @@ -4731,7 +4732,10 @@ version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d063d0df000aaec20105aab3d743660322bc0269934ea95d79fa19aa8792385" dependencies = [ + "arbitrary", "bytes-lit", + "ctor", + "ed25519-dalek 2.1.1", "rand", "rustc_version", "serde", @@ -5091,6 +5095,7 @@ version = "22.0.0-rc.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c88dc0e928b9cb65ea43836b52560bb4ead3e32895f5019ca223dc7cd1966cbf" dependencies = [ + "arbitrary", "base64 0.13.1", "clap", "crate-git-revision 0.0.6", @@ -5347,6 +5352,13 @@ dependencies = [ "test-case-core", ] +[[package]] +name = "test_constructor" +version = "21.5.0" +dependencies = [ + "soroban-sdk 22.0.0-rc.3", +] + [[package]] name = "test_custom_account" version = "21.5.0" diff --git a/Cargo.toml b/Cargo.toml index 58caad196..d5f87b38e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,15 @@ members = [ "cmd/crates/soroban-test/tests/fixtures/hello", "cmd/crates/soroban-test/tests/fixtures/bye", ] -default-members = ["cmd/soroban-cli", "cmd/crates/soroban-spec-tools", "cmd/crates/soroban-test"] -exclude = ["cmd/crates/soroban-test/tests/fixtures/hello", "cmd/crates/soroban-test/tests/fixtures/bye"] +default-members = [ + "cmd/soroban-cli", + "cmd/crates/soroban-spec-tools", + "cmd/crates/soroban-test", +] +exclude = [ + "cmd/crates/soroban-test/tests/fixtures/hello", + "cmd/crates/soroban-test/tests/fixtures/bye", +] [workspace.package] version = "21.5.0" diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index aa2c8e865..ae25453c6 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -388,7 +388,11 @@ If no keys are specified the contract itself is extended. Deploy a wasm contract -**Usage:** `stellar contract deploy [OPTIONS] --source-account <--wasm |--wasm-hash >` +**Usage:** `stellar contract deploy [OPTIONS] --source-account <--wasm |--wasm-hash > [-- ...]` + +###### **Arguments:** + +* `` — If provided, will be passed to the contract's `__constructor` function with provided arguments for that function as `--arg-name value` ###### **Options:** diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml new file mode 100644 index 000000000..ef1dd882c --- /dev/null +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "test_constructor" +version = "21.5.0" +authors = ["Stellar Development Foundation "] +license = "Apache-2.0" +edition = "2021" +publish = false +rust-version.workspace = true + +[lib] +crate-type = ["cdylib"] +doctest = false + +[dependencies] +soroban-sdk = { workspace = true } + +[dev-dependencies] +soroban-sdk = { workspace = true, features = ["testutils"]} diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/src/lib.rs new file mode 100644 index 000000000..8b867968f --- /dev/null +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/src/lib.rs @@ -0,0 +1,18 @@ +#![no_std] +use soroban_sdk::{contract, contractimpl, symbol_short, Env, Symbol}; + +#[contract] +pub struct Contract; +const COUNTER: Symbol = symbol_short!("COUNTER"); + +#[contractimpl] +impl Contract { + /// Example constructor + pub fn __constructor(env: Env, counter: u32) { + env.storage().persistent().set(&COUNTER, &counter); + } + /// Counter value + pub fn counter(env: Env) -> u32 { + env.storage().persistent().get(&COUNTER).unwrap() + } +} diff --git a/cmd/crates/soroban-test/tests/it/integration.rs b/cmd/crates/soroban-test/tests/it/integration.rs index 3e8521869..d6db5842b 100644 --- a/cmd/crates/soroban-test/tests/it/integration.rs +++ b/cmd/crates/soroban-test/tests/it/integration.rs @@ -1,4 +1,5 @@ mod bindings; +mod constructor; mod cookbook; mod custom_types; mod dotenv; diff --git a/cmd/crates/soroban-test/tests/it/integration/constructor.rs b/cmd/crates/soroban-test/tests/it/integration/constructor.rs new file mode 100644 index 000000000..1919b56b0 --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/integration/constructor.rs @@ -0,0 +1,73 @@ +use assert_cmd::Command; + +use soroban_cli::xdr::{ + self, CreateContractArgsV2, HostFunction, InvokeHostFunctionOp, Limits, OperationBody, ReadXdr, + Transaction, TransactionV1Envelope, +}; +use soroban_test::{AssertExt, TestEnv}; + +use super::util::CONSTRUCTOR; + +fn constructor_cmd(sandbox: &TestEnv, value: u32, arg: &str) -> Command { + let mut cmd = sandbox.new_assert_cmd("contract"); + cmd.arg("deploy") + .arg("--wasm") + .arg(CONSTRUCTOR.path()) + .arg("--alias=init"); + if !arg.is_empty() { + cmd.arg(arg); + } + cmd.arg("--").arg("--counter").arg(value.to_string()); + cmd +} + +#[tokio::test] +async fn deploy_constructor_contract() { + let sandbox = TestEnv::new(); + let value = 100; + let build = constructor_cmd(&sandbox, value, "--build-only") + .assert() + .stdout_as_str(); + let tx = xdr::TransactionEnvelope::from_xdr_base64(&build, Limits::none()).unwrap(); + let ops = if let xdr::TransactionEnvelope::Tx(TransactionV1Envelope { + tx: Transaction { operations, .. }, + .. + }) = tx + { + operations + } else { + panic!() + } + .to_vec(); + let first = ops.first().unwrap(); + let args = match first { + xdr::Operation { + body: + OperationBody::InvokeHostFunction(InvokeHostFunctionOp { + host_function: + HostFunction::CreateContractV2(CreateContractArgsV2 { + constructor_args, .. + }), + .. + }), + .. + } => constructor_args, + _ => panic!("expected invoke host function with create contract v2"), + } + .to_vec(); + + match args.first().unwrap() { + xdr::ScVal::U32(u32) => assert_eq!(*u32, value), + _ => panic!("Expected U32"), + } + + constructor_cmd(&sandbox, value, "").assert().success(); + + let res = sandbox + .new_assert_cmd("contract") + .args(["invoke", "--id=init", "--", "counter"]) + .assert() + .success() + .stdout_as_str(); + assert_eq!(res.trim(), value.to_string()); +} diff --git a/cmd/crates/soroban-test/tests/it/integration/util.rs b/cmd/crates/soroban-test/tests/it/integration/util.rs index 438428e38..486b00a1b 100644 --- a/cmd/crates/soroban-test/tests/it/integration/util.rs +++ b/cmd/crates/soroban-test/tests/it/integration/util.rs @@ -6,6 +6,7 @@ use soroban_test::{TestEnv, Wasm}; use std::fmt::Display; pub const HELLO_WORLD: &Wasm = &Wasm::Custom("test-wasms", "test_hello_world"); +pub const CONSTRUCTOR: &Wasm = &Wasm::Custom("test-wasms", "test_constructor"); pub const CUSTOM_TYPES: &Wasm = &Wasm::Custom("test-wasms", "test_custom_types"); pub const CUSTOM_ACCOUNT: &Wasm = &Wasm::Custom("test-wasms", "test_custom_account"); pub const SWAP: &Wasm = &Wasm::Custom("test-wasms", "test_swap"); diff --git a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs index 263908521..169c0109a 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs @@ -93,11 +93,11 @@ impl NetworkRunnable for Cmd { .verify_network_passphrase(Some(&network.network_passphrase)) .await?; let source_account = config.source_account()?; - // Get the account sequence number - let public_strkey = source_account.to_string(); // TODO: use symbols for the method names (both here and in serve) - let account_details = client.get_account(&public_strkey).await?; + let account_details = client + .get_account(&source_account.clone().to_string()) + .await?; let sequence: i64 = account_details.seq_num.into(); let network_passphrase = &network.network_passphrase; let contract_id = contract_id_hash_from_asset(asset, network_passphrase); diff --git a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs index 21c685b93..9bf63802c 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs @@ -1,33 +1,38 @@ use std::array::TryFromSliceError; +use std::ffi::OsString; use std::fmt::Debug; use std::num::ParseIntError; use crate::xdr::{ AccountId, ContractExecutable, ContractIdPreimage, ContractIdPreimageFromAddress, - CreateContractArgs, Error as XdrError, Hash, HostFunction, InvokeHostFunctionOp, Limits, Memo, - MuxedAccount, Operation, OperationBody, Preconditions, PublicKey, ScAddress, SequenceNumber, - Transaction, TransactionExt, Uint256, VecM, WriteXdr, + CreateContractArgs, CreateContractArgsV2, Error as XdrError, Hash, HostFunction, + InvokeContractArgs, InvokeHostFunctionOp, Limits, Memo, MuxedAccount, Operation, OperationBody, + Preconditions, PublicKey, ScAddress, SequenceNumber, Transaction, TransactionExt, Uint256, + VecM, WriteXdr, }; use clap::{arg, command, Parser}; use rand::Rng; use regex::Regex; +use soroban_spec_tools::contract as contract_spec; + use crate::{ assembled::simulate_and_assemble_transaction, - commands::{contract::install, HEADING_RPC}, - config::{self, data, locator, network}, - rpc, utils, wasm, -}; -use crate::{ commands::{ - contract::{self, id::wasm::get_contract_id}, + contract::{self, arg_parsing, id::wasm::get_contract_id, install}, global, txn_result::{TxnEnvelopeResult, TxnResult}, - NetworkRunnable, + NetworkRunnable, HEADING_RPC, }, + config::{self, data, locator, network}, print::Print, + rpc, + utils::{self, rpc::get_remote_wasm_from_hash}, + wasm, }; +pub const CONSTRUCTOR_FUNCTION_NAME: &str = "__constructor"; + #[derive(Parser, Debug, Clone)] #[command(group( clap::ArgGroup::new("wasm_src") @@ -60,6 +65,9 @@ pub struct Cmd { /// configuration without asking for confirmation. #[arg(long, value_parser = clap::builder::ValueParser::new(alias_validator))] pub alias: Option, + /// If provided, will be passed to the contract's `__constructor` function with provided arguments for that function as `--arg-name value` + #[arg(last = true, id = "CONTRACT_CONSTRUCTOR_ARGS")] + pub slop: Vec, } #[derive(thiserror::Error, Debug)] @@ -110,6 +118,10 @@ pub enum Error { InvalidAliasFormat { alias: String }, #[error(transparent)] Locator(#[from] locator::Error), + #[error(transparent)] + ContractSpec(#[from] contract_spec::Error), + #[error(transparent)] + ArgParse(#[from] arg_parsing::Error), #[error("Only ed25519 accounts are allowed")] OnlyEd25519AccountsAllowed, } @@ -157,6 +169,7 @@ impl NetworkRunnable for Cmd { type Error = Error; type Result = TxnResult; + #[allow(clippy::too_many_lines)] async fn run_against_rpc_server( &self, global_args: Option<&global::Args>, @@ -211,21 +224,54 @@ impl NetworkRunnable for Cmd { client .verify_network_passphrase(Some(&network.network_passphrase)) .await?; + let MuxedAccount::Ed25519(bytes) = config.source_account()? else { return Err(Error::OnlyEd25519AccountsAllowed); }; + let source_account = AccountId(PublicKey::PublicKeyTypeEd25519(bytes)); + let contract_id_preimage = ContractIdPreimage::Address(ContractIdPreimageFromAddress { + address: ScAddress::Account(source_account.clone()), + salt: Uint256(salt), + }); + let contract_id = + get_contract_id(contract_id_preimage.clone(), &network.network_passphrase)?; + let raw_wasm = if let Some(wasm) = self.wasm.as_ref() { + wasm::Args { wasm: wasm.clone() }.read()? + } else { + get_remote_wasm_from_hash(&client, &wasm_hash).await? + }; + let entries = soroban_spec_tools::contract::Spec::new(&raw_wasm)?.spec; + let res = soroban_spec_tools::Spec::new(entries.clone()); + let constructor_params = if let Ok(func) = res.find_function(CONSTRUCTOR_FUNCTION_NAME) { + if func.inputs.len() == 0 { + None + } else { + let mut slop = vec![OsString::from(CONSTRUCTOR_FUNCTION_NAME)]; + slop.extend_from_slice(&self.slop); + Some( + arg_parsing::build_host_function_parameters( + &stellar_strkey::Contract(contract_id.0), + &slop, + &entries, + config, + )? + .2, + ) + } + } else { + None + }; - let key = stellar_strkey::ed25519::PublicKey(bytes.into()); // Get the account sequence number - let account_details = client.get_account(&key.to_string()).await?; + let account_details = client.get_account(&source_account.to_string()).await?; let sequence: i64 = account_details.seq_num.into(); - let (txn, contract_id) = build_create_contract_tx( + let txn = build_create_contract_tx( wasm_hash, sequence + 1, self.fee.fee, - &network.network_passphrase, - salt, - key, + source_account, + contract_id_preimage, + constructor_params.as_ref(), )?; if self.fee.build_only { @@ -266,33 +312,39 @@ impl NetworkRunnable for Cmd { } fn build_create_contract_tx( - hash: Hash, + wasm_hash: Hash, sequence: i64, fee: u32, - network_passphrase: &str, - salt: [u8; 32], - key: stellar_strkey::ed25519::PublicKey, -) -> Result<(Transaction, stellar_strkey::Contract), Error> { - let source_account = AccountId(PublicKey::PublicKeyTypeEd25519(key.0.into())); - - let contract_id_preimage = ContractIdPreimage::Address(ContractIdPreimageFromAddress { - address: ScAddress::Account(source_account), - salt: Uint256(salt), - }); - let contract_id = get_contract_id(contract_id_preimage.clone(), network_passphrase)?; - - let op = Operation { - source_account: None, - body: OperationBody::InvokeHostFunction(InvokeHostFunctionOp { - host_function: HostFunction::CreateContract(CreateContractArgs { - contract_id_preimage, - executable: ContractExecutable::Wasm(hash), + key: AccountId, + contract_id_preimage: ContractIdPreimage, + constructor_params: Option<&InvokeContractArgs>, +) -> Result { + let op = if let Some(InvokeContractArgs { args, .. }) = constructor_params { + Operation { + source_account: None, + body: OperationBody::InvokeHostFunction(InvokeHostFunctionOp { + host_function: HostFunction::CreateContractV2(CreateContractArgsV2 { + contract_id_preimage, + executable: ContractExecutable::Wasm(wasm_hash), + constructor_args: args.clone(), + }), + auth: VecM::default(), }), - auth: VecM::default(), - }), + } + } else { + Operation { + source_account: None, + body: OperationBody::InvokeHostFunction(InvokeHostFunctionOp { + host_function: HostFunction::CreateContract(CreateContractArgs { + contract_id_preimage, + executable: ContractExecutable::Wasm(wasm_hash), + }), + auth: VecM::default(), + }), + } }; let tx = Transaction { - source_account: MuxedAccount::Ed25519(key.0.into()), + source_account: key.into(), fee, seq_num: SequenceNumber(sequence), cond: Preconditions::None, @@ -301,7 +353,7 @@ fn build_create_contract_tx( ext: TransactionExt::V0, }; - Ok((tx, contract_id)) + Ok(tx) } #[cfg(test)] @@ -314,18 +366,26 @@ mod tests { .unwrap() .try_into() .unwrap(); + let salt = [0u8; 32]; + let key = + &utils::parse_secret_key("SBFGFF27Y64ZUGFAIG5AMJGQODZZKV2YQKAVUUN4HNE24XZXD2OEUVUP") + .unwrap(); + let source_account = AccountId(PublicKey::PublicKeyTypeEd25519(Uint256( + key.verifying_key().to_bytes(), + ))); + + let contract_id_preimage = ContractIdPreimage::Address(ContractIdPreimageFromAddress { + address: ScAddress::Account(source_account.clone()), + salt: Uint256(salt), + }); + let result = build_create_contract_tx( Hash(hash), 300, 1, - "Public Global Stellar Network ; September 2015", - [0u8; 32], - stellar_strkey::ed25519::PublicKey( - utils::parse_secret_key("SBFGFF27Y64ZUGFAIG5AMJGQODZZKV2YQKAVUUN4HNE24XZXD2OEUVUP") - .unwrap() - .verifying_key() - .to_bytes(), - ), + source_account, + contract_id_preimage, + None, ); assert!(result.is_ok()); diff --git a/cmd/soroban-cli/src/commands/contract/extend.rs b/cmd/soroban-cli/src/commands/contract/extend.rs index 24aac54c5..6ec8ebdb1 100644 --- a/cmd/soroban-cli/src/commands/contract/extend.rs +++ b/cmd/soroban-cli/src/commands/contract/extend.rs @@ -135,7 +135,9 @@ impl NetworkRunnable for Cmd { let extend_to = self.ledgers_to_extend(); // Get the account sequence number - let account_details = client.get_account(&source_account.to_string()).await?; + let account_details = client + .get_account(&source_account.clone().to_string()) + .await?; let sequence: i64 = account_details.seq_num.into(); let tx = Transaction { @@ -184,10 +186,7 @@ impl NetworkRunnable for Cmd { if !events.is_empty() { tracing::info!("Events:\n {events:#?}"); } - let meta = res - .result_meta - .as_ref() - .ok_or(Error::MissingOperationResult)?; + let meta = res.result_meta.ok_or(Error::MissingOperationResult)?; // The transaction from core will succeed regardless of whether it actually found & extended // the entry, so we have to inspect the result meta to tell if it worked or not. diff --git a/cmd/soroban-cli/src/commands/contract/install.rs b/cmd/soroban-cli/src/commands/contract/install.rs index cd6e93b24..a215a987d 100644 --- a/cmd/soroban-cli/src/commands/contract/install.rs +++ b/cmd/soroban-cli/src/commands/contract/install.rs @@ -137,7 +137,9 @@ impl NetworkRunnable for Cmd { // Get the account sequence number let source_account = config.source_account()?; - let account_details = client.get_account(&source_account.to_string()).await?; + let account_details = client + .get_account(&source_account.clone().to_string()) + .await?; let sequence: i64 = account_details.seq_num.into(); let (tx_without_preflight, hash) = @@ -204,7 +206,7 @@ impl NetworkRunnable for Cmd { if let Some(TransactionResult { result: TransactionResultResult::TxInternalError, .. - }) = txn_resp.result.as_ref() + }) = txn_resp.result { // Now just need to restore it and don't have to install again restore::Cmd { diff --git a/cmd/soroban-cli/src/commands/contract/restore.rs b/cmd/soroban-cli/src/commands/contract/restore.rs index 87a52a9f6..92fc4b41d 100644 --- a/cmd/soroban-cli/src/commands/contract/restore.rs +++ b/cmd/soroban-cli/src/commands/contract/restore.rs @@ -136,8 +136,9 @@ impl NetworkRunnable for Cmd { let source_account = config.source_account()?; // Get the account sequence number - let public_strkey = source_account.to_string(); - let account_details = client.get_account(&public_strkey).await?; + let account_details = client + .get_account(&source_account.clone().to_string()) + .await?; let sequence: i64 = account_details.seq_num.into(); let tx = Transaction { @@ -206,7 +207,7 @@ impl NetworkRunnable for Cmd { ); } Ok(TxnResult::Res( - parse_operations(operations).ok_or(Error::MissingOperationResult)?, + parse_operations(&operations.to_vec()).ok_or(Error::MissingOperationResult)?, )) } } diff --git a/cmd/soroban-cli/src/commands/tx/args.rs b/cmd/soroban-cli/src/commands/tx/args.rs index 7e032fd53..fc99b9591 100644 --- a/cmd/soroban-cli/src/commands/tx/args.rs +++ b/cmd/soroban-cli/src/commands/tx/args.rs @@ -39,7 +39,7 @@ impl Args { let source_account = self.source_account()?; let seq_num = self .config - .next_sequence_number(&source_account.to_string()) + .next_sequence_number(source_account.clone().account_id()) .await?; // Once we have a way to add operations this will be updated to allow for a different source account let operation = xdr::Operation { diff --git a/cmd/soroban-cli/src/config/data.rs b/cmd/soroban-cli/src/config/data.rs index bbfc6994e..f032a94d3 100644 --- a/cmd/soroban-cli/src/config/data.rs +++ b/cmd/soroban-cli/src/config/data.rs @@ -209,7 +209,7 @@ mod test { assert_eq!(rpc_uri, new_rpc_uri); match (action, original_action) { (Action::Simulate { response: a }, Action::Simulate { response: b }) => { - assert_eq!(a.cost.cpu_insns, b.cost.cpu_insns); + assert_eq!(a.min_resource_fee, b.min_resource_fee); } _ => panic!("Action mismatch"), } diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index 21ebb1fe9..11eb179ee 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -115,10 +115,19 @@ impl Args { Ok(self.network.get(&self.locator)?) } - pub async fn next_sequence_number(&self, account_str: &str) -> Result { + pub async fn next_sequence_number( + &self, + account: impl Into, + ) -> Result { let network = self.get_network()?; let client = network.rpc_client()?; - Ok((client.get_account(account_str).await?.seq_num.0 + 1).into()) + Ok((client + .get_account(&account.into().to_string()) + .await? + .seq_num + .0 + + 1) + .into()) } } From 048d11b88c50abb7d00123818a29991337526fc4 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Thu, 7 Nov 2024 03:58:33 +1000 Subject: [PATCH 17/77] Fix which macOS arch is used for binary builds (#1705) --- .github/workflows/binaries.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index f2f53bd78..25cea7366 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -33,9 +33,9 @@ jobs: - os: ubuntu-20.04 # Use 20.04 to get an older version of glibc for increased compat target: aarch64-unknown-linux-gnu - os: macos-14 - target: x86_64-apple-darwin - - os: macos-12 target: aarch64-apple-darwin + - os: macos-12 + target: x86_64-apple-darwin - os: windows-latest target: x86_64-pc-windows-msvc ext: .exe From 1fc9c343798657952a6a2bae8350589c096389e0 Mon Sep 17 00:00:00 2001 From: Gleb Date: Wed, 6 Nov 2024 13:54:46 -0800 Subject: [PATCH 18/77] Cleanup unit testing/add ARM support (#1691) * WIP: check make test * Update makefile * Cleanup * Deprecation fix * Add build target * Add libssl-dev * Print openssl dir * cfg path * cfg path * Add sysroot * libssl * ls * fix apt * ln * libssl * arm * ... * tmate * apt sources * Remove tmate * libudev arm64 * Change runner to arm * Fix rust job * Update rust-cache * Uncomment other OSes * Cleanup apt * Update rust-cache * Unpin rust-cache version --- .github/workflows/rust.yml | 14 +++++--------- Makefile | 2 +- .../tests/fixtures/test-wasms/swap/src/test.rs | 4 +++- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9ae750a77..7b046c8c3 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -47,7 +47,7 @@ jobs: sys: - os: ubuntu-latest-16-cores target: x86_64-unknown-linux-gnu - - os: ubuntu-latest-16-cores + - os: ubuntu-jammy-16-cores-arm64 target: aarch64-unknown-linux-gnu - os: macos-latest target: x86_64-apple-darwin @@ -79,14 +79,10 @@ jobs: - if: runner.os == 'Linux' run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev - run: cargo clippy --all-targets --target ${{ matrix.sys.target }} - - run: make build-test - # TODO: enable ARM linux - - if: startsWith(matrix.sys.target, 'x86_64') || runner.os == 'macOS' - # specify directories explicitly (otherwise it will fail with missing symbols) - run: | - for I in cmd/soroban-cli cmd/crates/* cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world ; do - cargo test --target ${{ matrix.sys.target }} --manifest-path $I/Cargo.toml - done + - run: make test + env: + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc + CARGO_BUILD_TARGET: ${{ matrix.sys.target }} publish-dry-run: if: github.event_name == 'push' || startsWith(github.head_ref, 'release/') diff --git a/Makefile b/Makefile index f534410e0..92cdacd73 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ generate-full-help-doc: cargo run --bin doc-gen --features clap-markdown test: build-test - cargo test + cargo test --workspace e2e-test: cargo test --features it --test it -- integration diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs index e32b45e0a..5c973880e 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs @@ -11,7 +11,9 @@ use token::Client as TokenClient; use token::StellarAssetClient as TokenAdminClient; fn create_token_contract<'a>(e: &Env, admin: &Address) -> (TokenClient<'a>, TokenAdminClient<'a>) { - let contract_address = e.register_stellar_asset_contract(admin.clone()); + let contract_address = e + .register_stellar_asset_contract_v2(admin.clone()) + .address(); ( TokenClient::new(e, &contract_address), TokenAdminClient::new(e, &contract_address), From 0b4c3630d423e2a2def8d3b5a922a6c651739317 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Thu, 7 Nov 2024 09:10:30 +1000 Subject: [PATCH 19/77] Add cargo-deny for license checks and dep duplicate avoidance (#1685) --- .github/workflows/rust.yml | 15 +- Cargo.lock | 38 ++-- cmd/crates/stellar-ledger/Cargo.toml | 7 +- deny.toml | 287 +++++++++++++++++++++++++++ 4 files changed, 326 insertions(+), 21 deletions(-) create mode 100644 deny.toml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 7b046c8c3..595e6e817 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,7 +17,7 @@ jobs: complete: if: always() - needs: [fmt, check-generated-full-help-docs, build-and-test, publish-dry-run] + needs: [fmt, cargo-deny, check-generated-full-help-docs, build-and-test, publish-dry-run] runs-on: ubuntu-latest steps: - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') @@ -30,6 +30,19 @@ jobs: - run: rustup update - run: cargo fmt --all --check + cargo-deny: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + check: [advisories, bans, licenses, sources] + continue-on-error: ${{ matrix.check == 'advisories' || matrix.check == 'bans' || matrix.check == 'licenses' }} + steps: + - uses: actions/checkout@v3 + - uses: EmbarkStudios/cargo-deny-action@b01e7a8cfb1f496c52d77361e84c1840d8246393 + with: + command: check ${{ matrix.check }} + check-generated-full-help-docs: runs-on: ubuntu-latest-16-cores steps: diff --git a/Cargo.lock b/Cargo.lock index 806e767ec..6bc90a065 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1701,9 +1701,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1711,9 +1711,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" @@ -1728,9 +1728,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1762,9 +1762,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -1773,21 +1773,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -3013,11 +3013,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -3045,9 +3045,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", diff --git a/cmd/crates/stellar-ledger/Cargo.toml b/cmd/crates/stellar-ledger/Cargo.toml index abf73c375..10fd34e42 100644 --- a/cmd/crates/stellar-ledger/Cargo.toml +++ b/cmd/crates/stellar-ledger/Cargo.toml @@ -10,6 +10,11 @@ version.workspace = true edition = "2021" rust-version.workspace = true +# This crate has not yet ever been published. Skip publishing until these +# security issues are addressed: +# https://github.com/stellar/stellar-cli/issues/1706 +publish = false + [dependencies] soroban-spec = { workspace = true } thiserror = "1.0.32" @@ -47,7 +52,7 @@ once_cell = "1.19.0" pretty_assertions = "1.2.1" serial_test = "3.0.0" httpmock = "0.7.0-rc.1" -test-case = "*" +test-case = "3.3.1" testcontainers = "0.20.1" diff --git a/deny.toml b/deny.toml new file mode 100644 index 000000000..7588e71f1 --- /dev/null +++ b/deny.toml @@ -0,0 +1,287 @@ +# This template contains all of the possible sections and their default values + +# Note that all fields that take a lint level have these possible values: +# * deny - An error will be produced and the check will fail +# * warn - A warning will be produced, but the check will not fail +# * allow - No warning or error will be produced, though in some cases a note +# will be + +# The values provided in this template are the default values that will be used +# when any section or field is not specified in your own configuration + +# Root options + +# If 1 or more target triples (and optionally, target_features) are specified, +# only the specified targets will be checked when running `cargo deny check`. +# This means, if a particular package is only ever used as a target specific +# dependency, such as, for example, the `nix` crate only being used via the +# `target_family = "unix"` configuration, that only having windows targets in +# this list would mean the nix crate, as well as any of its exclusive +# dependencies not shared by any other crates, would be ignored, as the target +# list here is effectively saying which targets you are building for. +targets = [ + { triple = "x86_64-unknown-linux-gnu" }, + { triple = "aarch64-unknown-linux-gnu" }, + { triple = "x86_64-apple-darwin" }, + { triple = "aarch64-apple-darwin" }, + { triple = "x86_64-pc-windows-msvc" }, +] +# When creating the dependency graph used as the source of truth when checks are +# executed, this field can be used to prune crates from the graph, removing them +# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate +# is pruned from the graph, all of its dependencies will also be pruned unless +# they are connected to another crate in the graph that hasn't been pruned, +# so it should be used with care. The identifiers are [Package ID Specifications] +# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html) + +exclude = [ +] + +# If true, metadata will be collected with `--all-features`. Note that this can't +# be toggled off if true, if you want to conditionally enable `--all-features` it +# is recommended to pass `--all-features` on the cmd line instead +all-features = true +# If true, metadata will be collected with `--no-default-features`. The same +# caveat with `all-features` applies +no-default-features = false +# If set, these feature will be enabled when collecting metadata. If `--features` +# is specified on the cmd line they will take precedence over this option. +#features = [] +# When outputting inclusion graphs in diagnostics that include features, this +# option can be used to specify the depth at which feature edges will be added. +# This option is included since the graphs can be quite large and the addition +# of features from the crate(s) to all of the graph roots can be far too verbose. +# This option can be overridden via `--feature-depth` on the cmd line +feature-depth = 1 + +# This section is considered when running `cargo deny check advisories` +# More documentation for the advisories section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html +[advisories] +# The path where the advisory database is cloned/fetched into +db-path = "~/.cargo/advisory-db" +# The url(s) of the advisory databases to use +db-urls = ["https://github.com/rustsec/advisory-db"] +# The lint level for security vulnerabilities +vulnerability = "deny" +# The lint level for unmaintained crates +unmaintained = "warn" +# The lint level for crates that have been yanked from their source registry +yanked = "warn" +# The lint level for crates with security notices. Note that as of +# 2019-12-17 there are no security notice advisories in +# https://github.com/rustsec/advisory-db +notice = "warn" +# A list of advisory IDs to ignore. Note that ignored advisories will still +# output a note when they are encountered. +ignore = [ + #"RUSTSEC-0000-0000", +] +# Threshold for security vulnerabilities, any vulnerability with a CVSS score +# lower than the range specified will be ignored. Note that ignored advisories +# will still output a note when they are encountered. +# * None - CVSS Score 0.0 +# * Low - CVSS Score 0.1 - 3.9 +# * Medium - CVSS Score 4.0 - 6.9 +# * High - CVSS Score 7.0 - 8.9 +# * Critical - CVSS Score 9.0 - 10.0 +#severity-threshold = + +# If this is true, then cargo deny will use the git executable to fetch advisory database. +# If this is false, then it uses a built-in git library. +# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support. +# See Git Authentication for more information about setting up git authentication. +#git-fetch-with-cli = true + +# This section is considered when running `cargo deny check licenses` +# More documentation for the licenses section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html +[licenses] +# The lint level for crates which do not have a detectable license +unlicensed = "deny" +# List of explicitly allowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +allow = [ + "MIT", + "Apache-2.0", + "BSD-3-Clause", + "Apache-2.0 WITH LLVM-exception", + "Unicode-DFS-2016", + "ISC", + "BSD-2-Clause", +] +# List of explicitly disallowed licenses +# See https://spdx.org/licenses/ for list of possible licenses +# [possible values: any SPDX 3.11 short identifier (+ optional exception)]. +deny = [ + #"Nokia", +] +# Lint level for licenses considered copyleft +copyleft = "deny" +# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses +# * both - The license will be approved if it is both OSI-approved *AND* FSF +# * either - The license will be approved if it is either OSI-approved *OR* FSF +# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF +# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved +# * neither - This predicate is ignored and the default lint level is used +allow-osi-fsf-free = "neither" +# Lint level used when no other predicates are matched +# 1. License isn't in the allow or deny lists +# 2. License isn't copyleft +# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither" +default = "deny" +# The confidence threshold for detecting a license from license text. +# The higher the value, the more closely the license text must be to the +# canonical license text of a valid SPDX license file. +# [possible values: any between 0.0 and 1.0]. +confidence-threshold = 0.8 +# Allow 1 or more licenses on a per-crate basis, so that particular licenses +# aren't accepted for every possible crate as with the normal allow list +exceptions = [ + # The following dep licenses were inspected and approved for use because we + # do not fork them. Related conversation and approval is at: + # https://stellarfoundation.slack.com/archives/C07TC92R2P7/p1730924548048429?thread_ts=1730900591.962089&cid=C07TC92R2P7 + { allow = ["MPL-2.0"], name = "option-ext" }, + { allow = ["MPL-2.0"], name = "webpki-roots" }, + # The following dep licensed was manually reviewed and approved for use. Related conversation and approval is at: + # https://stellarfoundation.slack.com/archives/C07TC92R2P7/p1730917671563029?thread_ts=1730903286.490759&cid=C07TC92R2P7 + { allow = ["OpenSSL"], name = "ring" }, +] + +[[licenses.clarify]] +name = "ring" +expression = "MIT AND ISC AND OpenSSL" +license-files = [ + { path = "LICENSE", hash = 0xbd0eed23 } +] + +# Some crates don't have (easily) machine readable licensing information, +# adding a clarification entry for it allows you to manually specify the +# licensing information +#[[licenses.clarify]] +# The name of the crate the clarification applies to +#name = "ring" +# The optional version constraint for the crate +#version = "*" +# The SPDX expression for the license requirements of the crate +#expression = "MIT AND ISC AND OpenSSL" +# One or more files in the crate's source used as the "source of truth" for +# the license expression. If the contents match, the clarification will be used +# when running the license check, otherwise the clarification will be ignored +# and the crate will be checked normally, which may produce warnings or errors +# depending on the rest of your configuration +#license-files = [ + # Each entry is a crate relative path, and the (opaque) hash of its contents + #{ path = "LICENSE", hash = 0xbd0eed23 } +#] + +[licenses.private] +# If true, ignores workspace crates that aren't published, or are only +# published to private registries. +# To see how to mark a crate as unpublished (to the official registry), +# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field. +ignore = true +# One or more private registries that you might publish crates to, if a crate +# is only published to private registries, and ignore is true, the crate will +# not have its license(s) checked +registries = [ + #"https://sekretz.com/registry +] + +# This section is considered when running `cargo deny check bans`. +# More documentation about the 'bans' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html +[bans] +# Lint level for when multiple versions of the same crate are detected +multiple-versions = "deny" +# Lint level for when a crate version requirement is `*` +wildcards = "deny" +allow-wildcard-paths = true +# The graph highlighting used when creating dotgraphs for crates +# with multiple versions +# * lowest-version - The path to the lowest versioned duplicate is highlighted +# * simplest-path - The path to the version with the fewest edges is highlighted +# * all - Both lowest-version and simplest-path are used +highlight = "all" +# The default lint level for `default` features for crates that are members of +# the workspace that is being checked. This can be overridden by allowing/denying +# `default` on a crate-by-crate basis if desired. +workspace-default-features = "allow" +# The default lint level for `default` features for external crates that are not +# members of the workspace. This can be overridden by allowing/denying `default` +# on a crate-by-crate basis if desired. +external-default-features = "allow" +# List of crates that are allowed. Use with care! +allow = [ + #{ name = "ansi_term", version = "=0.11.0" }, +] +# List of crates to deny +deny = [ + # Each entry the name of a crate and a version range. If version is + # not specified, all versions will be matched. + #{ name = "ansi_term", version = "=0.11.0" }, + # + # Wrapper crates can optionally be specified to allow the crate when it + # is a direct dependency of the otherwise banned crate + #{ name = "ansi_term", version = "=0.11.0", wrappers = [] }, +] + +# List of features to allow/deny +# Each entry the name of a crate and a version range. If version is +# not specified, all versions will be matched. +#[[bans.features]] +#name = "reqwest" +# Features to not allow +#deny = ["json"] +# Features to allow +#allow = [ +# "rustls", +# "__rustls", +# "__tls", +# "hyper-rustls", +# "rustls", +# "rustls-pemfile", +# "rustls-tls-webpki-roots", +# "tokio-rustls", +# "webpki-roots", +#] +# If true, the allowed features must exactly match the enabled feature set. If +# this is set there is no point setting `deny` +#exact = true + +# Certain crates/versions that will be skipped when doing duplicate detection. +skip = [ + # { name = "hashbrown", version = "=0.13.2" }, + # { name = "syn", version = "=1.0.109" }, +] +# Similarly to `skip` allows you to skip certain crates during duplicate +# detection. Unlike skip, it also includes the entire tree of transitive +# dependencies starting at the specified crate, up to a certain depth, which is +# by default infinite. +skip-tree = [ +] + +# This section is considered when running `cargo deny check sources`. +# More documentation about the 'sources' section can be found here: +# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html +[sources] +# Lint level for what to happen when a crate from a crate registry that is not +# in the allow list is encountered +unknown-registry = "deny" +# Lint level for what to happen when a crate from a git repository that is not +# in the allow list is encountered +unknown-git = "deny" +# List of URLs for allowed crate registries. Defaults to the crates.io index +# if not specified. If it is specified but empty, no registries are allowed. +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +# List of URLs for allowed Git repositories +allow-git = [] + +[sources.allow-org] +# 1 or more github.com organizations to allow git sources for +github = ["stellar"] +# 1 or more gitlab.com organizations to allow git sources for +# gitlab = [""] +# 1 or more bitbucket.org organizations to allow git sources for +# bitbucket = [""] From eb4c0de8c9f482f646b2c5bc716380201c7fb71e Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Wed, 6 Nov 2024 16:16:36 -0800 Subject: [PATCH 20/77] Do not overwrite existing keys when generating new ones. (#1709) --- .gitignore | 1 + FULL_HELP_DOCS.md | 1 + .../soroban-test/tests/it/integration.rs | 2 +- .../soroban-test/tests/it/integration/fund.rs | 23 ------ .../soroban-test/tests/it/integration/keys.rs | 76 +++++++++++++++++++ cmd/soroban-cli/src/commands/keys/generate.rs | 26 ++++++- cmd/soroban-cli/src/print.rs | 1 + 7 files changed, 105 insertions(+), 25 deletions(-) delete mode 100644 cmd/crates/soroban-test/tests/it/integration/fund.rs create mode 100644 cmd/crates/soroban-test/tests/it/integration/keys.rs diff --git a/.gitignore b/.gitignore index 7723bb84b..b7150ae5d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ test_snapshots .vscode/settings.json .idea local.sh +.stellar diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index ae25453c6..48cc98aa9 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1019,6 +1019,7 @@ Generate a new identity with a seed phrase, currently 12 words * `--fund` — Fund generated key pair Default value: `false` +* `--overwrite` — Overwrite existing identity if it already exists diff --git a/cmd/crates/soroban-test/tests/it/integration.rs b/cmd/crates/soroban-test/tests/it/integration.rs index d6db5842b..3ec0d61ed 100644 --- a/cmd/crates/soroban-test/tests/it/integration.rs +++ b/cmd/crates/soroban-test/tests/it/integration.rs @@ -3,8 +3,8 @@ mod constructor; mod cookbook; mod custom_types; mod dotenv; -mod fund; mod hello_world; +mod keys; mod snapshot; mod tx; mod util; diff --git a/cmd/crates/soroban-test/tests/it/integration/fund.rs b/cmd/crates/soroban-test/tests/it/integration/fund.rs deleted file mode 100644 index 263775412..000000000 --- a/cmd/crates/soroban-test/tests/it/integration/fund.rs +++ /dev/null @@ -1,23 +0,0 @@ -use soroban_test::TestEnv; - -#[tokio::test] -#[allow(clippy::too_many_lines)] -async fn fund() { - let sandbox = &TestEnv::new(); - sandbox - .new_assert_cmd("keys") - .arg("generate") - .arg("test") - .assert() - .success(); - sandbox - .new_assert_cmd("keys") - .arg("fund") - .arg("test") - .assert() - // Don't expect error if friendbot indicated that the account is - // already fully funded to the starting balance, because the - // user's goal is to get funded, and the account is funded - // so it is success much the same. - .success(); -} diff --git a/cmd/crates/soroban-test/tests/it/integration/keys.rs b/cmd/crates/soroban-test/tests/it/integration/keys.rs new file mode 100644 index 000000000..267a0b095 --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/integration/keys.rs @@ -0,0 +1,76 @@ +use predicates::prelude::predicate; +use soroban_test::AssertExt; +use soroban_test::TestEnv; + +fn pubkey_for_identity(sandbox: &TestEnv, name: &str) -> String { + let output = sandbox + .new_assert_cmd("keys") + .arg("address") + .arg(name) + .assert() + .stdout_as_str(); + return output; +} + +#[tokio::test] +#[allow(clippy::too_many_lines)] +async fn fund() { + let sandbox = &TestEnv::new(); + sandbox + .new_assert_cmd("keys") + .arg("generate") + .arg("test2") + .assert() + .success(); + sandbox + .new_assert_cmd("keys") + .arg("fund") + .arg("test2") + .assert() + // Don't expect error if friendbot indicated that the account is + // already fully funded to the starting balance, because the + // user's goal is to get funded, and the account is funded + // so it is success much the same. + .success(); +} + +#[tokio::test] +#[allow(clippy::too_many_lines)] +async fn overwrite_identity() { + let sandbox = &TestEnv::new(); + sandbox + .new_assert_cmd("keys") + .arg("generate") + .arg("test2") + .assert() + .success(); + + let initial_pubkey = sandbox + .new_assert_cmd("keys") + .arg("address") + .arg("test2") + .assert() + .stdout_as_str(); + + sandbox + .new_assert_cmd("keys") + .arg("generate") + .arg("test2") + .assert() + .stderr(predicate::str::contains( + "error: An identity with the name 'test2' already exists", + )); + + assert_eq!(initial_pubkey, pubkey_for_identity(&sandbox, "test2")); + + sandbox + .new_assert_cmd("keys") + .arg("generate") + .arg("test2") + .arg("--overwrite") + .assert() + .stderr(predicate::str::contains("Overwriting identity 'test2'")) + .success(); + + assert_ne!(initial_pubkey, pubkey_for_identity(&sandbox, "test2")); +} diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index b59e227fc..c6623386c 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -10,10 +10,15 @@ use crate::{commands::global, print::Print}; pub enum Error { #[error(transparent)] Config(#[from] locator::Error), + #[error(transparent)] Secret(#[from] secret::Error), + #[error(transparent)] Network(#[from] network::Error), + + #[error("An identity with the name '{0}' already exists")] + IdentityAlreadyExists(String), } #[derive(Debug, clap::Parser, Clone)] @@ -52,29 +57,47 @@ pub struct Cmd { /// Fund generated key pair #[arg(long, default_value = "false")] pub fund: bool, + + /// Overwrite existing identity if it already exists. + #[arg(long)] + pub overwrite: bool, } impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let print = Print::new(global_args.quiet); + + if self.config_locator.read_identity(&self.name).is_ok() { + if !self.overwrite { + return Err(Error::IdentityAlreadyExists(self.name.clone())); + } + + print.exclaimln(format!("Overwriting identity '{}'", &self.name)); + } + if !self.fund { - Print::new(global_args.quiet).warnln( + print.warnln( "Behavior of `generate` will change in the \ future, and it will no longer fund by default. If you want to fund please \ provide `--fund` flag. If you don't need to fund your keys in the future, ignore this \ warning. It can be suppressed with -q flag.", ); } + let seed_phrase = if self.default_seed { Secret::test_seed_phrase() } else { Secret::from_seed(self.seed.as_deref()) }?; + let secret = if self.as_secret { seed_phrase.private_key(self.hd_path)?.into() } else { seed_phrase }; + self.config_locator.write_identity(&self.name, &secret)?; + if !self.no_fund { let addr = secret.public_key(self.hd_path)?; let network = self.network.get(&self.config_locator)?; @@ -86,6 +109,7 @@ impl Cmd { }) .unwrap_or_default(); } + Ok(()) } } diff --git a/cmd/soroban-cli/src/print.rs b/cmd/soroban-cli/src/print.rs index ca66cdc50..fb9fb43dd 100644 --- a/cmd/soroban-cli/src/print.rs +++ b/cmd/soroban-cli/src/print.rs @@ -105,3 +105,4 @@ create_print_functions!(plus, plusln, "➕"); create_print_functions!(save, saveln, "💾"); create_print_functions!(search, searchln, "🔎"); create_print_functions!(warn, warnln, "⚠️"); +create_print_functions!(exclaim, exclaimln, "❗️"); From 794fd4440e25de9c5a63c18015def2e421bd1ead Mon Sep 17 00:00:00 2001 From: Nnaji Benjamin <60315147+Benjtalkshow@users.noreply.github.com> Date: Thu, 7 Nov 2024 02:02:16 +0100 Subject: [PATCH 21/77] upgrade typescript to latest version (#1641) * upgrade typescript to latest version * upgrade tyoescript to latest version --------- Co-authored-by: Willem Wyndham Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- .../test_custom_types/package-lock.json | 18 ++++++++++++++++++ .../fixtures/test_custom_types/package.json | 5 +++-- .../src/project_template/package.json | 6 +++--- .../ts-tests/package-lock.json | 9 +++++---- .../ts-tests/package.json | 5 ++--- 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json index f45484ffb..172a80888 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json @@ -12,6 +12,7 @@ "buffer": "6.0.3" }, "devDependencies": { + "@types/node": "^22.7.4", "typescript": "5.3.3" } }, @@ -47,6 +48,16 @@ "urijs": "^1.19.1" } }, + "node_modules/@types/node": { + "version": "22.7.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", + "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, "node_modules/asynckit": { "version": "0.4.0", "license": "MIT" @@ -288,6 +299,13 @@ "node": ">=14.17" } }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, "node_modules/urijs": { "version": "1.19.11", "license": "MIT" diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json index 5cc5e337f..35504c2c5 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json @@ -8,10 +8,11 @@ "build": "tsc" }, "dependencies": { - "buffer": "6.0.3", - "@stellar/stellar-sdk": "12.1.0" + "@stellar/stellar-sdk": "12.1.0", + "buffer": "6.0.3" }, "devDependencies": { + "@types/node": "^22.7.4", "typescript": "5.3.3" } } diff --git a/cmd/crates/soroban-spec-typescript/src/project_template/package.json b/cmd/crates/soroban-spec-typescript/src/project_template/package.json index e9ba581a3..553d45831 100644 --- a/cmd/crates/soroban-spec-typescript/src/project_template/package.json +++ b/cmd/crates/soroban-spec-typescript/src/project_template/package.json @@ -8,10 +8,10 @@ "build": "tsc" }, "dependencies": { - "buffer": "6.0.3", - "@stellar/stellar-sdk": "12.1.0" + "@stellar/stellar-sdk": "12.1.0", + "buffer": "6.0.3" }, "devDependencies": { - "typescript": "5.3.3" + "typescript": "^5.6.2" } } diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json index deee8f09d..357de4a2c 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json @@ -14,7 +14,7 @@ "ava": "^5.3.1", "dotenv": "^16.3.1", "eslint": "^8.53.0", - "typescript": "^5.3.3" + "typescript": "^5.6.2" } }, "node_modules/@ava/typescript": { @@ -3194,10 +3194,11 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", + "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/package.json b/cmd/crates/soroban-spec-typescript/ts-tests/package.json index 734b26bba..b3f1990dd 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/package.json +++ b/cmd/crates/soroban-spec-typescript/ts-tests/package.json @@ -8,14 +8,14 @@ }, "devDependencies": { "@ava/typescript": "^4.1.0", + "@stellar/stellar-sdk": "12.2.0", "@types/node": "^20.4.9", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", "ava": "^5.3.1", "dotenv": "^16.3.1", "eslint": "^8.53.0", - "@stellar/stellar-sdk": "12.2.0", - "typescript": "^5.3.3" + "typescript": "^5.6.2" }, "ava": { "typescript": { @@ -29,4 +29,3 @@ ] } } - From 9912694cfb6f67c4ccfbcba62a27aa22aa43cc17 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Thu, 7 Nov 2024 05:29:02 -0800 Subject: [PATCH 22/77] Resolve identity from default config. (#1711) --- FULL_HELP_DOCS.md | 64 ++++++++++++++++++++------- cmd/soroban-cli/src/config/address.rs | 14 ++++-- cmd/soroban-cli/src/config/mod.rs | 7 ++- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 48cc98aa9..6f3882ce6 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -130,7 +130,7 @@ Get Id of builtin Soroban Asset Contract. Deprecated, use `stellar contract id a Deploy builtin Soroban Asset Contract -**Usage:** `stellar contract asset deploy [OPTIONS] --asset --source-account ` +**Usage:** `stellar contract asset deploy [OPTIONS] --asset ` ###### **Options:** @@ -140,6 +140,8 @@ Deploy builtin Soroban Asset Contract * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -345,7 +347,7 @@ Extend the time to live ledger of a contract-data ledger entry. If no keys are specified the contract itself is extended. -**Usage:** `stellar contract extend [OPTIONS] --ledgers-to-extend --source-account ` +**Usage:** `stellar contract extend [OPTIONS] --ledgers-to-extend ` ###### **Options:** @@ -371,6 +373,8 @@ If no keys are specified the contract itself is extended. * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -388,7 +392,7 @@ If no keys are specified the contract itself is extended. Deploy a wasm contract -**Usage:** `stellar contract deploy [OPTIONS] --source-account <--wasm |--wasm-hash > [-- ...]` +**Usage:** `stellar contract deploy [OPTIONS] <--wasm |--wasm-hash > [-- ...]` ###### **Arguments:** @@ -404,6 +408,8 @@ Deploy a wasm contract * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -475,7 +481,7 @@ Deploy builtin Soroban Asset Contract Deploy normal Wasm Contract -**Usage:** `stellar contract id wasm [OPTIONS] --salt --source-account ` +**Usage:** `stellar contract id wasm [OPTIONS] --salt ` ###### **Options:** @@ -485,6 +491,8 @@ Deploy normal Wasm Contract * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -676,7 +684,7 @@ This command will create a Cargo workspace project and add a sample Stellar cont Install a WASM file to the ledger without creating a contract instance -**Usage:** `stellar contract install [OPTIONS] --source-account --wasm ` +**Usage:** `stellar contract install [OPTIONS] --wasm ` ###### **Options:** @@ -685,6 +693,8 @@ Install a WASM file to the ledger without creating a contract instance * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -710,7 +720,7 @@ Generates an "implicit CLI" for the specified contract on-the-fly using the cont stellar contract invoke ... -- --help -**Usage:** `stellar contract invoke [OPTIONS] --id --source-account [-- ...]` +**Usage:** `stellar contract invoke [OPTIONS] --id [-- ...]` ###### **Arguments:** @@ -725,6 +735,8 @@ stellar contract invoke ... -- --help * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -813,7 +825,7 @@ Restore an evicted value for a contract-data legder entry. If no keys are specificed the contract itself is restored. -**Usage:** `stellar contract restore [OPTIONS] --source-account ` +**Usage:** `stellar contract restore [OPTIONS]` ###### **Options:** @@ -839,6 +851,8 @@ If no keys are specificed the contract itself is restored. * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1377,7 +1391,7 @@ Sign, Simulate, and Send transactions Simulate a transaction envelope from stdin -**Usage:** `stellar tx simulate [OPTIONS] --source-account ` +**Usage:** `stellar tx simulate [OPTIONS]` ###### **Options:** @@ -1386,6 +1400,8 @@ Simulate a transaction envelope from stdin * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1467,7 +1483,7 @@ Create a new transaction Transfers the XLM balance of an account to another account and removes the source account from the ledger -**Usage:** `stellar tx new account-merge [OPTIONS] --source-account --account ` +**Usage:** `stellar tx new account-merge [OPTIONS] --account ` ###### **Options:** @@ -1483,6 +1499,8 @@ Transfers the XLM balance of an account to another account and removes the sourc * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1494,7 +1512,7 @@ Transfers the XLM balance of an account to another account and removes the sourc Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number -**Usage:** `stellar tx new bump-sequence [OPTIONS] --source-account --bump-to ` +**Usage:** `stellar tx new bump-sequence [OPTIONS] --bump-to ` ###### **Options:** @@ -1510,6 +1528,8 @@ Bumps forward the sequence number of the source account to the given sequence nu * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1521,7 +1541,7 @@ Bumps forward the sequence number of the source account to the given sequence nu Creates, updates, or deletes a trustline Learn more about trustlines https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines -**Usage:** `stellar tx new change-trust [OPTIONS] --source-account --line ` +**Usage:** `stellar tx new change-trust [OPTIONS] --line ` ###### **Options:** @@ -1537,6 +1557,8 @@ Creates, updates, or deletes a trustline Learn more about trustlines https://dev * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1551,7 +1573,7 @@ Creates, updates, or deletes a trustline Learn more about trustlines https://dev Creates and funds a new account with the specified starting balance -**Usage:** `stellar tx new create-account [OPTIONS] --source-account --destination ` +**Usage:** `stellar tx new create-account [OPTIONS] --destination ` ###### **Options:** @@ -1567,6 +1589,8 @@ Creates and funds a new account with the specified starting balance * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1581,7 +1605,7 @@ Creates and funds a new account with the specified starting balance Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account Learn more about entries and subentries: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries -**Usage:** `stellar tx new manage-data [OPTIONS] --source-account --data-name ` +**Usage:** `stellar tx new manage-data [OPTIONS] --data-name ` ###### **Options:** @@ -1597,6 +1621,8 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1609,7 +1635,7 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an Sends an amount in a specific asset to a destination account -**Usage:** `stellar tx new payment [OPTIONS] --source-account --destination --amount ` +**Usage:** `stellar tx new payment [OPTIONS] --destination --amount ` ###### **Options:** @@ -1625,6 +1651,8 @@ Sends an amount in a specific asset to a destination account * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1640,7 +1668,7 @@ Sends an amount in a specific asset to a destination account Set option for an account such as flags, inflation destination, signers, home domain, and master key weight Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags Learn more about the home domain: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md Learn more about signers operations and key weight: https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig -**Usage:** `stellar tx new set-options [OPTIONS] --source-account ` +**Usage:** `stellar tx new set-options [OPTIONS]` ###### **Options:** @@ -1656,6 +1684,8 @@ Set option for an account such as flags, inflation destination, signers, home do * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1682,7 +1712,7 @@ Set option for an account such as flags, inflation destination, signers, home do Allows issuing account to configure authorization and trustline flags to an asset The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags -**Usage:** `stellar tx new set-trustline-flags [OPTIONS] --source-account --trustor --asset ` +**Usage:** `stellar tx new set-trustline-flags [OPTIONS] --trustor --asset ` ###### **Options:** @@ -1698,6 +1728,8 @@ Allows issuing account to configure authorization and trustline flags to an asse * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail + + Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 066bc8d91..811548316 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use crate::xdr; -use super::{locator, secret}; +use super::{locator, secret, Config}; /// Address can be either a public key or eventually an alias of a address. #[derive(Clone, Debug)] @@ -31,8 +31,16 @@ impl FromStr for Address { type Err = Error; fn from_str(value: &str) -> Result { - Ok(xdr::MuxedAccount::from_str(value).map_or_else( - |_| Address::AliasOrSecret(value.to_string()), + let mut identity = value.to_string(); + + if value.is_empty() { + if let Ok(config) = Config::new() { + identity = config.defaults.identity.unwrap_or_default(); + } + } + + Ok(xdr::MuxedAccount::from_str(&identity).map_or_else( + |_| Address::AliasOrSecret(identity.to_string()), Address::MuxedAccount, )) } diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index 11eb179ee..396b2b8cc 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -47,7 +47,12 @@ pub struct Args { #[command(flatten)] pub network: network::Args, - #[arg(long, visible_alias = "source", env = "STELLAR_ACCOUNT")] + #[arg( + long, + visible_alias = "source", + env = "STELLAR_ACCOUNT", + default_value = "" + )] /// Account that where transaction originates from. Alias `source`. /// Can be an identity (--source alice), a public key (--source GDKW...), /// a muxed account (--source MDA…), a secret key (--source SC36…), From 11e08eff6915390e388a06a359d01d9594e64954 Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Thu, 7 Nov 2024 14:40:01 -0500 Subject: [PATCH 23/77] feat(ts-bindings): upgrade stellar-sdk to 12.2.0 (#1606) * feat(ts-bindings): upgrade stellar-sdk to 12.2.0 This is the latest version * feat(ts-bindings): upgrade stellar-sdk to 12.3.0 This is the latest version --------- Co-authored-by: Nando Vieira --- .../test_custom_types/package-lock.json | 93 +++++++++++-------- .../fixtures/test_custom_types/package.json | 5 +- .../src/project_template/package.json | 2 +- .../ts-tests/package-lock.json | 68 +++++++++----- .../ts-tests/package.json | 2 +- 5 files changed, 103 insertions(+), 67 deletions(-) diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json index 172a80888..454c8b964 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json @@ -8,23 +8,26 @@ "name": "test_custom_types", "version": "0.0.0", "dependencies": { - "@stellar/stellar-sdk": "12.1.0", + "@stellar/stellar-sdk": "12.3.0", "buffer": "6.0.3" }, "devDependencies": { - "@types/node": "^22.7.4", - "typescript": "5.3.3" + "typescript": "^5.6.2" } }, "node_modules/@stellar/js-xdr": { - "version": "3.1.1", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-3.1.2.tgz", + "integrity": "sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==", "license": "Apache-2.0" }, "node_modules/@stellar/stellar-base": { - "version": "12.0.1", + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-12.1.1.tgz", + "integrity": "sha512-gOBSOFDepihslcInlqnxKZdIW9dMUO1tpOm3AtJR33K2OvpXG6SaVHCzAmCFArcCqI9zXTEiSoh70T48TmiHJA==", "license": "Apache-2.0", "dependencies": { - "@stellar/js-xdr": "^3.1.1", + "@stellar/js-xdr": "^3.1.2", "base32.js": "^0.1.0", "bignumber.js": "^9.1.2", "buffer": "^6.0.3", @@ -36,11 +39,13 @@ } }, "node_modules/@stellar/stellar-sdk": { - "version": "12.1.0", + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-12.3.0.tgz", + "integrity": "sha512-F2DYFop/M5ffXF0lvV5Ezjk+VWNKg0QDX8gNhwehVU3y5LYA3WAY6VcCarMGPaG9Wdgoeh1IXXzOautpqpsltw==", "license": "Apache-2.0", "dependencies": { - "@stellar/stellar-base": "^12.0.1", - "axios": "^1.7.2", + "@stellar/stellar-base": "^12.1.1", + "axios": "^1.7.7", "bignumber.js": "^9.1.2", "eventsource": "^2.0.2", "randombytes": "^2.1.0", @@ -48,24 +53,17 @@ "urijs": "^1.19.1" } }, - "node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, "node_modules/asynckit": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -74,6 +72,8 @@ }, "node_modules/base32.js": { "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", + "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", "license": "MIT", "engines": { "node": ">=0.12.0" @@ -99,6 +99,8 @@ }, "node_modules/bignumber.js": { "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", "license": "MIT", "engines": { "node": "*" @@ -128,6 +130,8 @@ }, "node_modules/combined-stream": { "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -138,6 +142,8 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -151,7 +157,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.6", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -169,7 +177,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -200,10 +210,14 @@ }, "node_modules/inherits": { "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/mime-db": { "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -211,6 +225,8 @@ }, "node_modules/mime-types": { "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -220,7 +236,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.1", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", "license": "MIT", "optional": true, "bin": { @@ -231,6 +249,8 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, "node_modules/randombytes": { @@ -260,6 +280,8 @@ }, "node_modules/sha.js": { "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", @@ -270,8 +292,9 @@ } }, "node_modules/sodium-native": { - "version": "4.1.1", - "hasInstallScript": true, + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.0.tgz", + "integrity": "sha512-OcMgoS0NJx+4yVUlhvL9uZsVZfmyHZ2RpSXkiIoOHMglqvJDeGwn1rUigPrvcNTq3m9hPXtt6syxQbF3vvwmRQ==", "license": "MIT", "optional": true, "dependencies": { @@ -284,13 +307,16 @@ }, "node_modules/tweetnacl": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", "license": "Unlicense" }, "node_modules/typescript": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", - "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -299,13 +325,6 @@ "node": ">=14.17" } }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true, - "license": "MIT" - }, "node_modules/urijs": { "version": "1.19.11", "license": "MIT" diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json index 35504c2c5..a52979626 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json @@ -8,11 +8,10 @@ "build": "tsc" }, "dependencies": { - "@stellar/stellar-sdk": "12.1.0", + "@stellar/stellar-sdk": "12.3.0", "buffer": "6.0.3" }, "devDependencies": { - "@types/node": "^22.7.4", - "typescript": "5.3.3" + "typescript": "^5.6.2" } } diff --git a/cmd/crates/soroban-spec-typescript/src/project_template/package.json b/cmd/crates/soroban-spec-typescript/src/project_template/package.json index 553d45831..1d7d48793 100644 --- a/cmd/crates/soroban-spec-typescript/src/project_template/package.json +++ b/cmd/crates/soroban-spec-typescript/src/project_template/package.json @@ -8,7 +8,7 @@ "build": "tsc" }, "dependencies": { - "@stellar/stellar-sdk": "12.1.0", + "@stellar/stellar-sdk": "12.3.0", "buffer": "6.0.3" }, "devDependencies": { diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json index 357de4a2c..dec6997a7 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json @@ -7,7 +7,7 @@ "hasInstallScript": true, "devDependencies": { "@ava/typescript": "^4.1.0", - "@stellar/stellar-sdk": "12.2.0", + "@stellar/stellar-sdk": "12.3.0", "@types/node": "^20.4.9", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", @@ -202,13 +202,15 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-3.1.2.tgz", "integrity": "sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/@stellar/stellar-base": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-12.1.0.tgz", - "integrity": "sha512-pWwn+XWP5NotmIteZNuJzHeNn9DYSqH3lsYbtFUoSYy1QegzZdi9D8dK6fJ2fpBAnf/rcDjHgHOw3gtHaQFVbg==", + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-12.1.1.tgz", + "integrity": "sha512-gOBSOFDepihslcInlqnxKZdIW9dMUO1tpOm3AtJR33K2OvpXG6SaVHCzAmCFArcCqI9zXTEiSoh70T48TmiHJA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@stellar/js-xdr": "^3.1.2", "base32.js": "^0.1.0", @@ -222,13 +224,14 @@ } }, "node_modules/@stellar/stellar-sdk": { - "version": "12.2.0", - "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-12.2.0.tgz", - "integrity": "sha512-Wy5sDOqb5JvAC76f4sQIV6Pe3JNyZb0PuyVNjwt3/uWsjtxRkFk6s2yTHTefBLWoR+mKxDjO7QfzhycF1v8FXQ==", + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-12.3.0.tgz", + "integrity": "sha512-F2DYFop/M5ffXF0lvV5Ezjk+VWNKg0QDX8gNhwehVU3y5LYA3WAY6VcCarMGPaG9Wdgoeh1IXXzOautpqpsltw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@stellar/stellar-base": "^12.1.0", - "axios": "^1.7.2", + "@stellar/stellar-base": "^12.1.1", + "axios": "^1.7.7", "bignumber.js": "^9.1.2", "eventsource": "^2.0.2", "randombytes": "^2.1.0", @@ -601,7 +604,8 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ava": { "version": "5.3.1", @@ -700,10 +704,11 @@ } }, "node_modules/axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -721,6 +726,7 @@ "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -750,6 +756,7 @@ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -1043,6 +1050,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1162,6 +1170,7 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -1658,9 +1667,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ { @@ -1668,6 +1677,7 @@ "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -1682,6 +1692,7 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -2247,6 +2258,7 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2256,6 +2268,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -2303,10 +2316,11 @@ "dev": true }, "node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", + "version": "4.8.2", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", + "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", "dev": true, + "license": "MIT", "optional": true, "bin": { "node-gyp-build": "bin.js", @@ -2703,7 +2717,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/punycode": { "version": "2.3.1", @@ -2906,6 +2921,7 @@ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -2967,11 +2983,12 @@ } }, "node_modules/sodium-native": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.1.1.tgz", - "integrity": "sha512-LXkAfRd4FHtkQS4X6g+nRcVaN7mWVNepV06phIsC6+IZFvGh1voW5TNQiQp2twVaMf05gZqQjuS+uWLM6gHhNQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.2.0.tgz", + "integrity": "sha512-rdJRAf/RE/IRFUUoUsz10slNAQDTGz5ChpIeR1Ti0BtGYstl6Uok4hHALPBdnFcLml6qXJ2pDd0/De09mPa6mg==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "dependencies": { "node-gyp-build": "^4.8.0" @@ -3167,7 +3184,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "dev": true + "dev": true, + "license": "Unlicense" }, "node_modules/type-check": { "version": "0.4.0", diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/package.json b/cmd/crates/soroban-spec-typescript/ts-tests/package.json index b3f1990dd..69a17eb5c 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/package.json +++ b/cmd/crates/soroban-spec-typescript/ts-tests/package.json @@ -8,7 +8,7 @@ }, "devDependencies": { "@ava/typescript": "^4.1.0", - "@stellar/stellar-sdk": "12.2.0", + "@stellar/stellar-sdk": "12.3.0", "@types/node": "^20.4.9", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", From 8e1d45b53392338f26a41fa60e99b09dcd14b20f Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 8 Nov 2024 06:16:33 +1000 Subject: [PATCH 24/77] Move container command to root (#1710) --- FULL_HELP_DOCS.md | 93 +++++++++++++++++-- .../commands/{network => }/container/logs.rs | 2 +- .../container.rs => container/mod.rs} | 4 +- .../{network => }/container/shared.rs | 0 .../commands/{network => }/container/start.rs | 2 +- .../commands/{network => }/container/stop.rs | 2 +- cmd/soroban-cli/src/commands/mod.rs | 11 ++- cmd/soroban-cli/src/commands/network/mod.rs | 21 +++-- 8 files changed, 114 insertions(+), 21 deletions(-) rename cmd/soroban-cli/src/commands/{network => }/container/logs.rs (94%) rename cmd/soroban-cli/src/commands/{network/container.rs => container/mod.rs} (91%) rename cmd/soroban-cli/src/commands/{network => }/container/shared.rs (100%) rename cmd/soroban-cli/src/commands/{network => }/container/start.rs (99%) rename cmd/soroban-cli/src/commands/{network => }/container/stop.rs (95%) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 6f3882ce6..581c2cb87 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -47,7 +47,8 @@ Anything after the `--` double dash (the "slop") is parsed as arguments to the c * `events` — Watch the network for contract events * `env` — Prints the current environment variables or defaults to the stdout, in a format that can be used as .env file. Environment variables have precedency over defaults * `keys` — Create and manage identities including keys and addresses -* `network` — Start and configure networks +* `network` — Configure connection to networks +* `container` — Start local networks in containers * `snapshot` — Download a snapshot of a ledger from an archive * `tx` — Sign, Simulate, and Send transactions * `xdr` — Decode and encode XDR @@ -1105,7 +1106,7 @@ Set the default identity that will be used on all commands. This allows you to s ## `stellar network` -Start and configure networks +Configure connection to networks **Usage:** `stellar network ` @@ -1117,7 +1118,7 @@ Start and configure networks * `start` — ⚠️ Deprecated: use `stellar container start` instead * `stop` — ⚠️ Deprecated: use `stellar container stop` instead * `use` — Set the default network that will be used on all commands. This allows you to skip `--network` or setting a environment variable, while reusing this value in all commands that require it -* `container` — Commands to start, stop and get logs for a quickstart container +* `container` — ⚠️ Deprecated: use `stellar container` instead @@ -1245,6 +1246,8 @@ Set the default network that will be used on all commands. This allows you to sk ## `stellar network container` +⚠️ Deprecated: use `stellar container` instead + Commands to start, stop and get logs for a quickstart container **Usage:** `stellar network container ` @@ -1253,7 +1256,7 @@ Commands to start, stop and get logs for a quickstart container * `logs` — Get logs from a running network container * `start` — Start a container running a Stellar node, RPC, API, and friendbot (faucet) -* `stop` — Stop a network container started with `network container start` +* `stop` — Stop a network container started with `stellar container start` @@ -1277,7 +1280,7 @@ Get logs from a running network container Start a container running a Stellar node, RPC, API, and friendbot (faucet). -`stellar network container start NETWORK [OPTIONS]` +`stellar container start NETWORK [OPTIONS]` By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: @@ -1307,7 +1310,7 @@ By default, when starting a testnet container, without any optional arguments, i ## `stellar network container stop` -Stop a network container started with `network container start` +Stop a network container started with `stellar container start` **Usage:** `stellar network container stop [OPTIONS] ` @@ -1321,6 +1324,84 @@ Stop a network container started with `network container start` +## `stellar container` + +Start local networks in containers + +**Usage:** `stellar container ` + +###### **Subcommands:** + +* `logs` — Get logs from a running network container +* `start` — Start a container running a Stellar node, RPC, API, and friendbot (faucet) +* `stop` — Stop a network container started with `stellar container start` + + + +## `stellar container logs` + +Get logs from a running network container + +**Usage:** `stellar container logs [OPTIONS] ` + +###### **Arguments:** + +* `` — Container to get logs from + +###### **Options:** + +* `-d`, `--docker-host ` — Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock + + + +## `stellar container start` + +Start a container running a Stellar node, RPC, API, and friendbot (faucet). + +`stellar container start NETWORK [OPTIONS]` + +By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: + +`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` + +**Usage:** `stellar container start [OPTIONS] ` + +###### **Arguments:** + +* `` — Network to start + + Possible values: `local`, `testnet`, `futurenet`, `pubnet` + + +###### **Options:** + +* `-d`, `--docker-host ` — Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock +* `--name ` — Optional argument to specify the container name +* `-l`, `--limits ` — Optional argument to specify the limits for the local network only +* `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping + + Default value: `8000:8000` +* `-t`, `--image-tag-override ` — Optional argument to override the default docker image tag for the given network +* `--protocol-version ` — Optional argument to specify the protocol version for the local network only + + + +## `stellar container stop` + +Stop a network container started with `stellar container start` + +**Usage:** `stellar container stop [OPTIONS] ` + +###### **Arguments:** + +* `` — Container to stop + +###### **Options:** + +* `-d`, `--docker-host ` — Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock + + + ## `stellar snapshot` Download a snapshot of a ledger from an archive diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/container/logs.rs similarity index 94% rename from cmd/soroban-cli/src/commands/network/container/logs.rs rename to cmd/soroban-cli/src/commands/container/logs.rs index aaccffdde..85824b06c 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/container/logs.rs @@ -1,7 +1,7 @@ use futures_util::TryStreamExt; use crate::{ - commands::{global, network::container::shared::Error as ConnectionError}, + commands::{container::shared::Error as ConnectionError, global}, print, }; diff --git a/cmd/soroban-cli/src/commands/network/container.rs b/cmd/soroban-cli/src/commands/container/mod.rs similarity index 91% rename from cmd/soroban-cli/src/commands/network/container.rs rename to cmd/soroban-cli/src/commands/container/mod.rs index d14dc72e4..08203095d 100644 --- a/cmd/soroban-cli/src/commands/network/container.rs +++ b/cmd/soroban-cli/src/commands/container/mod.rs @@ -16,13 +16,13 @@ pub enum Cmd { Logs(logs::Cmd), /// Start a container running a Stellar node, RPC, API, and friendbot (faucet). /// - /// `stellar network container start NETWORK [OPTIONS]` + /// `stellar container start NETWORK [OPTIONS]` /// /// By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: /// /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` Start(start::Cmd), - /// Stop a network container started with `network container start`. + /// Stop a network container started with `stellar container start`. Stop(stop::Cmd), } diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/container/shared.rs similarity index 100% rename from cmd/soroban-cli/src/commands/network/container/shared.rs rename to cmd/soroban-cli/src/commands/container/shared.rs diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/container/start.rs similarity index 99% rename from cmd/soroban-cli/src/commands/network/container/start.rs rename to cmd/soroban-cli/src/commands/container/start.rs index 2f16d3c1e..6c5a5c291 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/container/start.rs @@ -9,8 +9,8 @@ use futures_util::TryStreamExt; use crate::{ commands::{ + container::shared::{Error as ConnectionError, Network}, global, - network::container::shared::{Error as ConnectionError, Network}, }, print, }; diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/container/stop.rs similarity index 95% rename from cmd/soroban-cli/src/commands/network/container/stop.rs rename to cmd/soroban-cli/src/commands/container/stop.rs index 77f674c46..6211c629f 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/container/stop.rs @@ -1,5 +1,5 @@ use crate::{ - commands::{global, network::container::shared::Error as BollardConnectionError}, + commands::{container::shared::Error as BollardConnectionError, global}, print, }; diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index f1febae27..f4344fb9d 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -7,6 +7,7 @@ use crate::config; pub mod cache; pub mod completion; +pub mod container; pub mod contract; pub mod env; pub mod events; @@ -113,6 +114,7 @@ impl Root { Cmd::Events(events) => events.run().await?, Cmd::Xdr(xdr) => xdr.run()?, Cmd::Network(network) => network.run(&self.global_args).await?, + Cmd::Container(container) => container.run(&self.global_args).await?, Cmd::Snapshot(snapshot) => snapshot.run(&self.global_args).await?, Cmd::Version(version) => version.run(), Cmd::Keys(id) => id.run(&self.global_args).await?, @@ -150,10 +152,14 @@ pub enum Cmd { #[command(subcommand)] Keys(keys::Cmd), - /// Start and configure networks + /// Configure connection to networks #[command(subcommand)] Network(network::Cmd), + /// Start local networks in containers + #[command(subcommand)] + Container(container::Cmd), + /// Download a snapshot of a ledger from an archive. #[command(subcommand)] Snapshot(snapshot::Cmd), @@ -201,6 +207,9 @@ pub enum Error { #[error(transparent)] Network(#[from] network::Error), + #[error(transparent)] + Container(#[from] container::Error), + #[error(transparent)] Snapshot(#[from] snapshot::Error), diff --git a/cmd/soroban-cli/src/commands/network/mod.rs b/cmd/soroban-cli/src/commands/network/mod.rs index a7519bc83..5cc2acc43 100644 --- a/cmd/soroban-cli/src/commands/network/mod.rs +++ b/cmd/soroban-cli/src/commands/network/mod.rs @@ -5,7 +5,6 @@ use crate::rpc::{self}; use super::{config::locator, global}; pub mod add; -pub mod container; pub mod default; pub mod ls; pub mod rm; @@ -32,12 +31,12 @@ pub enum Cmd { /// By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: /// /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` - Start(container::StartCmd), + Start(crate::commands::container::StartCmd), /// ⚠️ Deprecated: use `stellar container stop` instead /// /// Stop a network started with `network start`. For example, if you ran `stellar network start local`, you can use `stellar network stop local` to stop it. - Stop(container::StopCmd), + Stop(crate::commands::container::StopCmd), /// Set the default network that will be used on all commands. /// This allows you to skip `--network` or setting a environment variable, @@ -45,9 +44,11 @@ pub enum Cmd { #[command(name = "use")] Default(default::Cmd), + /// ⚠️ Deprecated: use `stellar container` instead + /// /// Commands to start, stop and get logs for a quickstart container #[command(subcommand)] - Container(container::Cmd), + Container(crate::commands::container::Cmd), } #[derive(thiserror::Error, Debug)] @@ -66,14 +67,14 @@ pub enum Error { // TODO: remove once `network start` is removed #[error(transparent)] - Start(#[from] container::start::Error), + Start(#[from] crate::commands::container::start::Error), // TODO: remove once `network stop` is removed #[error(transparent)] - Stop(#[from] container::stop::Error), + Stop(#[from] crate::commands::container::stop::Error), #[error(transparent)] - Container(#[from] container::Error), + Container(#[from] crate::commands::container::Error), #[error(transparent)] Config(#[from] locator::Error), @@ -103,12 +104,14 @@ impl Cmd { // TODO Remove this once `network start` is removed Cmd::Start(cmd) => { - eprintln!("⚠️ Warning: `network start` has been deprecated. Use `network container start` instead"); + eprintln!("⚠️ Warning: `network start` has been deprecated. Use `container start` instead"); cmd.run(global_args).await?; } // TODO Remove this once `network stop` is removed Cmd::Stop(cmd) => { - println!("⚠️ Warning: `network stop` has been deprecated. Use `network container stop` instead"); + println!( + "⚠️ Warning: `network stop` has been deprecated. Use `container stop` instead" + ); cmd.run(global_args).await?; } }; From 5fac1383ca3d51d0b9f113f233d9f7c07894bffa Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Thu, 7 Nov 2024 15:07:54 -0800 Subject: [PATCH 25/77] Revert "Resolve identity from default config. (#1711)" (#1715) This reverts commit 9912694cfb6f67c4ccfbcba62a27aa22aa43cc17. --- FULL_HELP_DOCS.md | 64 +++++++-------------------- cmd/soroban-cli/src/config/address.rs | 14 ++---- cmd/soroban-cli/src/config/mod.rs | 7 +-- 3 files changed, 20 insertions(+), 65 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 581c2cb87..899c0115e 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -131,7 +131,7 @@ Get Id of builtin Soroban Asset Contract. Deprecated, use `stellar contract id a Deploy builtin Soroban Asset Contract -**Usage:** `stellar contract asset deploy [OPTIONS] --asset ` +**Usage:** `stellar contract asset deploy [OPTIONS] --asset --source-account ` ###### **Options:** @@ -141,8 +141,6 @@ Deploy builtin Soroban Asset Contract * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -348,7 +346,7 @@ Extend the time to live ledger of a contract-data ledger entry. If no keys are specified the contract itself is extended. -**Usage:** `stellar contract extend [OPTIONS] --ledgers-to-extend ` +**Usage:** `stellar contract extend [OPTIONS] --ledgers-to-extend --source-account ` ###### **Options:** @@ -374,8 +372,6 @@ If no keys are specified the contract itself is extended. * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -393,7 +389,7 @@ If no keys are specified the contract itself is extended. Deploy a wasm contract -**Usage:** `stellar contract deploy [OPTIONS] <--wasm |--wasm-hash > [-- ...]` +**Usage:** `stellar contract deploy [OPTIONS] --source-account <--wasm |--wasm-hash > [-- ...]` ###### **Arguments:** @@ -409,8 +405,6 @@ Deploy a wasm contract * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -482,7 +476,7 @@ Deploy builtin Soroban Asset Contract Deploy normal Wasm Contract -**Usage:** `stellar contract id wasm [OPTIONS] --salt ` +**Usage:** `stellar contract id wasm [OPTIONS] --salt --source-account ` ###### **Options:** @@ -492,8 +486,6 @@ Deploy normal Wasm Contract * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -685,7 +677,7 @@ This command will create a Cargo workspace project and add a sample Stellar cont Install a WASM file to the ledger without creating a contract instance -**Usage:** `stellar contract install [OPTIONS] --wasm ` +**Usage:** `stellar contract install [OPTIONS] --source-account --wasm ` ###### **Options:** @@ -694,8 +686,6 @@ Install a WASM file to the ledger without creating a contract instance * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -721,7 +711,7 @@ Generates an "implicit CLI" for the specified contract on-the-fly using the cont stellar contract invoke ... -- --help -**Usage:** `stellar contract invoke [OPTIONS] --id [-- ...]` +**Usage:** `stellar contract invoke [OPTIONS] --id --source-account [-- ...]` ###### **Arguments:** @@ -736,8 +726,6 @@ stellar contract invoke ... -- --help * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -826,7 +814,7 @@ Restore an evicted value for a contract-data legder entry. If no keys are specificed the contract itself is restored. -**Usage:** `stellar contract restore [OPTIONS]` +**Usage:** `stellar contract restore [OPTIONS] --source-account ` ###### **Options:** @@ -852,8 +840,6 @@ If no keys are specificed the contract itself is restored. * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1472,7 +1458,7 @@ Sign, Simulate, and Send transactions Simulate a transaction envelope from stdin -**Usage:** `stellar tx simulate [OPTIONS]` +**Usage:** `stellar tx simulate [OPTIONS] --source-account ` ###### **Options:** @@ -1481,8 +1467,6 @@ Simulate a transaction envelope from stdin * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1564,7 +1548,7 @@ Create a new transaction Transfers the XLM balance of an account to another account and removes the source account from the ledger -**Usage:** `stellar tx new account-merge [OPTIONS] --account ` +**Usage:** `stellar tx new account-merge [OPTIONS] --source-account --account ` ###### **Options:** @@ -1580,8 +1564,6 @@ Transfers the XLM balance of an account to another account and removes the sourc * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1593,7 +1575,7 @@ Transfers the XLM balance of an account to another account and removes the sourc Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number -**Usage:** `stellar tx new bump-sequence [OPTIONS] --bump-to ` +**Usage:** `stellar tx new bump-sequence [OPTIONS] --source-account --bump-to ` ###### **Options:** @@ -1609,8 +1591,6 @@ Bumps forward the sequence number of the source account to the given sequence nu * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1622,7 +1602,7 @@ Bumps forward the sequence number of the source account to the given sequence nu Creates, updates, or deletes a trustline Learn more about trustlines https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines -**Usage:** `stellar tx new change-trust [OPTIONS] --line ` +**Usage:** `stellar tx new change-trust [OPTIONS] --source-account --line ` ###### **Options:** @@ -1638,8 +1618,6 @@ Creates, updates, or deletes a trustline Learn more about trustlines https://dev * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1654,7 +1632,7 @@ Creates, updates, or deletes a trustline Learn more about trustlines https://dev Creates and funds a new account with the specified starting balance -**Usage:** `stellar tx new create-account [OPTIONS] --destination ` +**Usage:** `stellar tx new create-account [OPTIONS] --source-account --destination ` ###### **Options:** @@ -1670,8 +1648,6 @@ Creates and funds a new account with the specified starting balance * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1686,7 +1662,7 @@ Creates and funds a new account with the specified starting balance Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account Learn more about entries and subentries: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries -**Usage:** `stellar tx new manage-data [OPTIONS] --data-name ` +**Usage:** `stellar tx new manage-data [OPTIONS] --source-account --data-name ` ###### **Options:** @@ -1702,8 +1678,6 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1716,7 +1690,7 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an Sends an amount in a specific asset to a destination account -**Usage:** `stellar tx new payment [OPTIONS] --destination --amount ` +**Usage:** `stellar tx new payment [OPTIONS] --source-account --destination --amount ` ###### **Options:** @@ -1732,8 +1706,6 @@ Sends an amount in a specific asset to a destination account * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1749,7 +1721,7 @@ Sends an amount in a specific asset to a destination account Set option for an account such as flags, inflation destination, signers, home domain, and master key weight Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags Learn more about the home domain: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md Learn more about signers operations and key weight: https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig -**Usage:** `stellar tx new set-options [OPTIONS]` +**Usage:** `stellar tx new set-options [OPTIONS] --source-account ` ###### **Options:** @@ -1765,8 +1737,6 @@ Set option for an account such as flags, inflation destination, signers, home do * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1793,7 +1763,7 @@ Set option for an account such as flags, inflation destination, signers, home do Allows issuing account to configure authorization and trustline flags to an asset The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags -**Usage:** `stellar tx new set-trustline-flags [OPTIONS] --trustor --asset ` +**Usage:** `stellar tx new set-trustline-flags [OPTIONS] --source-account --trustor --asset ` ###### **Options:** @@ -1809,8 +1779,6 @@ Allows issuing account to configure authorization and trustline flags to an asse * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail - - Default value: `` * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 811548316..066bc8d91 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -2,7 +2,7 @@ use std::str::FromStr; use crate::xdr; -use super::{locator, secret, Config}; +use super::{locator, secret}; /// Address can be either a public key or eventually an alias of a address. #[derive(Clone, Debug)] @@ -31,16 +31,8 @@ impl FromStr for Address { type Err = Error; fn from_str(value: &str) -> Result { - let mut identity = value.to_string(); - - if value.is_empty() { - if let Ok(config) = Config::new() { - identity = config.defaults.identity.unwrap_or_default(); - } - } - - Ok(xdr::MuxedAccount::from_str(&identity).map_or_else( - |_| Address::AliasOrSecret(identity.to_string()), + Ok(xdr::MuxedAccount::from_str(value).map_or_else( + |_| Address::AliasOrSecret(value.to_string()), Address::MuxedAccount, )) } diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index 396b2b8cc..11eb179ee 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -47,12 +47,7 @@ pub struct Args { #[command(flatten)] pub network: network::Args, - #[arg( - long, - visible_alias = "source", - env = "STELLAR_ACCOUNT", - default_value = "" - )] + #[arg(long, visible_alias = "source", env = "STELLAR_ACCOUNT")] /// Account that where transaction originates from. Alias `source`. /// Can be an identity (--source alice), a public key (--source GDKW...), /// a muxed account (--source MDA…), a secret key (--source SC36…), From 61550ec2157e5550dfaa967fa20c2ca9e2de4df2 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Thu, 7 Nov 2024 15:41:20 -0800 Subject: [PATCH 26/77] Load default configuration into env vars. (#1716) --- cmd/soroban-cli/src/cli.rs | 27 +++++++++++++++++++++++++ cmd/soroban-cli/src/commands/env/mod.rs | 23 +++++++++------------ 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/cmd/soroban-cli/src/cli.rs b/cmd/soroban-cli/src/cli.rs index 9183d0e30..76c5c3194 100644 --- a/cmd/soroban-cli/src/cli.rs +++ b/cmd/soroban-cli/src/cli.rs @@ -2,6 +2,7 @@ use clap::CommandFactory; use dotenvy::dotenv; use tracing_subscriber::{fmt, EnvFilter}; +use crate::config::Config; use crate::print::Print; use crate::upgrade_check::upgrade_check; use crate::{commands, Root}; @@ -33,6 +34,8 @@ pub async fn main() { } } + set_env_from_config(); + let mut root = Root::new().unwrap_or_else(|e| match e { commands::Error::Clap(e) => { let mut cmd = Root::command(); @@ -86,3 +89,27 @@ pub async fn main() { std::process::exit(1); } } + +// Load ~/.config/stellar/config.toml defaults as env vars. +fn set_env_from_config() { + if let Ok(config) = Config::new() { + set_env_value_from_config("STELLAR_ACCOUNT", config.defaults.identity); + set_env_value_from_config("STELLAR_NETWORK", config.defaults.network); + } +} + +// Set an env var from a config file if the env var is not already set. +// Additionally, a `$NAME_SOURCE` variant will be set, which allows +// `stellar env` to properly identity the source. +fn set_env_value_from_config(name: &str, value: Option) { + let Some(value) = value else { + return; + }; + + std::env::remove_var(format!("{name}_SOURCE")); + + if std::env::var(name).is_err() { + std::env::set_var(name, value); + std::env::set_var(format!("{name}_SOURCE"), "use"); + } +} diff --git a/cmd/soroban-cli/src/commands/env/mod.rs b/cmd/soroban-cli/src/commands/env/mod.rs index 4d745400c..298cac3d2 100644 --- a/cmd/soroban-cli/src/commands/env/mod.rs +++ b/cmd/soroban-cli/src/commands/env/mod.rs @@ -1,9 +1,6 @@ use crate::{ commands::global, - config::{ - locator::{self}, - Config, - }, + config::locator::{self}, print::Print, }; use clap::Parser; @@ -23,14 +20,13 @@ pub enum Error { impl Cmd { pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { let print = Print::new(global_args.quiet); - let config = Config::new()?; let mut lines: Vec<(String, String)> = Vec::new(); - if let Some(data) = get("STELLAR_NETWORK", config.defaults.network) { + if let Some(data) = get("STELLAR_NETWORK") { lines.push(data); } - if let Some(data) = get("STELLAR_ACCOUNT", config.defaults.identity) { + if let Some(data) = get("STELLAR_ACCOUNT") { lines.push(data); } @@ -51,13 +47,14 @@ impl Cmd { } } -fn get(env_var: &str, default_value: Option) -> Option<(String, String)> { - if let Ok(value) = std::env::var(env_var) { - return Some((format!("{env_var}={value}"), "env".to_string())); - } +fn get(env_var: &str) -> Option<(String, String)> { + // The _SOURCE env var is set from cmd/soroban-cli/src/cli.rs#set_env_value_from_config + let source = std::env::var(format!("{env_var}_SOURCE")) + .ok() + .unwrap_or("env".to_string()); - if let Some(value) = default_value { - return Some((format!("{env_var}={value}"), "default".to_string())); + if let Ok(value) = std::env::var(env_var) { + return Some((format!("{env_var}={value}"), source)); } None From 715a2008090afdc6c538a1c373d89709981181d6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 8 Nov 2024 00:55:59 +0000 Subject: [PATCH 27/77] Bump version to 22.0.0-rc.1 (#1717) Co-authored-by: Nando Vieira --- Cargo.lock | 37 ++++++++++--------- Cargo.toml | 14 +++---- cmd/crates/soroban-test/Cargo.toml | 2 +- .../tests/fixtures/bye/Cargo.toml | 2 +- .../tests/fixtures/hello/Cargo.toml | 2 +- .../test-wasms/constructor/Cargo.toml | 2 +- .../test-wasms/custom_account/Cargo.toml | 2 +- .../test-wasms/custom_type/Cargo.toml | 2 +- .../test-wasms/hello_world/Cargo.toml | 2 +- cmd/soroban-cli/Cargo.toml | 2 +- cmd/stellar-cli/Cargo.toml | 2 +- 11 files changed, 34 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6bc90a065..4d3cc0c78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4432,7 +4432,7 @@ dependencies = [ [[package]] name = "soroban-cli" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "assert_cmd", "assert_fs", @@ -4676,7 +4676,7 @@ dependencies = [ [[package]] name = "soroban-hello" -version = "21.5.0" +version = "22.0.0-rc.1" [[package]] name = "soroban-ledger-snapshot" @@ -4813,7 +4813,7 @@ dependencies = [ [[package]] name = "soroban-spec-json" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "pretty_assertions", "serde", @@ -4859,7 +4859,7 @@ dependencies = [ [[package]] name = "soroban-spec-tools" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "base64 0.21.7", "ethnum", @@ -4877,7 +4877,7 @@ dependencies = [ [[package]] name = "soroban-spec-typescript" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "base64 0.21.7", "heck 0.4.1", @@ -4898,7 +4898,7 @@ dependencies = [ [[package]] name = "soroban-test" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "assert_cmd", "assert_fs", @@ -4969,18 +4969,18 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-bye" -version = "21.5.0" +version = "22.0.0-rc.1" [[package]] name = "stellar-cli" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "soroban-cli", ] [[package]] name = "stellar-ledger" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "async-trait", "bollard", @@ -5018,8 +5018,9 @@ dependencies = [ [[package]] name = "stellar-rpc-client" -version = "21.4.0" -source = "git+https://github.com/stellar/rs-stellar-rpc-client?rev=7554d4c87c026313a1f5b3c7ae66a92b5ff7e091#7554d4c87c026313a1f5b3c7ae66a92b5ff7e091" +version = "22.0.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaba3219c517ceba11f99e1f9adb1e801fe8416bc9ff35c6842b5fe8cac19290" dependencies = [ "clap", "hex", @@ -5354,42 +5355,42 @@ dependencies = [ [[package]] name = "test_constructor" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "soroban-sdk 22.0.0-rc.3", ] [[package]] name = "test_custom_account" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "soroban-sdk 21.7.2", ] [[package]] name = "test_custom_types" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "soroban-sdk 21.7.2", ] [[package]] name = "test_hello_world" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "soroban-sdk 21.7.2", ] [[package]] name = "test_swap" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "soroban-sdk 21.7.2", ] [[package]] name = "test_token" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "soroban-sdk 21.7.2", "soroban-token-sdk", @@ -5397,7 +5398,7 @@ dependencies = [ [[package]] name = "test_udt" -version = "21.5.0" +version = "22.0.0-rc.1" dependencies = [ "soroban-sdk 21.7.2", ] diff --git a/Cargo.toml b/Cargo.toml index d5f87b38e..31e92e40b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,24 +19,24 @@ exclude = [ ] [workspace.package] -version = "21.5.0" +version = "22.0.0-rc.1" rust-version = "1.81.0" # Dependencies located in this repo: [workspace.dependencies.soroban-cli] -version = "=21.5.0" +version = "=22.0.0-rc.1" path = "cmd/soroban-cli" [workspace.dependencies.soroban-spec-json] -version = "=21.5.0" +version = "=22.0.0-rc.1" path = "./cmd/crates/soroban-spec-json" [workspace.dependencies.soroban-spec-typescript] -version = "21.5.0" +version = "22.0.0-rc.1" path = "./cmd/crates/soroban-spec-typescript" [workspace.dependencies.soroban-spec-tools] -version = "21.5.0" +version = "22.0.0-rc.1" path = "./cmd/crates/soroban-spec-tools" # Dependencies from the rs-stellar-xdr repo: @@ -63,9 +63,7 @@ version = "=22.0.0-rc.3" # Dependencies from the rs-stellar-rpc-client repo: [workspace.dependencies.soroban-rpc] package = "stellar-rpc-client" -version = "21.4.0" -git = "https://github.com/stellar/rs-stellar-rpc-client" -rev = "7554d4c87c026313a1f5b3c7ae66a92b5ff7e091" +version = "=22.0.0-rc.1" # Dependencies from elsewhere shared by crates: [workspace.dependencies] diff --git a/cmd/crates/soroban-test/Cargo.toml b/cmd/crates/soroban-test/Cargo.toml index b240494e4..d9eb31bdd 100644 --- a/cmd/crates/soroban-test/Cargo.toml +++ b/cmd/crates/soroban-test/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/soroban-test" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "21.5.0" +version = "22.0.0-rc.1" edition = "2021" rust-version.workspace = true autobins = false diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml index 7678eee5e..acee77f4b 100644 --- a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stellar-bye" -version = "21.5.0" +version = "22.0.0-rc.1" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml index 0c3b1512f..2a212a532 100644 --- a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "soroban-hello" -version = "21.5.0" +version = "22.0.0-rc.1" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml index ef1dd882c..8c38fecb4 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_constructor" -version = "21.5.0" +version = "22.0.0-rc.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml index 792925edb..9be386b69 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_account" -version = "21.5.0" +version = "22.0.0-rc.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index 398520104..7c4ca5828 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_types" -version = "21.5.0" +version = "22.0.0-rc.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index 5f8b1256f..19b7353ca 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_hello_world" -version = "21.5.0" +version = "22.0.0-rc.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index efef18e0f..d2a53e6f2 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/stellar-cli" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "21.5.0" +version = "22.0.0-rc.1" edition = "2021" rust-version.workspace = true autobins = false diff --git a/cmd/stellar-cli/Cargo.toml b/cmd/stellar-cli/Cargo.toml index 2a388b4de..21e7e307b 100644 --- a/cmd/stellar-cli/Cargo.toml +++ b/cmd/stellar-cli/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/stellar-cli" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "21.5.0" +version = "22.0.0-rc.1" edition = "2021" rust-version.workspace = true autobins = false From f1f95831b13baaecbe6127aa7e28a2d017ccec5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?jeesun=20=EC=A7=80=EC=84=A0?= Date: Sun, 10 Nov 2024 16:48:20 -0800 Subject: [PATCH 28/77] update cli doc url (#1719) --- FULL_HELP_DOCS.md | 2 +- cmd/soroban-cli/src/commands/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 899c0115e..c7cd9c56c 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -18,7 +18,7 @@ For additional information see: - Stellar Docs: https://developers.stellar.org - Smart Contract Docs: https://developers.stellar.org/docs/build/smart-contracts/overview -- CLI Docs: https://developers.stellar.org/docs/tools/stellar-cli +- CLI Docs: https://developers.stellar.org/docs/tools/developer-tools/cli/stellar-cli To get started generate a new identity: diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index f4344fb9d..25d61364d 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -38,7 +38,7 @@ For additional information see: - Stellar Docs: https://developers.stellar.org - Smart Contract Docs: https://developers.stellar.org/docs/build/smart-contracts/overview -- CLI Docs: https://developers.stellar.org/docs/tools/stellar-cli"; +- CLI Docs: https://developers.stellar.org/docs/tools/developer-tools/cli/stellar-cli"; // long_about is shown when someone uses `--help`; short help when using `-h` const LONG_ABOUT: &str = " From ec8e93f7885c17e17b2d5bfe827d0927cded80e9 Mon Sep 17 00:00:00 2001 From: Paul <134265547+pamellix@users.noreply.github.com> Date: Tue, 12 Nov 2024 01:31:16 +0300 Subject: [PATCH 29/77] docs: Add syntax highlights (#1712) * Add syntax highlights * tweak * undo --------- Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 381f5a3dd..f8ba1f052 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,9 @@ cargo install --locked stellar-cli --features opt Install or run the unreleased main branch with nix: ``` -% nix run 'github:stellar/stellar-cli' -- --help +$ nix run 'github:stellar/stellar-cli' -- --help or install -% nix profile install github:stellar/stellar-cli +$ nix profile install github:stellar/stellar-cli ``` ## Autocomplete @@ -53,12 +53,12 @@ stellar completion --shell Possible SHELL values are `bash`, `elvish`, `fish`, `powershell`, `zsh`, etc. To enable autocomplete in the current bash shell, run: -``` +```bash source <(stellar completion --shell bash) ``` To enable autocomplete permanently, run: -``` +```bash echo "source <(stellar completion --shell bash)" >> ~/.bashrc ``` From 9e15e9519a345edcc034d541c7b30694b078bcf4 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Tue, 12 Nov 2024 13:08:46 -0800 Subject: [PATCH 30/77] Add license. (#1723) --- LICENSE | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..a084d8624 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2024 Stellar Development Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 02c9c8e5422f7f83795eb75dfadfa3f2c1b8f640 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:32:55 -0500 Subject: [PATCH 31/77] Fix/invoke view only (#1697) * Use a default account if the tx is only being simulated * Add a comment to get_matches_from for --help * Update invoke_view_with_non_existent_source_account test --- .../tests/it/integration/hello_world.rs | 4 +- .../src/commands/contract/arg_parsing.rs | 3 + .../src/commands/contract/invoke.rs | 62 ++++++++++++++----- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index 272587c53..12963b1f4 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -20,9 +20,7 @@ async fn invoke_view_with_non_existent_source_account() { let id = deploy_hello(sandbox).await; let world = "world"; let mut cmd = hello_world_cmd(&id, world); - cmd.config.source_account = Address::default(); - cmd.is_view = true; - let res = sandbox.run_cmd_with(cmd, "test").await.unwrap(); + let res = sandbox.run_cmd_with(cmd, "").await.unwrap(); assert_eq!(res, TxnResult::Res(format!(r#"["Hello",{world:?}]"#))); } diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index 2eb3c2696..21fa2f383 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -62,6 +62,9 @@ pub fn build_host_function_parameters( } cmd.build(); let long_help = cmd.render_long_help(); + + // get_matches_from exits the process if `help`, `--help` or `-h`are passed in the slop + // see clap documentation for more info: https://github.com/clap-rs/clap/blob/v4.1.8/src/builder/command.rs#L631 let mut matches_ = cmd.get_matches_from(slop); let Some((function, matches_)) = &matches_.remove_subcommand() else { println!("{long_help}"); diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index 5d43f9bfa..47e2699fc 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -7,7 +7,7 @@ use std::{fmt::Debug, fs, io}; use clap::{arg, command, Parser, ValueEnum}; -use soroban_rpc::{SimulateHostFunctionResult, SimulateTransactionResponse}; +use soroban_rpc::{Client, SimulateHostFunctionResult, SimulateTransactionResponse}; use soroban_spec::read::FromWasmError; use super::super::events; @@ -163,7 +163,7 @@ impl Cmd { .transpose() } - fn send(&self, sim_res: &SimulateTransactionResponse) -> Result { + fn should_send_tx(&self, sim_res: &SimulateTransactionResponse) -> Result { Ok(match self.send { Send::Default => { if self.is_view { @@ -179,6 +179,28 @@ impl Cmd { Send::Yes => ShouldSend::Yes, }) } + + // uses a default account to check if the tx should be sent after the simulation + async fn should_send_after_sim( + &self, + host_function_params: InvokeContractArgs, + rpc_client: Client, + ) -> Result { + let account_details = default_account_entry(); + let sequence: i64 = account_details.seq_num.into(); + let AccountId(PublicKey::PublicKeyTypeEd25519(account_id)) = account_details.account_id; + + let tx = build_invoke_contract_tx( + host_function_params.clone(), + sequence + 1, + self.fee.fee, + account_id, + )?; + let txn = simulate_and_assemble_transaction(&rpc_client, &tx).await?; + let txn = self.fee.apply_to_assembled_txn(txn); // do we need this part? + let sim_res = txn.sim_response(); + self.should_send_tx(sim_res) + } } #[async_trait::async_trait] @@ -205,19 +227,6 @@ impl NetworkRunnable for Cmd { let _ = build_host_function_parameters(&contract_id, &self.slop, spec_entries, config)?; } let client = network.rpc_client()?; - let account_details = if self.is_view { - default_account_entry() - } else { - client - .verify_network_passphrase(Some(&network.network_passphrase)) - .await?; - - client - .get_account(&config.source_account()?.to_string()) - .await? - }; - let sequence: i64 = account_details.seq_num.into(); - let AccountId(PublicKey::PublicKeyTypeEd25519(account_id)) = account_details.account_id; let spec_entries = get_remote_contract_spec( &contract_id.0, @@ -229,9 +238,27 @@ impl NetworkRunnable for Cmd { .await .map_err(Error::from)?; - // Get the ledger footprint let (function, spec, host_function_params, signers) = build_host_function_parameters(&contract_id, &self.slop, &spec_entries, config)?; + + let should_send_tx = self + .should_send_after_sim(host_function_params.clone(), client.clone()) + .await?; + + let account_details = if should_send_tx == ShouldSend::Yes { + client + .verify_network_passphrase(Some(&network.network_passphrase)) + .await?; + + client + .get_account(&config.source_account()?.to_string()) + .await? + } else { + default_account_entry() + }; + let sequence: i64 = account_details.seq_num.into(); + let AccountId(PublicKey::PublicKeyTypeEd25519(account_id)) = account_details.account_id; + let tx = build_invoke_contract_tx( host_function_params.clone(), sequence + 1, @@ -250,7 +277,7 @@ impl NetworkRunnable for Cmd { if global_args.map_or(true, |a| !a.no_cache) { data::write(sim_res.clone().into(), &network.rpc_uri()?)?; } - let should_send = self.send(sim_res)?; + let should_send = self.should_send_tx(sim_res)?; let (return_value, events) = match should_send { ShouldSend::Yes => { let global::Args { no_cache, .. } = global_args.cloned().unwrap_or_default(); @@ -365,6 +392,7 @@ pub enum Send { Yes, } +#[derive(Debug, PartialEq)] enum ShouldSend { DefaultNo, No, From bc49f4ca1a23a86ca92c7c483b57462682d8b987 Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Thu, 14 Nov 2024 16:24:15 -0500 Subject: [PATCH 32/77] feat(ts-bindings): update js stellar-sdk dep to 13.0.0 (#1724) --- .../test_custom_types/package-lock.json | 52 +++++++++++++----- .../fixtures/test_custom_types/package.json | 2 +- .../src/project_template/package.json | 2 +- .../ts-tests/package-lock.json | 55 +++++++++++++------ .../ts-tests/package.json | 2 +- 5 files changed, 79 insertions(+), 34 deletions(-) diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json index 454c8b964..a4e3759e2 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json @@ -8,7 +8,7 @@ "name": "test_custom_types", "version": "0.0.0", "dependencies": { - "@stellar/stellar-sdk": "12.3.0", + "@stellar/stellar-sdk": "13.0.0", "buffer": "6.0.3" }, "devDependencies": { @@ -22,9 +22,9 @@ "license": "Apache-2.0" }, "node_modules/@stellar/stellar-base": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-12.1.1.tgz", - "integrity": "sha512-gOBSOFDepihslcInlqnxKZdIW9dMUO1tpOm3AtJR33K2OvpXG6SaVHCzAmCFArcCqI9zXTEiSoh70T48TmiHJA==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-13.0.1.tgz", + "integrity": "sha512-Xbd12mc9Oj/130Tv0URmm3wXG77XMshZtZ2yNCjqX5ZbMD5IYpbBs3DVCteLU/4SLj/Fnmhh1dzhrQXnk4r+pQ==", "license": "Apache-2.0", "dependencies": { "@stellar/js-xdr": "^3.1.2", @@ -35,19 +35,20 @@ "tweetnacl": "^1.0.3" }, "optionalDependencies": { - "sodium-native": "^4.1.1" + "sodium-native": "^4.3.0" } }, "node_modules/@stellar/stellar-sdk": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-12.3.0.tgz", - "integrity": "sha512-F2DYFop/M5ffXF0lvV5Ezjk+VWNKg0QDX8gNhwehVU3y5LYA3WAY6VcCarMGPaG9Wdgoeh1IXXzOautpqpsltw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-13.0.0.tgz", + "integrity": "sha512-+wvmKi+XWwu27nLYTM17EgBdpbKohEkOfCIK4XKfsI4WpMXAqvnqSm98i9h5dAblNB+w8BJqzGs1JY0PtTGm4A==", "license": "Apache-2.0", "dependencies": { - "@stellar/stellar-base": "^12.1.1", + "@stellar/stellar-base": "^13.0.1", "axios": "^1.7.7", "bignumber.js": "^9.1.2", "eventsource": "^2.0.2", + "feaxios": "^0.0.20", "randombytes": "^2.1.0", "toml": "^3.0.0", "urijs": "^1.19.1" @@ -156,6 +157,15 @@ "node": ">=12.0.0" } }, + "node_modules/feaxios": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/feaxios/-/feaxios-0.0.20.tgz", + "integrity": "sha512-g3hm2YDNffNxA3Re3Hd8ahbpmDee9Fv1Pb1C/NoWsjY7mtD8nyNeJytUzn+DK0Hyl9o6HppeWOrtnqgmhOYfWA==", + "license": "MIT", + "dependencies": { + "is-retry-allowed": "^3.0.0" + } + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -214,6 +224,18 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, + "node_modules/is-retry-allowed": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-3.0.0.tgz", + "integrity": "sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -236,9 +258,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", - "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.3.tgz", + "integrity": "sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw==", "license": "MIT", "optional": true, "bin": { @@ -292,9 +314,9 @@ } }, "node_modules/sodium-native": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.0.tgz", - "integrity": "sha512-OcMgoS0NJx+4yVUlhvL9uZsVZfmyHZ2RpSXkiIoOHMglqvJDeGwn1rUigPrvcNTq3m9hPXtt6syxQbF3vvwmRQ==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.1.tgz", + "integrity": "sha512-YdP64gAdpIKHfL4ttuX4aIfjeunh9f+hNeQJpE9C8UMndB3zkgZ7YmmGT4J2+v6Ibyp6Wem8D1TcSrtdW0bqtg==", "license": "MIT", "optional": true, "dependencies": { diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json index a52979626..8c3762b91 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package.json @@ -8,7 +8,7 @@ "build": "tsc" }, "dependencies": { - "@stellar/stellar-sdk": "12.3.0", + "@stellar/stellar-sdk": "13.0.0", "buffer": "6.0.3" }, "devDependencies": { diff --git a/cmd/crates/soroban-spec-typescript/src/project_template/package.json b/cmd/crates/soroban-spec-typescript/src/project_template/package.json index 1d7d48793..b5c6459e4 100644 --- a/cmd/crates/soroban-spec-typescript/src/project_template/package.json +++ b/cmd/crates/soroban-spec-typescript/src/project_template/package.json @@ -8,7 +8,7 @@ "build": "tsc" }, "dependencies": { - "@stellar/stellar-sdk": "12.3.0", + "@stellar/stellar-sdk": "13.0.0", "buffer": "6.0.3" }, "devDependencies": { diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json index dec6997a7..45cc97a67 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json @@ -7,7 +7,7 @@ "hasInstallScript": true, "devDependencies": { "@ava/typescript": "^4.1.0", - "@stellar/stellar-sdk": "12.3.0", + "@stellar/stellar-sdk": "13.0.0", "@types/node": "^20.4.9", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", @@ -206,9 +206,9 @@ "license": "Apache-2.0" }, "node_modules/@stellar/stellar-base": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-12.1.1.tgz", - "integrity": "sha512-gOBSOFDepihslcInlqnxKZdIW9dMUO1tpOm3AtJR33K2OvpXG6SaVHCzAmCFArcCqI9zXTEiSoh70T48TmiHJA==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-13.0.1.tgz", + "integrity": "sha512-Xbd12mc9Oj/130Tv0URmm3wXG77XMshZtZ2yNCjqX5ZbMD5IYpbBs3DVCteLU/4SLj/Fnmhh1dzhrQXnk4r+pQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -220,20 +220,21 @@ "tweetnacl": "^1.0.3" }, "optionalDependencies": { - "sodium-native": "^4.1.1" + "sodium-native": "^4.3.0" } }, "node_modules/@stellar/stellar-sdk": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-12.3.0.tgz", - "integrity": "sha512-F2DYFop/M5ffXF0lvV5Ezjk+VWNKg0QDX8gNhwehVU3y5LYA3WAY6VcCarMGPaG9Wdgoeh1IXXzOautpqpsltw==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-13.0.0.tgz", + "integrity": "sha512-+wvmKi+XWwu27nLYTM17EgBdpbKohEkOfCIK4XKfsI4WpMXAqvnqSm98i9h5dAblNB+w8BJqzGs1JY0PtTGm4A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@stellar/stellar-base": "^12.1.1", + "@stellar/stellar-base": "^13.0.1", "axios": "^1.7.7", "bignumber.js": "^9.1.2", "eventsource": "^2.0.2", + "feaxios": "^0.0.20", "randombytes": "^2.1.0", "toml": "^3.0.0", "urijs": "^1.19.1" @@ -1590,6 +1591,16 @@ "reusify": "^1.0.4" } }, + "node_modules/feaxios": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/feaxios/-/feaxios-0.0.20.tgz", + "integrity": "sha512-g3hm2YDNffNxA3Re3Hd8ahbpmDee9Fv1Pb1C/NoWsjY7mtD8nyNeJytUzn+DK0Hyl9o6HppeWOrtnqgmhOYfWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-retry-allowed": "^3.0.0" + } + }, "node_modules/figures": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", @@ -2040,6 +2051,19 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "dev": true }, + "node_modules/is-retry-allowed": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-3.0.0.tgz", + "integrity": "sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -2316,9 +2340,9 @@ "dev": true }, "node_modules/node-gyp-build": { - "version": "4.8.2", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz", - "integrity": "sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw==", + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.3.tgz", + "integrity": "sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw==", "dev": true, "license": "MIT", "optional": true, @@ -2983,11 +3007,10 @@ } }, "node_modules/sodium-native": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.2.0.tgz", - "integrity": "sha512-rdJRAf/RE/IRFUUoUsz10slNAQDTGz5ChpIeR1Ti0BtGYstl6Uok4hHALPBdnFcLml6qXJ2pDd0/De09mPa6mg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.1.tgz", + "integrity": "sha512-YdP64gAdpIKHfL4ttuX4aIfjeunh9f+hNeQJpE9C8UMndB3zkgZ7YmmGT4J2+v6Ibyp6Wem8D1TcSrtdW0bqtg==", "dev": true, - "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/package.json b/cmd/crates/soroban-spec-typescript/ts-tests/package.json index 69a17eb5c..a8bb3c1ff 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/package.json +++ b/cmd/crates/soroban-spec-typescript/ts-tests/package.json @@ -8,7 +8,7 @@ }, "devDependencies": { "@ava/typescript": "^4.1.0", - "@stellar/stellar-sdk": "12.3.0", + "@stellar/stellar-sdk": "13.0.0", "@types/node": "^20.4.9", "@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/parser": "^6.10.0", From b37da02841fa4c31c71ed4064bae1c312599d8b4 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 14 Nov 2024 19:31:16 -0500 Subject: [PATCH 33/77] fix: Add ContractAddress type to consolidate contract id parsing with aliases (#1692) * fix: resolve contract id * refactor: Refactor contract ID handling in Args module. --- Cargo.lock | 38 ++++++++-------- FULL_HELP_DOCS.md | 8 ++-- .../tests/it/integration/hello_world.rs | 2 +- .../src/commands/contract/alias/add.rs | 8 ++-- .../src/commands/contract/fetch.rs | 10 ++++- .../src/commands/contract/info/shared.rs | 14 +++--- .../src/commands/contract/invoke.rs | 7 ++- cmd/soroban-cli/src/commands/events.rs | 7 ++- cmd/soroban-cli/src/config/alias.rs | 43 ++++++++++++++++++- cmd/soroban-cli/src/config/locator.rs | 25 ++++++----- cmd/soroban-cli/src/config/mod.rs | 2 + cmd/soroban-cli/src/key.rs | 11 +++-- cmd/soroban-cli/src/wasm.rs | 8 +--- 13 files changed, 118 insertions(+), 65 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d3cc0c78..82b62d2e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1701,9 +1701,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1711,9 +1711,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" @@ -1728,9 +1728,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -1762,9 +1762,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", @@ -1773,21 +1773,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -3013,11 +3013,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.68" +version = "0.10.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" dependencies = [ - "bitflags 2.6.0", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -3045,9 +3045,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.104" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index c7cd9c56c..6bf321246 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -198,7 +198,7 @@ Add contract alias ###### **Arguments:** -* `` — The contract alias that will be removed +* `` — The contract alias that will be used ###### **Options:** @@ -522,7 +522,7 @@ Outputs no data when no data is present in the contract. * `--wasm ` — Wasm file to extract the data from * `--wasm-hash ` — Wasm hash to get the data for -* `--id ` — Contract id to get the data for +* `--id ` — Contract id or contract alias to get the data for * `--rpc-url ` — RPC server endpoint * `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server @@ -562,7 +562,7 @@ Outputs no data when no data is present in the contract. * `--wasm ` — Wasm file to extract the data from * `--wasm-hash ` — Wasm hash to get the data for -* `--id ` — Contract id to get the data for +* `--id ` — Contract id or contract alias to get the data for * `--rpc-url ` — RPC server endpoint * `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server @@ -602,7 +602,7 @@ Outputs no data when no data is present in the contract. * `--wasm ` — Wasm file to extract the data from * `--wasm-hash ` — Wasm hash to get the data for -* `--id ` — Contract id to get the data for +* `--id ` — Contract id or contract alias to get the data for * `--rpc-url ` — RPC server endpoint * `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index 12963b1f4..a6bd00c91 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -159,7 +159,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() } diff --git a/cmd/soroban-cli/src/commands/contract/alias/add.rs b/cmd/soroban-cli/src/commands/contract/alias/add.rs index 5a7a17ddb..923ead5e9 100644 --- a/cmd/soroban-cli/src/commands/contract/alias/add.rs +++ b/cmd/soroban-cli/src/commands/contract/alias/add.rs @@ -13,9 +13,9 @@ pub struct Cmd { pub config_locator: locator::Args, #[command(flatten)] - network: network::Args, + pub 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. @@ -41,7 +41,7 @@ pub enum Error { AlreadyExist { alias: String, network_passphrase: String, - contract: String, + contract: stellar_strkey::Contract, }, } @@ -57,7 +57,7 @@ impl Cmd { .get_contract_id(&self.alias, network_passphrase)?; if let Some(contract) = contract { - if contract != self.contract_id.to_string() && !self.overwrite { + if contract != self.contract_id && !self.overwrite { return Err(Error::AlreadyExist { alias: alias.to_string(), network_passphrase: network_passphrase.to_string(), diff --git a/cmd/soroban-cli/src/commands/contract/fetch.rs b/cmd/soroban-cli/src/commands/contract/fetch.rs index 2714b1f07..31ed191ff 100644 --- a/cmd/soroban-cli/src/commands/contract/fetch.rs +++ b/cmd/soroban-cli/src/commands/contract/fetch.rs @@ -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, @@ -111,6 +111,12 @@ impl NetworkRunnable for Cmd { config: Option<&config::Args>, ) -> Result, 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?) } } diff --git a/cmd/soroban-cli/src/commands/contract/info/shared.rs b/cmd/soroban-cli/src/commands/contract/info/shared.rs index b34ec7da8..33a95b607 100644 --- a/cmd/soroban-cli/src/commands/contract/info/shared.rs +++ b/cmd/soroban-cli/src/commands/contract/info/shared.rs @@ -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)] @@ -24,9 +24,9 @@ pub struct Args { /// Wasm hash to get the data for #[arg(long = "wasm-hash", group = "Source")] pub wasm_hash: Option, - /// Contract id to get the data for + /// Contract id or contract alias to get the data for #[arg(long = "id", env = "STELLAR_CONTRACT_ID", group = "Source")] - pub contract_id: Option, + pub contract_id: Option, #[command(flatten)] pub network: network::Args, #[command(flatten)] @@ -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>, Error> { @@ -84,7 +86,9 @@ pub async fn fetch_wasm(args: &Args) -> Result>, Error> { get_remote_wasm_from_hash(&client, &hash).await? } else if let Some(contract_id) = &args.contract_id { - 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); } diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index 47e2699fc..04eeaebd6 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -40,7 +40,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, @@ -217,9 +217,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 { diff --git a/cmd/soroban-cli/src/commands/events.rs b/cmd/soroban-cli/src/commands/events.rs index a1f5de921..48d79c1b7 100644 --- a/cmd/soroban-cli/src/commands/events.rs +++ b/cmd/soroban-cli/src/commands/events.rs @@ -42,7 +42,7 @@ pub struct Cmd { num_args = 1..=6, help_heading = "FILTERS" )] - contract_ids: Vec, + contract_ids: Vec, /// 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. @@ -218,9 +218,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::, Error>>()?; diff --git a/cmd/soroban-cli/src/config/alias.rs b/cmd/soroban-cli/src/config/alias.rs index 68ad556d6..9d1d8c11b 100644 --- a/cmd/soroban-cli/src/config/alias.rs +++ b/cmd/soroban-cli/src/config/alias.rs @@ -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, } + +/// 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 { + 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 { + 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())), + } + } +} diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 60b7856a6..8f51975a1 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -76,6 +76,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}")] @@ -332,12 +334,17 @@ impl Args { &self, alias: &str, network_passphrase: &str, - ) -> Result, Error> { + ) -> Result, 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( @@ -345,14 +352,12 @@ impl Args { alias_or_contract_id: &str, network_passphrase: &str, ) -> Result { - 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) } } diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index 11eb179ee..6cd9b4d71 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -23,6 +23,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)] diff --git a/cmd/soroban-cli/src/key.rs b/cmd/soroban-cli/src/key.rs index 3f4dcaf7c..b704541c4 100644 --- a/cmd/soroban-cli/src/key.rs +++ b/cmd/soroban-cli/src/key.rs @@ -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; @@ -34,7 +34,7 @@ pub struct Args { required_unless_present = "wasm", required_unless_present = "wasm_hash" )] - pub contract_id: Option, + pub contract_id: Option, /// Storage key (symbols only) #[arg(long = "key", conflicts_with = "key_xdr")] pub key: Option>, @@ -97,8 +97,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() diff --git a/cmd/soroban-cli/src/wasm.rs b/cmd/soroban-cli/src/wasm.rs index 5f0ed3b5c..a907e021a 100644 --- a/cmd/soroban-cli/src/wasm.rs +++ b/cmd/soroban-cli/src/wasm.rs @@ -121,16 +121,10 @@ pub fn len(p: &Path) -> Result { } pub async fn fetch_from_contract( - contract_id: &str, + stellar_strkey::Contract(contract_id): &stellar_strkey::Contract, network: &Network, - locator: &locator::Args, ) -> Result, 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)) From 355905df40285855f144cf66f95ff092abe45903 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 15 Nov 2024 14:46:40 -0800 Subject: [PATCH 34/77] Generate windows installer. (#1726) --- .github/workflows/binaries.yml | 71 ++++++++++++++++++++++++- installer.iss | 94 +++++++++++++++++++++++++++++++++ stellar.ico | Bin 0 -> 11166 bytes 3 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 installer.iss create mode 100644 stellar.ico diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 25cea7366..985f91fa5 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -34,7 +34,7 @@ jobs: target: aarch64-unknown-linux-gnu - os: macos-14 target: aarch64-apple-darwin - - os: macos-12 + - os: macos-14 target: x86_64-apple-darwin - os: windows-latest target: x86_64-pc-windows-msvc @@ -44,41 +44,50 @@ jobs: - uses: actions/checkout@v4 - run: rustup update - run: rustup target add ${{ matrix.sys.target }} + - if: matrix.sys.target == 'aarch64-unknown-linux-gnu' run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev + - name: Setup vars run: | version="$(cargo metadata --format-version 1 --no-deps | jq -r '.packages[] | select(.name == "stellar-cli") | .version')" echo "VERSION=${version}" >> $GITHUB_ENV echo "NAME=${{ matrix.crate.name }}-${version}-${{ matrix.sys.target }}" >> $GITHUB_ENV + - name: Package (release only) if: github.event_name == 'release' run: cargo package --no-verify --package ${{ matrix.crate.name }} + - name: Package Extract (release only) if: github.event_name == 'release' run: | cd target/package tar xvfz ${{ matrix.crate.name }}-$VERSION.crate echo "BUILD_WORKING_DIR=target/package/${{ matrix.crate.name }}-$VERSION" >> $GITHUB_ENV + - name: Build env: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc working-directory: ${{ env.BUILD_WORKING_DIR }} run: cargo build --target-dir="$GITHUB_WORKSPACE/target" --package ${{ matrix.crate.name }} --features opt --release --target ${{ matrix.sys.target }} + - name: Build provenance for attestation (release only) if: github.event_name == 'release' uses: actions/attest-build-provenance@v1 with: subject-path: target/${{ matrix.sys.target }}/release/${{ matrix.crate.binary }}${{ matrix.sys.ext }} + - name: Compress run: | cd target/${{ matrix.sys.target }}/release tar czvf $NAME.tar.gz ${{ matrix.crate.binary }}${{ matrix.sys.ext }} + - name: Upload to Artifacts uses: actions/upload-artifact@v4 with: - name: ${{ env.NAME }} + name: ${{ env.NAME }}.tar.gz path: 'target/${{ matrix.sys.target }}/release/${{ env.NAME }}.tar.gz' + - name: Upload to Release (release only) if: github.event_name == 'release' uses: actions/github-script@v7 @@ -92,3 +101,61 @@ jobs: name: '${{ env.NAME }}.tar.gz', data: fs.readFileSync('target/${{ matrix.sys.target }}/release/${{ env.NAME }}.tar.gz'), }); + + installer: + needs: build + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup vars + run: | + version="$(cargo metadata --format-version 1 --no-deps | jq -r '.packages[] | select(.name == "stellar-cli") | .version')" + installer_basename="stellar-cli-installer-${version}-x86_64-pc-windows-msvc" + echo "VERSION=${version}" >> $GITHUB_ENV + echo "STELLAR_CLI_INSTALLER_BASENAME=${installer_basename}" >> $GITHUB_ENV + echo "STELLAR_CLI_INSTALLER=${installer_basename}.exe" >> $GITHUB_ENV + echo "ARTIFACT_NAME=stellar-cli-${version}-x86_64-pc-windows-msvc.tar.gz" >> $GITHUB_ENV + + - name: Download Artifact + uses: actions/download-artifact@v4 + with: + name: ${{ env.ARTIFACT_NAME }} + + - name: Uncompress Artifact + run: tar xvf ${{ env.ARTIFACT_NAME }} + + - name: Build Installer + shell: powershell + run: | + $Env:Path += ";C:\Users\$Env:UserName\AppData\Local\Programs\Inno Setup 6" + $Env:STELLAR_CLI_VERSION = "${{ env.VERSION }}" + ISCC.exe installer.iss + + - name: Build provenance for attestation (release only) + if: github.event_name == 'release' + uses: actions/attest-build-provenance@v1 + with: + subject-path: ${{ env.STELLAR_CLI_INSTALLER }} + + - name: Upload Artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ env.STELLAR_CLI_INSTALLER }} + path: Output/stellar-installer.exe + + - name: Upload to Release (release only) + if: github.event_name == 'release' + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + await github.rest.repos.uploadReleaseAsset({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: ${{ github.event.release.id }}, + name: '${{ env.STELLAR_CLI_INSTALLER }}', + data: fs.readFileSync('Output/stellar-installer.exe'), + }); + diff --git a/installer.iss b/installer.iss new file mode 100644 index 000000000..895740ccb --- /dev/null +++ b/installer.iss @@ -0,0 +1,94 @@ +#define STELLAR_CLI_VERSION GetEnv("STELLAR_CLI_VERSION") +#define STELLAR_CLI_INSTALLER GetEnv("STELLAR_CLI_INSTALLER") + +[Setup] +AppName=Stellar CLI +AppVersion={#STELLAR_CLI_VERSION} +DefaultDirName={commonpf}\Stellar CLI +DefaultGroupName=Stellar CLI +OutputBaseFilename=stellar-installer +PrivilegesRequired=admin +LicenseFile=LICENSE +UninstallDisplayIcon={app}\stellar.ico +Compression=lzma +SolidCompression=yes +ChangesEnvironment=yes + +[Files] +Source: "stellar.exe"; DestDir: "{app}" +Source: "stellar.ico"; DestDir: "{app}" +Source: "LICENSE"; DestDir: "{app}"; Flags: ignoreversion + +[Icons] +; Windows optimizes start menu, and removes the uninstall entry. Unless we +; specify it twice. 🫠 +Name: "{group}\Uninstall Stellar CLI"; Filename: "{uninstallexe}" +Name: "{group}\Uninstall Stellar CLI"; Filename: "{uninstallexe}" +Name: "{group}\Stellar Developer Docs"; Filename: "https://stellar.org/docs" + +[Code] +const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; + +procedure EnvAddPath(Path: string); +var + Paths: string; +begin + { Retrieve current path (use empty string if entry not exists) } + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Paths := ''; + + { Skip if string already found in path } + if Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';') > 0 then exit; + + { App string to the end of the path variable } + Paths := Paths + ';'+ Path +';' + + { Overwrite (or create if missing) path environment variable } + if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Log(Format('The [%s] added to PATH: [%s]', [Path, Paths])) + else Log(Format('Error while adding the [%s] to PATH: [%s]', [Path, Paths])); +end; + +procedure EnvRemovePath(Path: string); +var + Paths: string; + P: Integer; +begin + { Skip if registry entry not exists } + if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then + exit; + + { Skip if string not found in path } + P := Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';'); + if P = 0 then exit; + + { Update path variable } + Delete(Paths, P - 1, Length(Path) + 1); + + { Overwrite path environment variable } + if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) + then Log(Format('The [%s] removed from PATH: [%s]', [Path, Paths])) + else Log(Format('Error while removing the [%s] from PATH: [%s]', [Path, Paths])); +end; + +procedure CurStepChanged(CurStep: TSetupStep); +begin + if CurStep = ssPostInstall + then EnvAddPath(ExpandConstant('{app}')); +end; + +procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep); +begin + if CurUninstallStep = usPostUninstall + then EnvRemovePath(ExpandConstant('{app}')); +end; + +[UninstallDelete] +; Remove the Start Menu group +Type: filesandordirs; Name: "{group}" + +; Remove installed files and directory +Type: files; Name: "{app}\stellar.exe" +Type: files; Name: "{uninstallexe}" +Type: files; Name: "{app}\stellar.ico" +Type: dirifempty; Name: "{app}" diff --git a/stellar.ico b/stellar.ico new file mode 100644 index 0000000000000000000000000000000000000000..4bbfa5f04cc650d18b34a9d03d6c5c6193db2213 GIT binary patch literal 11166 zcmdsdg;!Nk_wA*T20`h#ASfs;ARyfeQX(KCp$JO1N_RJc(k&8#5(3hxBFIIM2I=mS zeCvGQZ@lr|pYWdI;12IS_w2LxT64`g*FvGN;4ktA3&n~G;X$D;!Rt^>4P{aydLnp9 zs;Z)(jl7HeBgBVaMvm_-P$-^zstU5Y?jvhyul2i^jyos&9kf-iII1lAJSt|nv=Z~E zxYh8^rMcABDh20sow~{ThS6?e^}v`Gs_+v11=sS1ShKk=ZxjnZ_8VS^jZ?k3b8Oz| zvgTVdzw05j^V0awfJ@Ehzp;ZI;ojHjt*2w6_j39yWwJEILg}msu2K`-dXLh)${0k1 z3T!d`fBj{LUj+{Jsg{n8|HEqAtS?_^6%`e~I4zKIb8~AN7=$kLX5@VOL`6eGL+b5y zc5>_Y^P8)yt7rS>FJ2H!NJtEgj<){%Nt&LXzPY=rki`4Q#L7ywwvhUEbHAl9Jw`+G zUFVM^K8L?8ct-WFXyB_!anAPFM&Fl|+l+xvuG6atWnnjAFB5p!+VXC1Z^vY0kSD4sj+987nw$H}`s14pm6>jCZOLXxd77BY zawXplCPLw86%B|v&6DI1c$g0j51VdIHN!`Iqoc`R9jvR5T=~wEiQU9nYEDZ!f_EZ@j_5L0Spd>nEqD0WXS=MBl%ESE*~gD()+uCj`b^HxPLstPvYTzRu=rWwNtCs< zsW2GK=5#wTX1y%z(hWnCt?73CDr>re{R?DF;<$ynVQ?BVOZ^4-)yjBHsDz{>dG18B zA8&5FFD>O`%!M$hpw>fgFEBTEcWHZsO5ce-!f~R)WR}hTUuH=T>ad; zx%pQfQ<_Z8BvA?qm;M=wmMjsThZ0kHRn8u2-W&;y>5eojxO}|!FsIgT;=9J4>2*Z z%%?xzlvP(N!*em5S=-r>R~nKgss%1DKYy>w4L_2vb_vOuC1tFvt{FFYsMcQi__WCf zOTY3t&8yu-*^xx08s{adS;t$jWxr>iy+`pUz@;i2RMul(Vk-con4^Q?ttN=uiHQk_ z`+(|d(XaLOeWi~i(k4!4zg--wb0ZH747_^%x`M1M77-DVroO)AW=gPnGX_J|+}un- z6d3U}(tT~@X4exzMoIUwVXVg;6sT8^ir$WWeR&ZJ3+oH4K!ByYyZcw2+eT1|+s4-& zGRQj;vmbqZlu=Ppi^HE6GR_)4d?32aYb4|4CDoIDI~?|tVGif`0kW1xZ|@G$vz8V) zfUDJs`jo!dbZ7iuB>U^*;Zsv4=w?Y{V`JJ|jvO8y9{f+bC_2(2{|pTLT^;@`=5feR z#v&C_^xz}?Z{up)aaL*~0V@p0rn@BOr`^>2&lJt8)I&8+T+7SL&aW;%!sZWv-BD0h zHg63gRjM4#S7*4JE=hNGcDC4GK)z&ad8zU2h{ttpBye}vx!%}udvnuAhP5f-nhtFx zmixi_qpOK(t3&1Tc6ZphQ6y6U4#`5#qWbbrL_|amH(SXCY(|75Xa!n0c)Lzcc6wFr z-BW(`s&>$gb!>c`l76fTmpiW-KVq=2e6LZ++5+8dcWYm6_k|B=DXiUd{@*rGz@ENQ^?KBqq}ZEOoQ^9 zotrZ~+Finbyz$!Iot1+F7oI8N$cN$G>Z*0IemQncP0hy>w+9a%1Ox_}u8-A}RaJ4W z+2TaANOyd=UsPt=itj(Uk%=u6fSnt+6!xqR54%3 zm(*KM_^7GrX}@2;G`lmTSv;gNDqfRHdLB`~7%XnCby?Xw`R9}~EG(>xI+HUrq;F|y z$QY-;OEc$V$g#t{KaWXmgYmIX zqZbz~iw!<^ux@xAjJsv&a{ry1Q>=ZPprl!-d$?TmvCOQU2-2!+ao@(;nu3-#1X7T$ zotXxzd1xp;-3erT%#XRvy}c{r3To`S4<499a;n_DtDveH+PAjz&!amq435vFmk%PYN3wOn{_=B@YRdm6b8-xhFU`Z{8fLvSCP2yW(}cCYm!^{pnK+ zY#;?CrR;2&Pyyc5=HJ%jTTc1Le3fvd(*Pg*A@4PJm2GTp2nq^jYF@Qp=wX7(%F3D| z=!7U}XaZpusa6Pjh??FCJ>z$nR;W*(b6x&@Aw|?qsnP3HMKpSw9?BksFkYaX@AR}; z&ZwxUXy@-j9X4trIxW_~cx+8gO`me}&Se)jx0Zkl`kyUGXLy%1y_5l@Hzw*sA|n-L zWqteBQr^Bb-JbnML5LeMLNcFwr9KVc1V5^xk=yj2K7C?MR3r70-?|Su zcQ=_I%dDJsyv~hloW|QFz^tg@#4jc;>V2>SKAq`{+t;qH;?)DMC|qcb;@IQ<){D! zwCrSqr>dJ`j=jZ&nD}^{$B!S^2ON%!j+%EyG0}=x(=J(Poi%-n=c2rL(VxZpBsRp8 zg@pxRk%Un!#`%FTod#i(KLI(v^$>r((TaSRq z5K49xx4^;Vuc)@p&Xu{8W(Z*k*VRn_3@n6Oz{ijG*VxU@OR6XQR5%1fxfMCCeUYDejKQ21qjsv?q(-|%LwrGq~0_S~E zk-WZsa*sdD;pwgqnU~|(7Y7^&<*u$Se*N?y@0QU~2DvN>-~pUMn=1kaSU^T_fLCPi zyl!c2rKF`*slAmt3t*vdYW62soNR3D z`FFyp{w|=RLKyS&FXO@bxV(plWR=aRQtpJAC%&1qv@|Sc)r|vnF%8ROfB2a=xtE)p z8^@I^v9?47SFc@b{+`HF{&L5{f8N}K2@*y@K>>G0kb;3K{-RGj*FCh5kWPUcWP{nx z{7=i_Pgj=a?frtuSYKH#&o8cxRLZ-%ivbw6exWiC>d3{-tg5>7_wQfv z#sx?s6Gd9C(Q7OwJl+!Y`LT;ojY)4NOk5c5Ng-i@+r z$!#Q=`T6*sN4tGX>F2<5TqY!QPw1dN{7eyLXJhkK39|u$i;ItM_HTQx_}g#i{Z#`f zri`~=QTzN2_lN6QZ{L1Y&}?U8LmDV2TT90&@8WW^;q2%I#OFoTavPwjfy9^5P&j&e zdUES>RE@s6Q$m;mc@X^YXpmUu(IY0kQlr9ti8p+Yqj(?H#@G_A!1gr*9sx{+6Jbw0R$>8zK-5E;6nlD8Mszgl#;>#^*}|`f8h7vpxHuC8UU?= zw)H~;1Jl7`0|+>D+{4EV%XY%+lZ_c&?fI|tZ=mQS@h@DsAYRWdBJyTOS#~5_uV`zn zdQy%zX{Pb~^kd)JLw)@w;JI>HF_yNc^Y*}gkunWDVzKFC@BlX8Lyk`VA1oYvlas@( z+>~ZF;-Wm9BA`60DTd zd@$)9&DVHB^{4caP^~BA=iPV07tpaGS~Yv;q334@jhftvUESSqZMlH{YZCqY_wo4n z_$0m0jEWXs?=Jf46llC1JGGT}0OV_HYnxig@D{1H0d}@E)5$I_{w}s=?{PcC6eSBw zv|YnLr2>r8F74(`MlpMtm1c4jlpE(wQD1;JHejK^EV<0QyORY%qM|I+xvL&~pVGh{ zwUr8rULGWpQBn#T?5(Y}Ou_q}MSik6v-p zn;Q=|x99F))`jWxh-9G3X@p88-FRrR9m-rW2XPn@8Y&B+PI)XJOs44UER0V|uTabL z4tI$WzqaMOR@sX`yd|Q#j7&@dPV;v$>L!eEu>N;B9Z2OrG(zG~FjTDhc=Zmz>14R$m;=kE%PRXM8A=XIC^}FAV z9o=&8>E$|7VO4zii_UL)dOFC5TDxX1Cp&v{tCQvPw40`u zmM;(&G+fr3ejB2Lhli*8tx)HbtNs-vdb#eU|33Oxs8bMU>(^IEt}1ScFF^8G^Bx1RhlB z`E%~ru_M4BLSLA9D3HWT)rIqa%Vnvoov4w1^l^q zFaIt`Om*8$X<(u&gC*>)l5>lTA)r?QSDOb1-@vle)YVC$Pz4dGKobkQk@7nFKS}eS0cm0h=6#TK+#c%Dp*}xW6-w#oaJl?#0+2|3y2x0 zf$WB%k&)?9yT?rUJ45eQXt(<@OzzqzBxk#@BKy7kx@RF~uFY;87 zC#r7BIll)6*o1^G0>*-FL9da4ekyZW(NiMz@=?Ujv{}9;l@Wb*dK~Zi_=U=bHn7g? z`eg_VSdQ1;Tw1qGIFbx3FE1Cr5|<%E?NA

sPeuj{E;befu1(kX?|w$Sf2{n6epS5qL+0h> zl{@Z!qnHBqNCb6TQc|VvJQ{Y%6d)I5oPy&DLP@_TTmwbA2p$M*0+n(UqpvP^d)}QS zl{(B-U=Klwi8SyGAc^F_(*eeG*|8?I>s?~!jOlb+C`EYt=Kek>lvlKb1cQKpz!&?! z*j5kTbrZ07$czMf2hd<={tzJRe}km0fq?-4A6u10$-VON9A$FMcprzOqa*NLhxu+g zOsO#OojZ3r7BWl%QI-sw)2piydL@Rju8qEclCqrfl;29oPmHl2p<}0j<)O!E)X{u= z&9Pc!KlC(qJ}gb-odhM$V6Vhex2>LFh36}i|QDk zLGTG-c1{l6MYjpsXFaL1*4Ed{yW95n_w_3*DgFHY8Cp_DD_<1s9VdVN_kbMEe3TAV zc!xXJX@#6oi~Wq>A~tvp~bGBPr;wJp6bev|VO z&M6O^wM`PL;~iGa8SBC7@I|xo3q_Ei4>JIxS58BhXX7iwGhoR z3uc@=D@7S+yU3CuuAZJ=^6l3mXf)b+L>Xz*lkaBu*x zfa_Cvf4R9b@L>}mLlNZHvAm+kbh#7Tj*6t(U3GO6j2&0{=}@L1f-9&{k7y1j>R$uv z7;5m80L%o{N=QsBFC&BE=}FiatMLb(X+7D%R9RW6RBdNvH5_C1Fr#K~iNuG0guARt z$R{q2ii49Aed9)?imfLYbpb&^W@jh=BI=dTlo7Sc!NFkyK&lXcX=%ZR2n>{Am4U*( zcjjf2#Ap3Jyom_wm&mxY6V2h@)?oc|GdvNS5e0?%wA9ox>tR8Uqosmkpwf>6IBwif zxBF2t59c0rO($Q5m4bGc`*W4U)m(P16l~-a?V9uRDfxJKV=Q29B>uUAwx6HxW#7O8gk}?z>ZUaLJdbh#hxH1YZDqJDtRcHGd!^Wxfx&J8Kmy(*}d8+fcvojen+)s zUpCwR*tc)r7WY$#mzL!vnaNqa4%ynw1Y#NS0b9Xq&9A7SrjN{LQ!52e3rMhvni@cS zM(=`XK&A*6RU~!pGnJ+dIu{PA3lknY>Sm`+Z|bg&Ap7OY)c`sL2!~&Ny{G)rGpd@s zlHy_t3W`h@j(6oR_gCrS;^SjeQ|~?r!bO>PMEHWz1yLTlA81%I_^L)8Pv+iY+;yEo zT{F}xTAE$ZT!{U_hZ9R*bs&g1)6MiJE}>Ci^yQA*Q7aKQ zeSX#(lbEPD66yT};DJ_siU_uapg#m@_PFpZSPp?vc;=K2l1#Eo7 z%Xy})yDTPUD8LOf2Az-7X>Jp;z?6eX=;XkoEi5W}aaH)$@xBdO3Zj(&9ZLv@%Qntr zsH3Z!yZ4BI8zmm|_H8H_{TN#mYQpQ-22SAX!Nlv_M^@CBKqah9w~Yy?d&R1nM-Tyn zX{0OOKE8;w@rT+M=jwld(&Tw1{pc2>;CPvn&IkL|`;f34u{KuxP2Ht|$0jw`&PeOBD0@EreK_ zMFSA)Eg-w>(BIgxGT|U#QOUwqR5Q|DP%;q@9F@m$eUeJ?AY2q$&U<*R?!XVb_AehC=$B4HRglx#r1}2Xf z&CdRJVWBfDVYW8=$8N?ASq)TEKW)t?MF$4~;PGWn3mRygM$hAY$RC8(=*L!U{hwCT z`uciENJtZ$m;qbD(bU|JBw!D=j%qd1Ei+pnKq8gyL`kyd8R|`M zJgidC)T96lL*IcR*-T%Ys}4<|;f0oZ(u?>Paumla;Fpx%lPG5^?$FQcIT{?}j# zph@9-P-^6B#LM+&A=71LkdTZ_$;5<}=L0!iJVf3!c$J3I8yg$C({YXTv! z!ot)Dd0o@UF{*PV1xA8cBZI1(F3o*?<)%UjqzAuM!9p(H+vsR+#)89P9}lo-6~`+3 z{8=7$=goD4maymIczAfESob*ay?~a}i^vb#6Ul{r`Xp#Q{7G?TflK{e+xMS3gM>1t z^xj~k*gHFO!2PIcXplxwo$DH!YO}3MhXMo2U{QC^5)Aj;luR0>P~6{7%>!%(oNXt* zh9YrbVL^4l-Rxn#EGN>IOuzm5In&9^`g&A`*HP$JQkOBF`7;#43MAZkAvg>iJ}(1d zfKuLuoo;Po!=NEM#4m3~l_Fw;d9{htXm?ibu!%#GiiMbB9T9Y3lb9*qOhZ&47#1Ll zN=?^VR)jSWOgV1CI|j*aZYAA68kj#We-=E|@p_;SpZAVA_reDa_5!U)B{__a~P! zS(_rD<;MY1)H?eu9z0-!SfwR!1(D(pm|melTS)97#R4s%;#+4=1d%QuXtGM)bJ7#9 zhw-F^e;*T+)1jau1YEetdMVsMOML;M4$#X2CrstZ)We4l&3jUB6%SuD1&33=pjp~+ zRz;88%O?gE!6b2sDipW=)gF5MOzGvxp+H<*9MZN(iwdo12Y2umG&gu2$Jx5&APoydaH^?=X-ra$XgAW)gQx*F zD{h@EJ{!z7P`={z=FpUl`1oRoIs%P?mXSXcgiKj~mFj9OIMks3ivG7M27-_mhsVbV z+yNq?$C)_4f%B*Zh}SRSOhb`xvYTLXH!nLI8~7CBNopAz+d3c5&(9-(2V$t!c}Wgd z{Ra9WBrH;le8yjY9WeneLGMsxDSr{KgApe#8#>#-HT3IWRcbV|j+j|k1pSvyHMO?- zJG&(db0-qP&Wn?Jp`cpkreuqX@t~kj0-ot@*egvvJqzb!3kwVAYXFn;fi~dM`V=k{ zhzB2y2bP$iOf(@HQdH5--u430mIaH35)rT39tr=Wo}m7Soe9$*{V~Yp<=rU2jw#sY z;t)+6?$ozf(5^&WYn}(CziX$%d7&c^!6MBJMaJ&y7CzjKy1l&}qN?xTZEWABTzu&! zUpgPPJfumaSFE3<(^bG5!5~ToC7Z^9JYNY6N~K8pK&ad+yXin4*hNME%xdSRtdeAc z8}L6IKut{z7>h+WZHNLIa5~u8&7KPUg{CH%Gy-W9P}t09nYDFv z)Ll1mu3tjIO6?j?FM$UDt^q7c(w(1!D)gHM`EVC-d*~SECAkF#1ehQ$SjrPk{c7A_ zmcm1IZhW(jH9cEnBZBr*GC&jt2YiKGpcTV!Hz8TiVM!-!NkPUeX}L`kYru{uS@2*2 z?sB$5xP~15`uJEH_A35d&xGB|%8HPj{LdY<9^l37{Ji7z(M_J&wd0M(;JcjtKOCY& zzU~b^L>?L1T1%ywU$Fz_uxgA-liUDK00ZsK0G2NMKu1P~GyZQuh8Nnb5o9fLfwY(8 ze=dM01PcnHLe*}=sKMjbg!j28MqP+L!U+4xvuE;f*;tK}!s@|d9}bWrgsa%pKGRXo z)BYQOPpTR8-|l`7Fj=477gu~9L4ZUxhc9pO8;1^Lz`U8d69zW`}Y-wY;0tbqsAx-DD=hh$r`6;3W|!&y}jg+y1BK!7+fH; z0dj1BeY-~!kQRS|flOIXD5AsD{*O9JzcxP~)YYW|eyzXG%Izv`XyfFg|HIf9*|w?+ZIWM$jnPZ0yR8%TEF`#4OG*J2$CMI zrvhOpqZ&s%sQ6%4D9|r0FNc+t@pq?5BqiP)tLXwIjCeJEe%SSmDZL9bD<2y>ntX9o zMdQVkhH;?2;f9t3fo@}k>I&@^oQz)4T2Hl|8t-!{5HGG96E-mi5@KSk?Ck!=V@E7X zZ?R}!Z-QS%4_VpS5=ad8oVo63q{HGbwuCotFsH$dh>;AT0Ru?1#T4O1MLh5&>N=lJ zv8LN)_d>yO1M6W6ScBlY?^{f1T6pf=nv9U3JnEQ!f zzD+MBB^4ntj`9J&8u>=x-LT4*`qu{$>#bmNMnY;iiPwI-#czl@^pJv9u1`!1MMp`v z_t6p;2nR+fkDh6)BV94u%Fy4p-=0+kkO3R+;ups`qF8tG zsRIROm@qknQHiCk=Rzh=?rr_^z{SNyqVYdmuZQOvFR!f_Mo0vT8(21^KS-IQ381gC z3wSYJ>*Al3bQvZNg1}B*p3|M}%Td0{&D|2oAbPgzv@@?>pF4%20cb0JSWO0FN}Ov% zD<;25nnp(Go#wk`fm4I(Q$0}60ndNt@%hnZ=+McnrhF7Itg!S2pIGDsMtb~v5mTEU zXbljy_l1SBii&th?f?E=O;=YJMxL+}6BFGxr?6r_EvdJIMFD;zO~z$TP)lY1W0q1< zHh-TEhvo~?PAq-gs4+s*Gc`Adm!}=-HtCsE!BZUc9;L6ZZ-Q{Uh=?bi0eWCmL(R_A z<<8PBRH-xnG&D5CDkw+={gFA{se~+6Gzt)Cb7w~$AWYnC{cbJ!?sqsIB5ec<1k0kH|~jJMve8w>r{L}=pz6! zJ@{B%Jw33`GcPyl50EK`7rgXXN>A|SslYix`o!fGmUjbzPJpHdc#}c8_;syx;HgXl zEkYEw>-tzII8!h+mIFR&vWN|R{=Ez`z)D&2pFMziYx?Artvc(|zVcS{{w`Q!Ol!9dN ze6j$y&|F*uNVNa_*$$hiTKC&pQc@C`4Ip6iIN+|sRZL)Vd3Fgy1D@{vjH8PEMR-R8PaxN{vN Date: Fri, 15 Nov 2024 16:46:52 -0800 Subject: [PATCH 35/77] Fix powershell completion code. (#1730) --- FULL_HELP_DOCS.md | 4 ++-- cmd/soroban-cli/src/commands/tx/new/set_options.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 6bf321246..f007d0bf4 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1749,9 +1749,9 @@ Set option for an account such as flags, inflation destination, signers, home do * `--signer ` — Add, update, or remove a signer from an account * `--signer-weight ` — Signer weight is a number from 0-255 (inclusive). The signer is deleted if the weight is 0 * `--set-required` — When enabled, an issuer must approve an account before that account can hold its asset. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-required-0x1 -* `--set-revocable` — When enabled, an issuer can revoke an existing trustline’s authorization, thereby freezing the asset held by an account. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-revocable-0x2 +* `--set-revocable` — When enabled, an issuer can revoke an existing trustline's authorization, thereby freezing the asset held by an account. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-revocable-0x2 * `--set-clawback-enabled` — Enables the issuing account to take back (burning) all of the asset. https://developers.stellar.org/docs/tokens/control-asset-access#clawback-enabled-0x8 -* `--set-immutable` — With this setting, none of the other authorization flags (`AUTH_REQUIRED_FLAG`, `AUTH_REVOCABLE_FLAG`) can be set, and the issuing account can’t be merged. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-immutable-0x4 +* `--set-immutable` — With this setting, none of the other authorization flags (`AUTH_REQUIRED_FLAG`, `AUTH_REVOCABLE_FLAG`) can be set, and the issuing account can't be merged. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-immutable-0x4 * `--clear-required` * `--clear-revocable` * `--clear-immutable` diff --git a/cmd/soroban-cli/src/commands/tx/new/set_options.rs b/cmd/soroban-cli/src/commands/tx/new/set_options.rs index 3410b69e8..69cd10745 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_options.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_options.rs @@ -40,7 +40,7 @@ pub struct Cmd { /// https://developers.stellar.org/docs/tokens/control-asset-access#authorization-required-0x1 pub set_required: bool, #[arg(long, conflicts_with = "clear_revocable")] - /// When enabled, an issuer can revoke an existing trustline’s authorization, thereby freezing the asset held by an account. + /// When enabled, an issuer can revoke an existing trustline's authorization, thereby freezing the asset held by an account. /// https://developers.stellar.org/docs/tokens/control-asset-access#authorization-revocable-0x2 pub set_revocable: bool, #[arg(long, conflicts_with = "clear_clawback_enabled")] @@ -48,7 +48,7 @@ pub struct Cmd { /// https://developers.stellar.org/docs/tokens/control-asset-access#clawback-enabled-0x8 pub set_clawback_enabled: bool, #[arg(long, conflicts_with = "clear_immutable")] - /// With this setting, none of the other authorization flags (`AUTH_REQUIRED_FLAG`, `AUTH_REVOCABLE_FLAG`) can be set, and the issuing account can’t be merged. + /// With this setting, none of the other authorization flags (`AUTH_REQUIRED_FLAG`, `AUTH_REVOCABLE_FLAG`) can be set, and the issuing account can't be merged. /// https://developers.stellar.org/docs/tokens/control-asset-access#authorization-immutable-0x4 pub set_immutable: bool, #[arg(long)] From a8fdd5a6846f62baf9253ef6cbb3cd523e008369 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Sun, 17 Nov 2024 18:54:37 -0500 Subject: [PATCH 36/77] fix/add-exceptions-to-cargo-deny (#1722) --- Cargo.lock | 612 ++++-------------- Cargo.toml | 8 +- cmd/crates/soroban-test/Cargo.toml | 4 +- .../test-wasms/custom_account/Cargo.toml | 4 +- .../test-wasms/custom_account/src/lib.rs | 4 +- .../test-wasms/custom_type/Cargo.toml | 4 +- .../test-wasms/hello_world/Cargo.toml | 4 +- .../test-wasms/hello_world/src/lib.rs | 2 +- .../tests/fixtures/test-wasms/swap/Cargo.toml | 4 +- .../fixtures/test-wasms/swap/src/test.rs | 2 +- .../fixtures/test-wasms/token/Cargo.toml | 6 +- .../fixtures/test-wasms/token/src/test.rs | 4 +- .../tests/fixtures/test-wasms/udt/Cargo.toml | 4 +- .../tests/fixtures/test-wasms/udt/src/lib.rs | 2 +- .../tests/it/integration/hello_world.rs | 2 +- cmd/crates/stellar-ledger/Cargo.toml | 6 +- cmd/soroban-cli/Cargo.toml | 13 +- cmd/soroban-cli/src/commands/contract/init.rs | 2 +- cmd/soroban-cli/src/config/locator.rs | 9 +- cmd/soroban-cli/src/config/mod.rs | 5 +- .../src/utils/contract-template/src/test.rs | 2 +- deny.toml | 57 ++ 22 files changed, 226 insertions(+), 534 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82b62d2e3..e043b4f8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,7 +270,7 @@ dependencies = [ "bstr", "doc-comment", "libc", - "predicates 3.1.2", + "predicates", "predicates-core", "predicates-tree", "wait-timeout", @@ -285,7 +285,7 @@ dependencies = [ "anstyle", "doc-comment", "globwalk", - "predicates 3.1.2", + "predicates", "predicates-core", "predicates-tree", "tempfile", @@ -848,7 +848,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] @@ -944,17 +944,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crate-git-revision" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f998aef136a4e7833b0e4f0fc0939a59c40140b28e0ffbf524ad84fb2cc568c8" -dependencies = [ - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "crate-git-revision" version = "0.0.6" @@ -1022,7 +1011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ "generic-array", - "rand_core 0.6.4", + "rand_core", "subtle", "zeroize", ] @@ -1078,19 +1067,6 @@ dependencies = [ "syn 2.0.77", ] -[[package]] -name = "curve25519-dalek" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" -dependencies = [ - "byteorder 1.5.0", - "digest 0.9.0", - "rand_core 0.5.1", - "subtle", - "zeroize", -] - [[package]] name = "curve25519-dalek" version = "4.1.3" @@ -1182,7 +1158,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.11.1", + "strsim", "syn 2.0.77", ] @@ -1284,16 +1260,7 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys 0.3.7", + "dirs-sys", ] [[package]] @@ -1302,7 +1269,7 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys 0.4.1", + "dirs-sys", ] [[package]] @@ -1315,17 +1282,6 @@ dependencies = [ "dirs-sys-next", ] -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "dirs-sys" version = "0.4.1" @@ -1394,16 +1350,7 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", - "signature 2.1.0", -] - -[[package]] -name = "ed25519" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" -dependencies = [ - "signature 1.6.4", + "signature", ] [[package]] @@ -1413,19 +1360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" dependencies = [ "pkcs8", - "signature 2.1.0", -] - -[[package]] -name = "ed25519-dalek" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" -dependencies = [ - "curve25519-dalek 3.2.0", - "ed25519 1.5.3", - "sha2 0.9.9", - "zeroize", + "signature", ] [[package]] @@ -1434,9 +1369,9 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ - "curve25519-dalek 4.1.3", - "ed25519 2.2.3", - "rand_core 0.6.4", + "curve25519-dalek", + "ed25519", + "rand_core", "serde", "sha2 0.10.8", "subtle", @@ -1461,7 +1396,7 @@ dependencies = [ "ff", "generic-array", "group", - "rand_core 0.6.4", + "rand_core", "sec1", "subtle", "zeroize", @@ -1607,7 +1542,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -1880,7 +1815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ "ff", - "rand_core 0.6.4", + "rand_core", "subtle", ] @@ -2305,15 +2240,18 @@ dependencies = [ [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", - "hyper 0.14.30", + "http-body-util", + "hyper 1.4.1", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", ] [[package]] @@ -3338,20 +3276,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "predicates" -version = "2.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59230a63c37f3e18569bdb90e4a89cbf5bf8b06fea0b84e65ea10cc4df47addd" -dependencies = [ - "difflib", - "float-cmp", - "itertools 0.10.5", - "normalize-line-endings", - "predicates-core", - "regex", -] - [[package]] name = "predicates" version = "3.1.2" @@ -3360,7 +3284,10 @@ checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ "anstyle", "difflib", + "float-cmp", + "normalize-line-endings", "predicates-core", + "regex", ] [[package]] @@ -3488,7 +3415,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -3498,15 +3425,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core 0.6.4", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" - [[package]] name = "rand_core" version = "0.6.4" @@ -3580,46 +3501,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - [[package]] name = "reqwest" version = "0.12.7" @@ -3639,11 +3520,13 @@ dependencies = [ "http-body-util", "hyper 1.4.1", "hyper-rustls 0.27.3", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -3655,8 +3538,10 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper", + "system-configuration", "tokio", + "tokio-native-tls", "tokio-rustls 0.26.0", "tokio-util", "tower-service", @@ -4299,12 +4184,6 @@ dependencies = [ "libc", ] -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" - [[package]] name = "signature" version = "2.1.0" @@ -4312,7 +4191,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ "digest 0.10.7", - "rand_core 0.6.4", + "rand_core", ] [[package]] @@ -4336,24 +4215,13 @@ dependencies = [ "autocfg", ] -[[package]] -name = "slip10" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28724a6e6f70b0cb115c580891483da6f3aa99e6a353598303a57f89d23aa6bc" -dependencies = [ - "ed25519-dalek 1.0.1", - "hmac 0.9.0", - "sha2 0.9.9", -] - [[package]] name = "slipped10" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a45443e66aa5d96db5e02d17db056e1ca970232a4fe73e1f9bc1816d68f4e98" dependencies = [ - "ed25519-dalek 2.1.1", + "ed25519-dalek", "hmac 0.9.0", "sha2 0.9.9", ] @@ -4406,18 +4274,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "soroban-builtin-sdk-macros" -version = "21.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f57a68ef8777e28e274de0f3a88ad9a5a41d9a2eb461b4dd800b086f0e83b80" -dependencies = [ - "itertools 0.11.0", - "proc-macro2", - "quote", - "syn 2.0.77", -] - [[package]] name = "soroban-builtin-sdk-macros" version = "22.0.0-rc.3" @@ -4446,12 +4302,11 @@ dependencies = [ "clap", "clap-markdown", "clap_complete", - "crate-git-revision 0.0.4", + "crate-git-revision", "csv", "directories", - "dirs 4.0.0", "dotenvy", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "ethnum", "flate2", "fqdn", @@ -4470,10 +4325,10 @@ dependencies = [ "open", "pathdiff", "phf", - "predicates 2.1.5", + "predicates", "rand", "regex", - "reqwest 0.12.7", + "reqwest", "rpassword", "rust-embed", "semver", @@ -4484,17 +4339,17 @@ dependencies = [ "sha2 0.10.8", "shell-escape", "shlex", - "soroban-ledger-snapshot 22.0.0-rc.3", - "soroban-sdk 22.0.0-rc.3", - "soroban-spec 22.0.0-rc.3", + "soroban-ledger-snapshot", + "soroban-sdk", + "soroban-spec", "soroban-spec-json", - "soroban-spec-rust 22.0.0-rc.3", + "soroban-spec-rust", "soroban-spec-tools", "soroban-spec-typescript", "stellar-rpc-client", "stellar-strkey 0.0.11", - "stellar-xdr 22.0.0-rc.1.1", - "strsim 0.10.0", + "stellar-xdr", + "strsim", "strum 0.17.1", "strum_macros 0.17.1", "tempfile", @@ -4503,8 +4358,8 @@ dependencies = [ "thiserror", "tokio", "tokio-util", - "toml 0.5.11", - "toml_edit 0.21.1", + "toml", + "toml_edit", "tracing", "tracing-appender", "tracing-subscriber", @@ -4513,29 +4368,10 @@ dependencies = [ "walkdir", "wasm-gen", "wasm-opt", - "wasmparser 0.90.0", + "wasmparser", "which", ] -[[package]] -name = "soroban-env-common" -version = "21.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1c89463835fe6da996318156d39f424b4f167c725ec692e5a7a2d4e694b3d" -dependencies = [ - "arbitrary", - "crate-git-revision 0.0.6", - "ethnum", - "num-derive", - "num-traits", - "serde", - "soroban-env-macros 21.2.1", - "soroban-wasmi", - "static_assertions", - "stellar-xdr 21.2.0", - "wasmparser 0.116.1", -] - [[package]] name = "soroban-env-common" version = "22.0.0-rc.3" @@ -4543,26 +4379,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39b6d2ec8955243394278e1fae88be3b367fcfed9cf74e5044799a90786a8642" dependencies = [ "arbitrary", - "crate-git-revision 0.0.6", + "crate-git-revision", "ethnum", "num-derive", "num-traits", "serde", - "soroban-env-macros 22.0.0-rc.3", + "soroban-env-macros", "soroban-wasmi", "static_assertions", - "stellar-xdr 22.0.0-rc.1.1", - "wasmparser 0.116.1", -] - -[[package]] -name = "soroban-env-guest" -version = "21.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bfb2536811045d5cd0c656a324cbe9ce4467eb734c7946b74410d90dea5d0ce" -dependencies = [ - "soroban-env-common 21.2.1", - "static_assertions", + "stellar-xdr", + "wasmparser", ] [[package]] @@ -4571,41 +4397,8 @@ version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4002fc582cd20cc9b9fbb73959bc5d6b5b15feda11485cbfab0c28e78ecbab3e" dependencies = [ - "soroban-env-common 22.0.0-rc.3", - "static_assertions", -] - -[[package]] -name = "soroban-env-host" -version = "21.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b7a32c28f281c423189f1298960194f0e0fc4eeb72378028171e556d8cd6160" -dependencies = [ - "backtrace", - "curve25519-dalek 4.1.3", - "ecdsa", - "ed25519-dalek 2.1.1", - "elliptic-curve", - "generic-array", - "getrandom", - "hex-literal", - "hmac 0.12.1", - "k256", - "num-derive", - "num-integer", - "num-traits", - "p256", - "rand", - "rand_chacha", - "sec1", - "sha2 0.10.8", - "sha3", - "soroban-builtin-sdk-macros 21.2.1", - "soroban-env-common 21.2.1", - "soroban-wasmi", + "soroban-env-common", "static_assertions", - "stellar-strkey 0.0.8", - "wasmparser 0.116.1", ] [[package]] @@ -4618,9 +4411,9 @@ dependencies = [ "ark-ec", "ark-ff", "ark-serialize", - "curve25519-dalek 4.1.3", + "curve25519-dalek", "ecdsa", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "elliptic-curve", "generic-array", "getrandom", @@ -4636,27 +4429,12 @@ dependencies = [ "sec1", "sha2 0.10.8", "sha3", - "soroban-builtin-sdk-macros 22.0.0-rc.3", - "soroban-env-common 22.0.0-rc.3", + "soroban-builtin-sdk-macros", + "soroban-env-common", "soroban-wasmi", "static_assertions", "stellar-strkey 0.0.9", - "wasmparser 0.116.1", -] - -[[package]] -name = "soroban-env-macros" -version = "21.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "242926fe5e0d922f12d3796cd7cd02dd824e5ef1caa088f45fce20b618309f64" -dependencies = [ - "itertools 0.11.0", - "proc-macro2", - "quote", - "serde", - "serde_json", - "stellar-xdr 21.2.0", - "syn 2.0.77", + "wasmparser", ] [[package]] @@ -4670,7 +4448,7 @@ dependencies = [ "quote", "serde", "serde_json", - "stellar-xdr 22.0.0-rc.1.1", + "stellar-xdr", "syn 2.0.77", ] @@ -4678,20 +4456,6 @@ dependencies = [ name = "soroban-hello" version = "22.0.0-rc.1" -[[package]] -name = "soroban-ledger-snapshot" -version = "21.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84589856911dfd6731695c9b51c858aed6d4540118c0a1e5c4c858ea13bc744c" -dependencies = [ - "serde", - "serde_json", - "serde_with", - "soroban-env-common 21.2.1", - "soroban-env-host 21.2.1", - "thiserror", -] - [[package]] name = "soroban-ledger-snapshot" version = "22.0.0-rc.3" @@ -4701,31 +4465,11 @@ dependencies = [ "serde", "serde_json", "serde_with", - "soroban-env-common 22.0.0-rc.3", - "soroban-env-host 22.0.0-rc.3", + "soroban-env-common", + "soroban-env-host", "thiserror", ] -[[package]] -name = "soroban-sdk" -version = "21.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e39bf9e8ab05579c836e8e5be5f2f4c5ba75e7337ece20e975e82fc3a9d41e" -dependencies = [ - "arbitrary", - "bytes-lit", - "ctor", - "ed25519-dalek 2.1.1", - "rand", - "serde", - "serde_json", - "soroban-env-guest 21.2.1", - "soroban-env-host 21.2.1", - "soroban-ledger-snapshot 21.7.3", - "soroban-sdk-macros 21.7.3", - "stellar-strkey 0.0.8", -] - [[package]] name = "soroban-sdk" version = "22.0.0-rc.3" @@ -4735,70 +4479,38 @@ dependencies = [ "arbitrary", "bytes-lit", "ctor", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "rand", "rustc_version", "serde", "serde_json", - "soroban-env-guest 22.0.0-rc.3", - "soroban-env-host 22.0.0-rc.3", - "soroban-ledger-snapshot 22.0.0-rc.3", - "soroban-sdk-macros 22.0.0-rc.3", + "soroban-env-guest", + "soroban-env-host", + "soroban-ledger-snapshot", + "soroban-sdk-macros", "stellar-strkey 0.0.9", ] -[[package]] -name = "soroban-sdk-macros" -version = "21.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63c2173f1aacd56b4405eed71cb2a9694dff99d51ba72d4f0cbc5e4961fdabf4" -dependencies = [ - "crate-git-revision 0.0.6", - "darling", - "itertools 0.11.0", - "proc-macro2", - "quote", - "rustc_version", - "sha2 0.10.8", - "soroban-env-common 21.2.1", - "soroban-spec 21.7.3", - "soroban-spec-rust 21.7.3", - "stellar-xdr 21.2.0", - "syn 2.0.77", -] - [[package]] name = "soroban-sdk-macros" version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "508c9d819a05109120664aab86c371e1b72c5bea20b1a13158b4ef7948d9f673" dependencies = [ - "crate-git-revision 0.0.6", + "crate-git-revision", "darling", "itertools 0.10.5", "proc-macro2", "quote", "rustc_version", "sha2 0.10.8", - "soroban-env-common 22.0.0-rc.3", - "soroban-spec 22.0.0-rc.3", - "soroban-spec-rust 22.0.0-rc.3", - "stellar-xdr 22.0.0-rc.1.1", + "soroban-env-common", + "soroban-spec", + "soroban-spec-rust", + "stellar-xdr", "syn 2.0.77", ] -[[package]] -name = "soroban-spec" -version = "21.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7705bffbcc747c08e81698b87b4a787f8b268c25d88f777160091dc1ee8121cb" -dependencies = [ - "base64 0.13.1", - "stellar-xdr 21.2.0", - "thiserror", - "wasmparser 0.116.1", -] - [[package]] name = "soroban-spec" version = "22.0.0-rc.3" @@ -4806,9 +4518,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69001c97783ed3ce197eac2404e7beeabedd16e40e6f0aa210d1bc6a13063c33" dependencies = [ "base64 0.13.1", - "stellar-xdr 22.0.0-rc.1.1", + "stellar-xdr", "thiserror", - "wasmparser 0.116.1", + "wasmparser", ] [[package]] @@ -4820,24 +4532,8 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.9.9", - "soroban-spec 22.0.0-rc.3", - "stellar-xdr 22.0.0-rc.1.1", - "thiserror", -] - -[[package]] -name = "soroban-spec-rust" -version = "21.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48207ebc8616c2804a17203d1d86c53c3d3c804b682cbab011a135893db1cf78" -dependencies = [ - "prettyplease", - "proc-macro2", - "quote", - "sha2 0.10.8", - "soroban-spec 21.7.3", - "stellar-xdr 21.2.0", - "syn 2.0.77", + "soroban-spec", + "stellar-xdr", "thiserror", ] @@ -4851,8 +4547,8 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.8", - "soroban-spec 22.0.0-rc.3", - "stellar-xdr 22.0.0-rc.1.1", + "soroban-spec", + "stellar-xdr", "syn 2.0.77", "thiserror", ] @@ -4866,12 +4562,12 @@ dependencies = [ "hex", "itertools 0.10.5", "serde_json", - "soroban-spec 22.0.0-rc.3", + "soroban-spec", "stellar-strkey 0.0.11", - "stellar-xdr 22.0.0-rc.1.1", + "stellar-xdr", "thiserror", "tokio", - "wasmparser 0.90.0", + "wasmparser", "which", ] @@ -4889,8 +4585,8 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.9.9", - "soroban-spec 22.0.0-rc.3", - "stellar-xdr 22.0.0-rc.1.1", + "soroban-spec", + "stellar-xdr", "temp-dir", "thiserror", "walkdir", @@ -4902,22 +4598,22 @@ version = "22.0.0-rc.1" dependencies = [ "assert_cmd", "assert_fs", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "fs_extra", "hex", - "predicates 2.1.5", + "predicates", "sep5", "serde_json", "sha2 0.10.8", "soroban-cli", - "soroban-ledger-snapshot 22.0.0-rc.3", - "soroban-spec 22.0.0-rc.3", + "soroban-ledger-snapshot", + "soroban-spec", "soroban-spec-tools", "stellar-rpc-client", "stellar-strkey 0.0.11", "thiserror", "tokio", - "toml 0.8.19", + "toml", "ulid", "walkdir", "which", @@ -4925,11 +4621,11 @@ dependencies = [ [[package]] name = "soroban-token-sdk" -version = "21.7.2" +version = "22.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6ede0da76646037f3ea5db9ccd37830865444bb24f137cb8f0af8282c784f5" +checksum = "17bb933a3dcf41d234f6d669b077eb755663773630c6899a1c8a30dddf950f52" dependencies = [ - "soroban-sdk 21.7.2", + "soroban-sdk", ] [[package]] @@ -4985,7 +4681,7 @@ dependencies = [ "async-trait", "bollard", "byteorder 1.5.0", - "ed25519-dalek 2.1.1", + "ed25519-dalek", "env_logger", "futures", "hex", @@ -4997,18 +4693,18 @@ dependencies = [ "once_cell", "phf", "pretty_assertions", - "reqwest 0.11.27", + "reqwest", "sep5", "serde", "serde_derive", "serde_json", "serial_test", - "sha2 0.9.9", - "slip10", - "soroban-spec 22.0.0-rc.3", + "sha2 0.10.8", + "slipped10", + "soroban-spec", "stellar-rpc-client", "stellar-strkey 0.0.11", - "stellar-xdr 22.0.0-rc.1.1", + "stellar-xdr", "test-case", "testcontainers", "thiserror", @@ -5034,7 +4730,7 @@ dependencies = [ "serde_with", "sha2 0.10.8", "stellar-strkey 0.0.9", - "stellar-xdr 22.0.0-rc.1.1", + "stellar-xdr", "termcolor", "termcolor_output", "thiserror", @@ -5049,7 +4745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12d2bf45e114117ea91d820a846fd1afbe3ba7d717988fee094ce8227a3bf8bd" dependencies = [ "base32", - "crate-git-revision 0.0.6", + "crate-git-revision", "thiserror", ] @@ -5059,7 +4755,7 @@ version = "0.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e3aa3ed00e70082cb43febc1c2afa5056b9bb3e348bbb43d0cd0aa88a611144" dependencies = [ - "crate-git-revision 0.0.6", + "crate-git-revision", "data-encoding", "thiserror", ] @@ -5070,26 +4766,10 @@ version = "0.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0989c9a05eccbd08b60e603a1c7e3ed3ec92c0de73b8681fc964d272ab2b2697" dependencies = [ - "crate-git-revision 0.0.6", + "crate-git-revision", "data-encoding", ] -[[package]] -name = "stellar-xdr" -version = "21.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2675a71212ed39a806e415b0dbf4702879ff288ec7f5ee996dda42a135512b50" -dependencies = [ - "arbitrary", - "base64 0.13.1", - "crate-git-revision 0.0.6", - "escape-bytes", - "hex", - "serde", - "serde_with", - "stellar-strkey 0.0.8", -] - [[package]] name = "stellar-xdr" version = "22.0.0-rc.1.1" @@ -5099,7 +4779,7 @@ dependencies = [ "arbitrary", "base64 0.13.1", "clap", - "crate-git-revision 0.0.6", + "crate-git-revision", "escape-bytes", "hex", "schemars", @@ -5123,12 +4803,6 @@ dependencies = [ "precomputed-hash", ] -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -5223,12 +4897,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "sync_wrapper" version = "1.0.1" @@ -5240,20 +4908,20 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -5357,42 +5025,42 @@ dependencies = [ name = "test_constructor" version = "22.0.0-rc.1" dependencies = [ - "soroban-sdk 22.0.0-rc.3", + "soroban-sdk", ] [[package]] name = "test_custom_account" version = "22.0.0-rc.1" dependencies = [ - "soroban-sdk 21.7.2", + "soroban-sdk", ] [[package]] name = "test_custom_types" version = "22.0.0-rc.1" dependencies = [ - "soroban-sdk 21.7.2", + "soroban-sdk", ] [[package]] name = "test_hello_world" version = "22.0.0-rc.1" dependencies = [ - "soroban-sdk 21.7.2", + "soroban-sdk", ] [[package]] name = "test_swap" version = "22.0.0-rc.1" dependencies = [ - "soroban-sdk 21.7.2", + "soroban-sdk", ] [[package]] name = "test_token" version = "22.0.0-rc.1" dependencies = [ - "soroban-sdk 21.7.2", + "soroban-sdk", "soroban-token-sdk", ] @@ -5400,7 +5068,7 @@ dependencies = [ name = "test_udt" version = "22.0.0-rc.1" dependencies = [ - "soroban-sdk 21.7.2", + "soroban-sdk", ] [[package]] @@ -5413,7 +5081,7 @@ dependencies = [ "bollard", "bollard-stubs", "bytes", - "dirs 5.0.1", + "dirs", "docker_credential", "either", "futures", @@ -5421,7 +5089,7 @@ dependencies = [ "memchr", "parse-display", "pin-project-lite", - "reqwest 0.12.7", + "reqwest", "serde", "serde_json", "serde_with", @@ -5632,15 +5300,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.8.19" @@ -5650,7 +5309,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.20", + "toml_edit", ] [[package]] @@ -5662,17 +5321,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap 2.3.0", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.20" @@ -5683,7 +5331,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.18", + "winnow", ] [[package]] @@ -6017,9 +5665,9 @@ dependencies = [ [[package]] name = "wasm-opt" -version = "0.114.2" +version = "0.116.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effbef3bd1dde18acb401f73e740a6f3d4a1bc651e9773bddc512fe4d8d68f67" +checksum = "2fd87a4c135535ffed86123b6fb0f0a5a0bc89e50416c942c5f0662c645f679c" dependencies = [ "anyhow", "libc", @@ -6033,9 +5681,9 @@ dependencies = [ [[package]] name = "wasm-opt-cxx-sys" -version = "0.114.2" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c09e24eb283919ace2ed5733bda4842a59ce4c8de110ef5c6d98859513d17047" +checksum = "8c57b28207aa724318fcec6575fe74803c23f6f266fce10cbc9f3f116762f12e" dependencies = [ "anyhow", "cxx", @@ -6045,9 +5693,9 @@ dependencies = [ [[package]] name = "wasm-opt-sys" -version = "0.114.2" +version = "0.116.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f2f817bed2e8d65eb779fa37317e74de15585751f903c9118342d1970703a4" +checksum = "8a1cce564dc768dacbdb718fc29df2dba80bd21cb47d8f77ae7e3d95ceb98cbe" dependencies = [ "anyhow", "cc", @@ -6086,15 +5734,6 @@ dependencies = [ "paste", ] -[[package]] -name = "wasmparser" -version = "0.90.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62c8d843f4423efee314dc75a1049886deba3214f7e7f9ff0e4e58b4d618581" -dependencies = [ - "indexmap 1.9.3", -] - [[package]] name = "wasmparser" version = "0.116.1" @@ -6380,15 +6019,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.6.18" diff --git a/Cargo.toml b/Cargo.toml index 31e92e40b..f689accea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,7 +91,7 @@ tracing = "0.1.37" tracing-subscriber = "0.3.16" tracing-appender = "0.2.2" which = "4.4.0" -wasmparser = "0.90.0" +wasmparser = "0.116.1" directories = "5.0.1" ulid = "1.1" termcolor = "1.1.3" @@ -100,7 +100,11 @@ ed25519-dalek = ">= 2.1.1" http = "1.0.0" jsonrpsee-http-client = "0.20.1" jsonrpsee-core = "0.20.1" -tokio = "1.28.1" +walkdir = "2.5.0" +toml_edit = "0.22.20" +toml = "0.8.19" +reqwest = "0.12.7" +predicates = "3.1.2" [profile.test-wasms] inherits = "release" diff --git a/cmd/crates/soroban-test/Cargo.toml b/cmd/crates/soroban-test/Cargo.toml index d9eb31bdd..f694ec533 100644 --- a/cmd/crates/soroban-test/Cargo.toml +++ b/cmd/crates/soroban-test/Cargo.toml @@ -29,9 +29,9 @@ thiserror = "1.0.31" sha2 = "0.10.6" assert_cmd = "2.0.4" assert_fs = "1.0.7" -predicates = "2.1.5" +predicates = { workspace = true } fs_extra = "1.3.0" -toml = "0.8.10" +toml = { workspace = true } [dev-dependencies] diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml index 9be386b69..330fa03df 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { version = "=21.7.2" } +soroban-sdk = { workspace = true } [dev-dependencies] -soroban-sdk = { version = "=21.7.2", features = ["testutils"]} +soroban-sdk = { workspace = true, features = ["testutils"]} diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/src/lib.rs index c71324110..ed924322b 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/src/lib.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/src/lib.rs @@ -115,7 +115,9 @@ impl CustomAccountInterface for Contract { return Err(Error::NotPermitted); } } - Context::CreateContractHostFn(_) => return Err(Error::InvalidContext), + Context::CreateContractWithCtorHostFn(_) | Context::CreateContractHostFn(_) => { + return Err(Error::InvalidContext) + } }; } diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index 7c4ca5828..01429b00a 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["cdylib", "rlib"] doctest = false [dependencies] -soroban-sdk = { version = "=21.7.2" } +soroban-sdk = { workspace = true } [dev-dependencies] -soroban-sdk = { version = "=21.7.2", features = ["testutils"]} +soroban-sdk = { workspace = true, features = ["testutils"]} diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index 19b7353ca..6f00b845e 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["cdylib", "rlib"] doctest = false [dependencies] -soroban-sdk = { version = "=21.7.2" } +soroban-sdk = { workspace = true } [dev-dependencies] -soroban-sdk = { version = "=21.7.2", features = ["testutils"]} +soroban-sdk = { workspace = true, features = ["testutils"]} diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/src/lib.rs index 40006a1b7..b4b53c237 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/src/lib.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/src/lib.rs @@ -77,7 +77,7 @@ mod test { #[test] fn test_hello() { let env = Env::default(); - let contract_id = env.register_contract(None, Contract); + let contract_id = env.register(Contract, ()); let client = ContractClient::new(&env, &contract_id); let world = symbol_short!("world"); let res = client.hello(&world); diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml index 509483408..f74201a31 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { version = "=21.7.2" } +soroban-sdk = { workspace = true } [dev-dependencies] -soroban-sdk = { version = "=21.7.2", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs index 5c973880e..a60615162 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/src/test.rs @@ -21,7 +21,7 @@ fn create_token_contract<'a>(e: &Env, admin: &Address) -> (TokenClient<'a>, Toke } fn create_atomic_swap_contract(e: &Env) -> AtomicSwapContractClient { - AtomicSwapContractClient::new(e, &e.register_contract(None, AtomicSwapContract {})) + AtomicSwapContractClient::new(e, &e.register(AtomicSwapContract {}, ())) } #[test] diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml index 03055f2b7..880c39d52 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml @@ -12,8 +12,8 @@ rust-version.workspace = true crate-type = ["cdylib"] [dependencies] -soroban-sdk = { version = "=21.7.2" } -soroban-token-sdk = { version = "=21.7.2" } +soroban-sdk = { workspace = true } +soroban-token-sdk = { workspace = true } [dev-dependencies] -soroban-sdk = { version = "=21.7.2", features = ["testutils"] } +soroban-sdk = { workspace = true, features = ["testutils"] } diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/src/test.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/src/test.rs index 08be5f9ef..cd892a646 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/src/test.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/src/test.rs @@ -9,7 +9,7 @@ use soroban_sdk::{ }; fn create_token<'a>(e: &Env, admin: &Address) -> TokenClient<'a> { - let token = TokenClient::new(e, &e.register_contract(None, Token {})); + let token = TokenClient::new(e, &e.register(Token {}, ())); token.initialize(admin, &7, &"name".into_val(e), &"symbol".into_val(e)); token } @@ -247,7 +247,7 @@ fn initialize_already_initialized() { fn decimal_is_over_max() { let e = Env::default(); let admin = Address::generate(&e); - let token = TokenClient::new(&e, &e.register_contract(None, Token {})); + let token = TokenClient::new(&e, &e.register(Token {}, ())); token.initialize( &admin, &(u32::from(u8::MAX) + 1), diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/udt/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/udt/Cargo.toml index aea356447..206284802 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/udt/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/udt/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { version = "=21.7.2" } +soroban-sdk = { workspace = true } [dev-dependencies] -soroban-sdk = { version = "=21.7.2" , features = ["testutils"]} +soroban-sdk = { workspace = true , features = ["testutils"]} diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/udt/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/udt/src/lib.rs index 695d8a7a3..efb3cf480 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/udt/src/lib.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/udt/src/lib.rs @@ -80,7 +80,7 @@ mod test { #[test] fn test_add() { let e = Env::default(); - let contract_id = e.register_contract(None, Contract); + let contract_id = e.register(Contract, ()); let client = ContractClient::new(&e, &contract_id); let udt = UdtStruct { diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index a6bd00c91..fd38c2012 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -96,7 +96,7 @@ async fn invoke() { .arg("--id") .arg(id) .assert() - .stdout(predicates::str::contains(id).not()) + .stdout(predicates::str::contains(id)) .success(); invoke_hello_world_with_lib(sandbox, id).await; let config_locator = locator::Args { diff --git a/cmd/crates/stellar-ledger/Cargo.toml b/cmd/crates/stellar-ledger/Cargo.toml index 10fd34e42..b3d6318a4 100644 --- a/cmd/crates/stellar-ledger/Cargo.toml +++ b/cmd/crates/stellar-ledger/Cargo.toml @@ -21,20 +21,20 @@ thiserror = "1.0.32" serde = "1.0.82" serde_derive = "1.0.82" serde_json = "1.0.82" -sha2 = "0.9.9" +sha2 = { workspace = true } ed25519-dalek = { workspace = true } stellar-strkey = { workspace = true } ledger-transport-hid = "0.10.0" ledger-transport = "0.10.0" sep5.workspace = true -slip10 = "0.4.3" +slip10 = { package = "slipped10", version = "0.4.6" } tracing = { workspace = true } hex.workspace = true byteorder = "1.5.0" bollard = { workspace = true } home = "0.5.9" tokio = { version = "1", features = ["full"] } -reqwest = { version = "0.11", features = ["json"] } +reqwest = { workspace = true, features = ["json"] } soroban-rpc.workspace = true phf = { version = "0.11.2", features = ["macros"] } futures = "0.3.30" diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index d2a53e6f2..f1a2b146d 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -83,18 +83,17 @@ reqwest = { version = "0.12.7", default-features = false, features = [ jsonrpsee-http-client = "0.20.1" jsonrpsee-core = "0.20.1" regex = "1.6.0" -wasm-opt = { version = "0.114.0", optional = true } +wasm-opt = { version = "0.116.1", optional = true } chrono = { version = "0.4.27", features = ["serde"] } rpassword = "7.2.0" -dirs = "4.0.0" -toml = "0.5.9" +toml = { workspace = true } itertools = "0.10.5" shlex = "1.1.0" sep5 = { workspace = true } ethnum = { workspace = true } clap-markdown = { version = "0.1.4", optional = true } which = { workspace = true, features = ["regex"] } -strsim = "0.10.0" +strsim = "0.11.1" heck = "0.5.0" tracing = { workspace = true } tracing-appender = { workspace = true } @@ -109,7 +108,7 @@ strum_macros = "0.17.1" async-compression = { version = "0.4.12", features = ["tokio", "gzip"] } shell-escape = "0.1.5" tempfile = "3.8.1" -toml_edit = "0.21.0" +toml_edit = { workspace = true } rust-embed = { version = "8.2.0", features = ["debug-embed"] } bollard = { workspace = true } futures-util = "0.3.30" @@ -127,7 +126,7 @@ url = "2.5.2" wasm-gen = "0.1.4" [build-dependencies] -crate-git-revision = "0.0.4" +crate-git-revision = "0.0.6" serde.workspace = true thiserror.workspace = true @@ -135,6 +134,6 @@ thiserror.workspace = true [dev-dependencies] assert_cmd = "2.0.4" assert_fs = "1.0.7" -predicates = "2.1.5" +predicates = { workspace = true } walkdir = "2.5.0" mockito = "1.5.0" diff --git a/cmd/soroban-cli/src/commands/contract/init.rs b/cmd/soroban-cli/src/commands/contract/init.rs index 96f28c64e..9147bacf0 100644 --- a/cmd/soroban-cli/src/commands/contract/init.rs +++ b/cmd/soroban-cli/src/commands/contract/init.rs @@ -275,7 +275,7 @@ mod tests { let contract_dir = project_dir.join("contracts").join(contract_name); let cargo_toml_path = contract_dir.as_path().join("Cargo.toml"); let cargo_toml_str = read_to_string(cargo_toml_path.clone()).unwrap(); - let doc = cargo_toml_str.parse::().unwrap(); + let doc: toml_edit::DocumentMut = cargo_toml_str.parse().unwrap(); assert!( doc.get("dependencies") .unwrap() diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 8f51975a1..b6f5c75c1 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -1,4 +1,5 @@ use clap::arg; +use directories::UserDirs; use itertools::Itertools; use serde::de::DeserializeOwned; use std::{ @@ -419,11 +420,10 @@ impl KeyType { } pub fn read_from_path(path: &Path) -> Result { - let data = fs::read(path).map_err(|_| Error::NetworkFileRead { + let data = fs::read_to_string(path).map_err(|_| Error::NetworkFileRead { path: path.to_path_buf(), })?; - let res = toml::from_slice(data.as_slice()); - Ok(res?) + Ok(toml::from_str(&data)?) } pub fn read_with_global(&self, key: &str, pwd: &Path) -> Result { @@ -494,8 +494,9 @@ pub fn global_config_path() -> Result { let config_dir = if let Ok(config_home) = std::env::var("XDG_CONFIG_HOME") { PathBuf::from_str(&config_home).map_err(|_| Error::XdgConfigHome(config_home))? } else { - dirs::home_dir() + UserDirs::new() .ok_or(Error::HomeDirNotFound)? + .home_dir() .join(".config") }; diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index 6cd9b4d71..a429ff434 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -171,9 +171,8 @@ impl Config { let path = locator::config_file()?; if path.exists() { - let data = fs::read(&path).map_err(|_| locator::Error::FileRead { path })?; - - Ok(toml::from_slice(&data)?) + let data = fs::read_to_string(&path).map_err(|_| locator::Error::FileRead { path })?; + Ok(toml::from_str(&data)?) } else { Ok(Config::default()) } diff --git a/cmd/soroban-cli/src/utils/contract-template/src/test.rs b/cmd/soroban-cli/src/utils/contract-template/src/test.rs index af69a7ecb..0bdcba082 100644 --- a/cmd/soroban-cli/src/utils/contract-template/src/test.rs +++ b/cmd/soroban-cli/src/utils/contract-template/src/test.rs @@ -6,7 +6,7 @@ use soroban_sdk::{vec, Env, String}; #[test] fn test() { let env = Env::default(); - let contract_id = env.register_contract(None, Contract); + let contract_id = env.register(Contract, ()); let client = ContractClient::new(&env, &contract_id); let words = client.hello(&String::from_str(&env, "Dev")); diff --git a/deny.toml b/deny.toml index 7588e71f1..238e91a14 100644 --- a/deny.toml +++ b/deny.toml @@ -252,6 +252,63 @@ deny = [ # Certain crates/versions that will be skipped when doing duplicate detection. skip = [ + + # Requires updating slipped10 to newest sha2 others are dependents that will be updated + { crate = "sha2", reason = "temporary duplicate until upstream updates" }, + { crate = "digest", reason = "temporary duplicate until upstream updates" }, + { crate = "block-buffer", reason = "temporary duplicate until upstream updates" }, + # slipped again 0.12.1 + { crate = "hmac", reason = "temp" }, + + # update rpassword, hidapi (then ledger-transport-hid), and dirs-sys (then directories) to 0.52 + # { crate = "window-sys", reason = "temp" }, + + # syn is too large of a surface to check + { crate = "syn", reason = "Too many crates haven't updated to v2" }, + + # Need to release new version and update all stellar crates + { crate = "stellar-strkey", reason = "Temp until new release and updates upstream", version = "0.0.8" }, + + # Need to update jsonrpsee in stellar-rpc-client + { crate = "rustls-pemfile", reason = "Temp until new release and updates upstream" }, + { crate = "rustls-webpki", reason = "Temp until new release and updates upstream" }, + { crate = "rustls-native-certs", reason = "Temp until new release and updates upstream", version = "0.7.3" }, + { crate = "rustls", reason = "Temp until new release and updates upstream" }, + { crate = "hyper", reason = "temporary duplicate until upstream updates" }, + { crate = "hyper-rustls", reason = "temporary duplicate until upstream updates", version = "0.27.3" }, + { crate = "http-body", reason = "temporary duplicate until upstream updates" }, + { crate = "http", reason = "temporary duplicate until upstream updates" }, + { crate = "h2", reason = "temporary duplicate until upstream updates", version = "0.3.26" }, + { crate = "base64", reason = "temporary duplicate until upstream updates", version = "0.22.1" }, + # Upgrade stellar-rpc-client to use 0.26.0 + { crate = "tokio-rustls", reason = "temporary duplicate until upstream updates" }, + + # wasm-opt + { crate = "heck", reason = "wasm-opt needs to update to 0.5", version = "0.5.0"}, + { crate = "strum", reason = "wasm-opt needs to update", version = "0.26.3" }, + { crate = "strum_macros", reason = "wasm-opt needs to update", version = "0.26.4" }, + + + # soroban-env-host must upgrade ark-* to 0.14.5 + { crate = "hashbrown", reason = "temp", version = "13.2"}, + + { crate = "windows-sys", reason = "temp", version = "0.59.0"}, + { crate = "windows-targets", reason = "temp", version = "0.52.6"}, + { crate = "windows_x86_64_gnu", reason = "temp", version = "0.52.6"}, + { crate = "windows_x86_64_msvc", reason = "temp", version = "0.52.6"}, + # { crate = "dir-sys", reason = "temp", version } + # + # update tracing-subscriber + { crate = "regex-syntax", reason = "temp", version = "0.8.4" }, + { crate = "regex-automata", reason = "temp", version = "0.4.7" }, + + # wasm-gen update + { crate = "byteorder", reason = "temp", version = "1.5.0" }, + + # testcontainers + { crate = "idna", reason = "temp", version = "0.5.0" }, + + # { name = "hashbrown", version = "=0.13.2" }, # { name = "syn", version = "=1.0.109" }, ] From 77788732f7ed446a21586ede7416e6a599b0c97b Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 19 Nov 2024 03:49:20 +1000 Subject: [PATCH 37/77] Do not run npm commands but output instructions instead (#1731) --- .../ts-tests/initialize.sh | 1 + .../commands/contract/bindings/typescript.rs | 24 ++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh index d85eff115..031061cca 100755 --- a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh +++ b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh @@ -37,6 +37,7 @@ function deploy_all() { } function bind() { exe eval "./soroban contract bindings typescript --contract-id $(cat $1) --output-dir ./node_modules/$2 --overwrite" + exe eval "sh -c \"cd ./node_modules/$2 && npm install && npm run build\"" } function bind_all() { bind contract-id-custom-types.txt test-custom-types diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index 84e2b1762..4fcfe0955 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -5,6 +5,7 @@ use soroban_spec_tools::contract as contract_spec; use soroban_spec_typescript::{self as typescript, boilerplate::Project}; use stellar_strkey::DecodeError; +use crate::print::Print; use crate::wasm; use crate::{ commands::{contract::fetch, global, NetworkRunnable}, @@ -13,6 +14,7 @@ use crate::{ network::{self, Network}, }, get_spec::{self, get_remote_contract_spec}, + xdr::{Hash, ScAddress}, }; #[derive(Parser, Debug, Clone)] @@ -83,7 +85,9 @@ impl NetworkRunnable for Cmd { global_args: Option<&global::Args>, config: Option<&config::Args>, ) -> Result<(), Error> { + let print = Print::new(global_args.is_some_and(|a| a.quiet)); let spec = if let Some(wasm) = &self.wasm { + print.infoln("Loading contract spec from file..."); let wasm: wasm::Args = wasm.into(); wasm.parse()?.spec } else { @@ -97,6 +101,8 @@ impl NetworkRunnable for Cmd { .resolve_contract_id(&self.contract_id, &network.network_passphrase)? .0; + let contract_address = ScAddress::Contract(Hash(contract_id)); + print.globeln(format!("Downloading contract spec: {contract_address}")); get_remote_contract_spec( &contract_id, &self.locator, @@ -129,6 +135,7 @@ impl NetworkRunnable for Cmd { .expect("why did we remove the default futurenet network?") .into() }); + print.infoln(format!("Network: {network_passphrase}")); let absolute_path = self.output_dir.canonicalize()?; let file_name = absolute_path .file_name() @@ -136,6 +143,7 @@ impl NetworkRunnable for Cmd { let contract_name = &file_name .to_str() .ok_or_else(|| Error::NotUtf8(file_name.to_os_string()))?; + print.infoln(format!("Embedding contract address: {}", self.contract_id)); p.init( contract_name, &self.contract_id, @@ -143,17 +151,11 @@ impl NetworkRunnable for Cmd { &network_passphrase, &spec, )?; - std::process::Command::new("npm") - .arg("install") - .current_dir(&self.output_dir) - .spawn()? - .wait()?; - std::process::Command::new("npm") - .arg("run") - .arg("build") - .current_dir(&self.output_dir) - .spawn()? - .wait()?; + print.checkln("Generated!"); + print.infoln(format!( + "Run \"npm install && npm run build\" in {:?} to build the JavaScript NPM package.", + self.output_dir + )); Ok(()) } } From 90db678c08e51e84f05719b5f0965e8f53c3c893 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 19 Nov 2024 04:19:46 +1000 Subject: [PATCH 38/77] Use the same network and contract resolution for all of the bindings generation logic (#1733) --- .../commands/contract/bindings/typescript.rs | 50 ++++++++----------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index 4fcfe0955..679e757f4 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -9,10 +9,7 @@ use crate::print::Print; use crate::wasm; use crate::{ commands::{contract::fetch, global, NetworkRunnable}, - config::{ - self, locator, - network::{self, Network}, - }, + config::{self, locator, network}, get_spec::{self, get_remote_contract_spec}, xdr::{Hash, ScAddress}, }; @@ -86,22 +83,25 @@ impl NetworkRunnable for Cmd { config: Option<&config::Args>, ) -> Result<(), Error> { let print = Print::new(global_args.is_some_and(|a| a.quiet)); + + let network = self.network.get(&self.locator).ok().unwrap_or_else(|| { + network::DEFAULTS + .get("testnet") + .expect("no network specified and testnet network not found") + .into() + }); + + let contract_id = self + .locator + .resolve_contract_id(&self.contract_id, &network.network_passphrase)? + .0; + let contract_address = ScAddress::Contract(Hash(contract_id)); + let spec = if let Some(wasm) = &self.wasm { print.infoln("Loading contract spec from file..."); let wasm: wasm::Args = wasm.into(); wasm.parse()?.spec } else { - let network = config.map_or_else( - || self.network.get(&self.locator).map_err(Error::from), - |c| c.get_network().map_err(Error::from), - )?; - - let contract_id = self - .locator - .resolve_contract_id(&self.contract_id, &network.network_passphrase)? - .0; - - let contract_address = ScAddress::Contract(Hash(contract_id)); print.globeln(format!("Downloading contract spec: {contract_address}")); get_remote_contract_spec( &contract_id, @@ -125,17 +125,7 @@ impl NetworkRunnable for Cmd { } std::fs::create_dir_all(&self.output_dir)?; let p: Project = self.output_dir.clone().try_into()?; - let Network { - rpc_url, - network_passphrase, - .. - } = self.network.get(&self.locator).ok().unwrap_or_else(|| { - network::DEFAULTS - .get("futurenet") - .expect("why did we remove the default futurenet network?") - .into() - }); - print.infoln(format!("Network: {network_passphrase}")); + print.infoln(format!("Network: {}", network.network_passphrase)); let absolute_path = self.output_dir.canonicalize()?; let file_name = absolute_path .file_name() @@ -143,12 +133,12 @@ impl NetworkRunnable for Cmd { let contract_name = &file_name .to_str() .ok_or_else(|| Error::NotUtf8(file_name.to_os_string()))?; - print.infoln(format!("Embedding contract address: {}", self.contract_id)); + print.infoln(format!("Embedding contract address: {contract_address}")); p.init( contract_name, - &self.contract_id, - &rpc_url, - &network_passphrase, + &contract_address.to_string(), + &network.rpc_url, + &network.network_passphrase, &spec, )?; print.checkln("Generated!"); From 7abcaeb65cf254602a7e0fe6c552d3813bcb5bfe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 04:11:55 +0000 Subject: [PATCH 39/77] Bump version to 22.0.0 (#1742) Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- Cargo.lock | 32 +++++++++---------- Cargo.toml | 10 +++--- cmd/crates/soroban-test/Cargo.toml | 2 +- .../tests/fixtures/bye/Cargo.toml | 2 +- .../tests/fixtures/hello/Cargo.toml | 2 +- .../test-wasms/constructor/Cargo.toml | 3 +- .../test-wasms/custom_account/Cargo.toml | 3 +- .../test-wasms/custom_type/Cargo.toml | 3 +- .../test-wasms/hello_world/Cargo.toml | 3 +- .../tests/fixtures/test-wasms/swap/Cargo.toml | 3 +- .../fixtures/test-wasms/token/Cargo.toml | 3 +- cmd/soroban-cli/Cargo.toml | 2 +- cmd/stellar-cli/Cargo.toml | 2 +- 13 files changed, 32 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e043b4f8e..89cb82cdf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4288,7 +4288,7 @@ dependencies = [ [[package]] name = "soroban-cli" -version = "22.0.0-rc.1" +version = "22.0.0" dependencies = [ "assert_cmd", "assert_fs", @@ -4454,7 +4454,7 @@ dependencies = [ [[package]] name = "soroban-hello" -version = "22.0.0-rc.1" +version = "0.0.0" [[package]] name = "soroban-ledger-snapshot" @@ -4525,7 +4525,7 @@ dependencies = [ [[package]] name = "soroban-spec-json" -version = "22.0.0-rc.1" +version = "22.0.0" dependencies = [ "pretty_assertions", "serde", @@ -4555,7 +4555,7 @@ dependencies = [ [[package]] name = "soroban-spec-tools" -version = "22.0.0-rc.1" +version = "22.0.0" dependencies = [ "base64 0.21.7", "ethnum", @@ -4573,7 +4573,7 @@ dependencies = [ [[package]] name = "soroban-spec-typescript" -version = "22.0.0-rc.1" +version = "22.0.0" dependencies = [ "base64 0.21.7", "heck 0.4.1", @@ -4594,7 +4594,7 @@ dependencies = [ [[package]] name = "soroban-test" -version = "22.0.0-rc.1" +version = "22.0.0" dependencies = [ "assert_cmd", "assert_fs", @@ -4665,18 +4665,18 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-bye" -version = "22.0.0-rc.1" +version = "0.0.0" [[package]] name = "stellar-cli" -version = "22.0.0-rc.1" +version = "22.0.0" dependencies = [ "soroban-cli", ] [[package]] name = "stellar-ledger" -version = "22.0.0-rc.1" +version = "22.0.0" dependencies = [ "async-trait", "bollard", @@ -5023,42 +5023,42 @@ dependencies = [ [[package]] name = "test_constructor" -version = "22.0.0-rc.1" +version = "0.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_account" -version = "22.0.0-rc.1" +version = "0.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_types" -version = "22.0.0-rc.1" +version = "0.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_hello_world" -version = "22.0.0-rc.1" +version = "0.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_swap" -version = "22.0.0-rc.1" +version = "0.0.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_token" -version = "22.0.0-rc.1" +version = "0.0.0" dependencies = [ "soroban-sdk", "soroban-token-sdk", @@ -5066,7 +5066,7 @@ dependencies = [ [[package]] name = "test_udt" -version = "22.0.0-rc.1" +version = "22.0.0" dependencies = [ "soroban-sdk", ] diff --git a/Cargo.toml b/Cargo.toml index f689accea..d2572e9c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,24 +19,24 @@ exclude = [ ] [workspace.package] -version = "22.0.0-rc.1" +version = "22.0.0" rust-version = "1.81.0" # Dependencies located in this repo: [workspace.dependencies.soroban-cli] -version = "=22.0.0-rc.1" +version = "=22.0.0" path = "cmd/soroban-cli" [workspace.dependencies.soroban-spec-json] -version = "=22.0.0-rc.1" +version = "=22.0.0" path = "./cmd/crates/soroban-spec-json" [workspace.dependencies.soroban-spec-typescript] -version = "22.0.0-rc.1" +version = "22.0.0" path = "./cmd/crates/soroban-spec-typescript" [workspace.dependencies.soroban-spec-tools] -version = "22.0.0-rc.1" +version = "22.0.0" path = "./cmd/crates/soroban-spec-tools" # Dependencies from the rs-stellar-xdr repo: diff --git a/cmd/crates/soroban-test/Cargo.toml b/cmd/crates/soroban-test/Cargo.toml index f694ec533..d035652d1 100644 --- a/cmd/crates/soroban-test/Cargo.toml +++ b/cmd/crates/soroban-test/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/soroban-test" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "22.0.0-rc.1" +version.workspace = true edition = "2021" rust-version.workspace = true autobins = false diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml index acee77f4b..deccb9c75 100644 --- a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stellar-bye" -version = "22.0.0-rc.1" +version = "0.0.0" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml index 2a212a532..fe7eb636a 100644 --- a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "soroban-hello" -version = "22.0.0-rc.1" +version = "0.0.0" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml index 8c38fecb4..69d8a6430 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "test_constructor" -version = "22.0.0-rc.1" +version = "0.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" publish = false -rust-version.workspace = true [lib] crate-type = ["cdylib"] diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml index 330fa03df..765f671c6 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "test_custom_account" -version = "22.0.0-rc.1" +version = "0.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" publish = false -rust-version.workspace = true [lib] crate-type = ["cdylib"] diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index 01429b00a..b5a17c6a5 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "test_custom_types" -version = "22.0.0-rc.1" +version = "0.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" publish = false -rust-version.workspace = true [lib] crate-type = ["cdylib", "rlib"] diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index 6f00b845e..a13c98a39 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "test_hello_world" -version = "22.0.0-rc.1" +version = "0.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" publish = false -rust-version.workspace = true [lib] crate-type = ["cdylib", "rlib"] diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml index f74201a31..495a52d71 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml @@ -1,11 +1,10 @@ [package] name = "test_swap" -version.workspace = true +version = "0.0.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" publish = false -rust-version.workspace = true [lib] crate-type = ["cdylib"] diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml index 880c39d52..6456983e8 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml @@ -1,12 +1,11 @@ [package] name = "test_token" -version.workspace = true +version = "0.0.0" description = "Soroban standard token contract" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" publish = false -rust-version.workspace = true [lib] crate-type = ["cdylib"] diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index f1a2b146d..2f2a26255 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/stellar-cli" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "22.0.0-rc.1" +version.workspace = true edition = "2021" rust-version.workspace = true autobins = false diff --git a/cmd/stellar-cli/Cargo.toml b/cmd/stellar-cli/Cargo.toml index 21e7e307b..e1f1dce6b 100644 --- a/cmd/stellar-cli/Cargo.toml +++ b/cmd/stellar-cli/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/stellar-cli" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "22.0.0-rc.1" +version.workspace = true edition = "2021" rust-version.workspace = true autobins = false From ad1f4a4ae198a84202ae133e025aac6f3d89a59d Mon Sep 17 00:00:00 2001 From: Gleb Date: Tue, 19 Nov 2024 10:27:06 -0800 Subject: [PATCH 40/77] Clippy fixes for 1.82 (#1741) --- .../src/commands/contract/deploy/asset.rs | 4 +-- .../src/commands/contract/deploy/wasm.rs | 8 +++--- .../src/commands/contract/extend.rs | 4 +-- .../src/commands/contract/install.rs | 6 ++--- .../src/commands/contract/invoke.rs | 26 +++++++++---------- .../src/commands/contract/restore.rs | 6 ++--- cmd/soroban-cli/src/commands/tx/args.rs | 2 +- cmd/soroban-cli/src/commands/txn_result.rs | 14 +++++----- cmd/soroban-cli/src/wasm.rs | 4 +-- 9 files changed, 36 insertions(+), 38 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs index 169c0109a..04a0380ed 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs @@ -110,12 +110,12 @@ impl NetworkRunnable for Cmd { source_account, )?; if self.fee.build_only { - return Ok(TxnResult::Txn(tx)); + return Ok(TxnResult::Txn(Box::new(tx))); } let txn = simulate_and_assemble_transaction(&client, &tx).await?; let txn = self.fee.apply_to_assembled_txn(txn).transaction().clone(); if self.fee.sim_only { - return Ok(TxnResult::Txn(txn)); + return Ok(TxnResult::Txn(Box::new(txn))); } let get_txn_resp = client .send_transaction_polling(&self.config.sign_with_local_key(txn).await?) diff --git a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs index 9bf63802c..1d85832b0 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs @@ -265,14 +265,14 @@ impl NetworkRunnable for Cmd { // Get the account sequence number let account_details = client.get_account(&source_account.to_string()).await?; let sequence: i64 = account_details.seq_num.into(); - let txn = build_create_contract_tx( + let txn = Box::new(build_create_contract_tx( wasm_hash, sequence + 1, self.fee.fee, source_account, contract_id_preimage, constructor_params.as_ref(), - )?; + )?); if self.fee.build_only { print.checkln("Transaction built!"); @@ -282,7 +282,7 @@ impl NetworkRunnable for Cmd { print.infoln("Simulating deploy transaction…"); let txn = simulate_and_assemble_transaction(&client, &txn).await?; - let txn = self.fee.apply_to_assembled_txn(txn).transaction().clone(); + let txn = Box::new(self.fee.apply_to_assembled_txn(txn).transaction().clone()); if self.fee.sim_only { print.checkln("Done!"); @@ -293,7 +293,7 @@ impl NetworkRunnable for Cmd { print.log_transaction(&txn, &network, true)?; let get_txn_resp = client - .send_transaction_polling(&config.sign_with_local_key(txn).await?) + .send_transaction_polling(&config.sign_with_local_key(*txn).await?) .await? .try_into()?; diff --git a/cmd/soroban-cli/src/commands/contract/extend.rs b/cmd/soroban-cli/src/commands/contract/extend.rs index 6ec8ebdb1..e56cbe166 100644 --- a/cmd/soroban-cli/src/commands/contract/extend.rs +++ b/cmd/soroban-cli/src/commands/contract/extend.rs @@ -140,7 +140,7 @@ impl NetworkRunnable for Cmd { .await?; let sequence: i64 = account_details.seq_num.into(); - let tx = Transaction { + let tx = Box::new(Transaction { source_account, fee: self.fee.fee, seq_num: SequenceNumber(sequence + 1), @@ -167,7 +167,7 @@ impl NetworkRunnable for Cmd { }, resource_fee: 0, }), - }; + }); if self.fee.build_only { return Ok(TxnResult::Txn(tx)); } diff --git a/cmd/soroban-cli/src/commands/contract/install.rs b/cmd/soroban-cli/src/commands/contract/install.rs index a215a987d..0a9ec856d 100644 --- a/cmd/soroban-cli/src/commands/contract/install.rs +++ b/cmd/soroban-cli/src/commands/contract/install.rs @@ -146,7 +146,7 @@ impl NetworkRunnable for Cmd { build_install_contract_code_tx(&contract, sequence + 1, self.fee.fee, &source_account)?; if self.fee.build_only { - return Ok(TxnResult::Txn(tx_without_preflight)); + return Ok(TxnResult::Txn(Box::new(tx_without_preflight))); } // Don't check whether the contract is already installed when the user @@ -186,7 +186,7 @@ impl NetworkRunnable for Cmd { print.infoln("Simulating install transaction…"); let txn = simulate_and_assemble_transaction(&client, &tx_without_preflight).await?; - let txn = self.fee.apply_to_assembled_txn(txn).transaction().clone(); + let txn = Box::new(self.fee.apply_to_assembled_txn(txn).transaction().clone()); if self.fee.sim_only { return Ok(TxnResult::Txn(txn)); @@ -195,7 +195,7 @@ impl NetworkRunnable for Cmd { print.globeln("Submitting install transaction…"); let txn_resp = client - .send_transaction_polling(&self.config.sign_with_local_key(txn).await?) + .send_transaction_polling(&self.config.sign_with_local_key(*txn).await?) .await?; if args.map_or(true, |a| !a.no_cache) { diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index 04eeaebd6..c7b631343 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -25,10 +25,10 @@ use crate::{ print, rpc, xdr::{ self, AccountEntry, AccountEntryExt, AccountId, ContractEvent, ContractEventType, - DiagnosticEvent, HostFunction, InvokeContractArgs, InvokeHostFunctionOp, LedgerEntryData, - Limits, Memo, MuxedAccount, Operation, OperationBody, Preconditions, PublicKey, - ScSpecEntry, SequenceNumber, String32, StringM, Thresholds, Transaction, TransactionExt, - Uint256, VecM, WriteXdr, + DiagnosticEvent, HostFunction, InvokeContractArgs, InvokeHostFunctionOp, Limits, Memo, + MuxedAccount, Operation, OperationBody, Preconditions, PublicKey, ScSpecEntry, + SequenceNumber, String32, StringM, Thresholds, Transaction, TransactionExt, Uint256, VecM, + WriteXdr, }, Pwd, }; @@ -93,8 +93,6 @@ pub enum Error { ParseIntError(#[from] ParseIntError), #[error(transparent)] Rpc(#[from] rpc::Error), - #[error("unexpected contract code data type: {0:?}")] - UnexpectedContractCodeDataType(LedgerEntryData), #[error("missing operation result")] MissingOperationResult, #[error("error loading signing key: {0}")] @@ -258,21 +256,22 @@ impl NetworkRunnable for Cmd { let sequence: i64 = account_details.seq_num.into(); let AccountId(PublicKey::PublicKeyTypeEd25519(account_id)) = account_details.account_id; - let tx = build_invoke_contract_tx( + let tx = Box::new(build_invoke_contract_tx( host_function_params.clone(), sequence + 1, self.fee.fee, account_id, - )?; + )?); if self.fee.build_only { return Ok(TxnResult::Txn(tx)); } let txn = simulate_and_assemble_transaction(&client, &tx).await?; - let txn = self.fee.apply_to_assembled_txn(txn); + let assembled = self.fee.apply_to_assembled_txn(txn); + let mut txn = Box::new(assembled.transaction().clone()); if self.fee.sim_only { - return Ok(TxnResult::Txn(txn.transaction().clone())); + return Ok(TxnResult::Txn(txn)); } - let sim_res = txn.sim_response(); + let sim_res = assembled.sim_response(); if global_args.map_or(true, |a| !a.no_cache) { data::write(sim_res.clone().into(), &network.rpc_uri()?)?; } @@ -281,12 +280,11 @@ impl NetworkRunnable for Cmd { ShouldSend::Yes => { let global::Args { no_cache, .. } = global_args.cloned().unwrap_or_default(); // Need to sign all auth entries - let mut txn = txn.transaction().clone(); if let Some(tx) = config.sign_soroban_authorizations(&txn, &signers).await? { - txn = tx; + txn = Box::new(tx); } let res = client - .send_transaction_polling(&config.sign_with_local_key(txn).await?) + .send_transaction_polling(&config.sign_with_local_key(*txn).await?) .await?; if !no_cache { data::write(res.clone().try_into()?, &network.rpc_uri()?)?; diff --git a/cmd/soroban-cli/src/commands/contract/restore.rs b/cmd/soroban-cli/src/commands/contract/restore.rs index 92fc4b41d..cb35e6304 100644 --- a/cmd/soroban-cli/src/commands/contract/restore.rs +++ b/cmd/soroban-cli/src/commands/contract/restore.rs @@ -141,7 +141,7 @@ impl NetworkRunnable for Cmd { .await?; let sequence: i64 = account_details.seq_num.into(); - let tx = Transaction { + let tx = Box::new(Transaction { source_account, fee: self.fee.fee, seq_num: SequenceNumber(sequence + 1), @@ -167,12 +167,12 @@ impl NetworkRunnable for Cmd { }, resource_fee: 0, }), - }; + }); if self.fee.build_only { return Ok(TxnResult::Txn(tx)); } let res = client - .send_transaction_polling(&config.sign_with_local_key(tx).await?) + .send_transaction_polling(&config.sign_with_local_key(*tx).await?) .await?; if args.map_or(true, |a| !a.no_cache) { data::write(res.clone().try_into()?, &network.rpc_uri()?)?; diff --git a/cmd/soroban-cli/src/commands/tx/args.rs b/cmd/soroban-cli/src/commands/tx/args.rs index fc99b9591..1da1f230a 100644 --- a/cmd/soroban-cli/src/commands/tx/args.rs +++ b/cmd/soroban-cli/src/commands/tx/args.rs @@ -87,7 +87,7 @@ impl Args { let network = self.config.get_network()?; let client = Client::new(&network.rpc_url)?; if self.fee.build_only { - return Ok(TxnEnvelopeResult::TxnEnvelope(tx.into())); + return Ok(TxnEnvelopeResult::TxnEnvelope(Box::new(tx.into()))); } let txn_resp = client diff --git a/cmd/soroban-cli/src/commands/txn_result.rs b/cmd/soroban-cli/src/commands/txn_result.rs index d6b308b3a..568fd79d2 100644 --- a/cmd/soroban-cli/src/commands/txn_result.rs +++ b/cmd/soroban-cli/src/commands/txn_result.rs @@ -2,7 +2,7 @@ use crate::xdr::{Transaction, TransactionEnvelope, TransactionV1Envelope, VecM}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum TxnResult { - Txn(Transaction), + Txn(Box), Res(R), } @@ -16,12 +16,12 @@ impl TxnResult { pub fn to_envelope(self) -> TxnEnvelopeResult { match self { - TxnResult::Txn(tx) => { - TxnEnvelopeResult::TxnEnvelope(TransactionEnvelope::Tx(TransactionV1Envelope { - tx, + TxnResult::Txn(tx) => TxnEnvelopeResult::TxnEnvelope(Box::new( + TransactionEnvelope::Tx(TransactionV1Envelope { + tx: *tx, signatures: VecM::default(), - })) - } + }), + )), TxnResult::Res(res) => TxnEnvelopeResult::Res(res), } } @@ -29,6 +29,6 @@ impl TxnResult { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum TxnEnvelopeResult { - TxnEnvelope(TransactionEnvelope), + TxnEnvelope(Box), Res(R), } diff --git a/cmd/soroban-cli/src/wasm.rs b/cmd/soroban-cli/src/wasm.rs index a907e021a..30f7a3e4a 100644 --- a/cmd/soroban-cli/src/wasm.rs +++ b/cmd/soroban-cli/src/wasm.rs @@ -42,7 +42,7 @@ pub enum Error { #[error(transparent)] Rpc(#[from] soroban_rpc::Error), #[error("unexpected contract data {0:?}")] - UnexpectedContractToken(ContractDataEntry), + UnexpectedContractToken(Box), #[error( "cannot fetch wasm for contract because the contract is \ a network built-in asset contract that does not have a downloadable code binary" @@ -136,5 +136,5 @@ pub async fn fetch_from_contract( ContractExecutable::StellarAsset => Err(ContractIsStellarAsset), }; } - Err(UnexpectedContractToken(data_entry)) + Err(UnexpectedContractToken(Box::new(data_entry))) } From 11cde0c0c084ddc984cb9a346cacb97fcfb0b598 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Tue, 19 Nov 2024 11:05:00 -0800 Subject: [PATCH 41/77] Fix attestation order. (#1744) --- .github/workflows/binaries.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 985f91fa5..c008cc7b4 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -133,18 +133,18 @@ jobs: $Env:STELLAR_CLI_VERSION = "${{ env.VERSION }}" ISCC.exe installer.iss - - name: Build provenance for attestation (release only) - if: github.event_name == 'release' - uses: actions/attest-build-provenance@v1 - with: - subject-path: ${{ env.STELLAR_CLI_INSTALLER }} - - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: ${{ env.STELLAR_CLI_INSTALLER }} path: Output/stellar-installer.exe + - name: Build provenance for attestation (release only) + if: github.event_name == 'release' + uses: actions/attest-build-provenance@v1 + with: + subject-path: ${{ env.STELLAR_CLI_INSTALLER }} + - name: Upload to Release (release only) if: github.event_name == 'release' uses: actions/github-script@v7 From 9853a7739a619b5a7555bfa7aeab45818d723c3b Mon Sep 17 00:00:00 2001 From: Dmitry <98899785+mdqst@users.noreply.github.com> Date: Wed, 20 Nov 2024 01:25:12 +0300 Subject: [PATCH 42/77] Fix Typo in "Setting up development environment" Section of Documentation (#1743) --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 21b38392b..7c54767c6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ changes quickly. ## Setting up development environment -There are 2 ways to being developing stellar-cli: +There are 2 ways to begin developing stellar-cli: ### Installing all required dependencies From eebf0ffd82a653446468c0b455af498fd1feeb36 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 21 Nov 2024 15:59:40 -0500 Subject: [PATCH 43/77] fix(change trust): default limit to i64::Max (#1729) --- FULL_HELP_DOCS.md | 2 +- cmd/soroban-cli/src/commands/tx/new/change_trust.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index f007d0bf4..1ba366ac0 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1624,7 +1624,7 @@ Creates, updates, or deletes a trustline Learn more about trustlines https://dev * `--line ` * `--limit ` — Limit for the trust line, 0 to remove the trust line - Default value: `18446744073709551615` + Default value: `9223372036854775807` diff --git a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs index 1ea4e737e..da9acc8cf 100644 --- a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs +++ b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs @@ -10,7 +10,7 @@ pub struct Cmd { #[arg(long)] pub line: builder::Asset, /// Limit for the trust line, 0 to remove the trust line - #[arg(long, default_value = u64::MAX.to_string())] + #[arg(long, default_value = i64::MAX.to_string())] pub limit: i64, } From 62ce556cfb54f085a43f3de7da2e5a6f3a996a72 Mon Sep 17 00:00:00 2001 From: "Thomas M. DuBuisson" Date: Thu, 21 Nov 2024 14:00:56 -0800 Subject: [PATCH 44/77] Add tx hash at the top of the send command (#1747) Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Co-authored-by: Nando Vieira --- cmd/soroban-cli/src/commands/tx/send.rs | 11 ++++++++++- flake.nix | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cmd/soroban-cli/src/commands/tx/send.rs b/cmd/soroban-cli/src/commands/tx/send.rs index 22fbc860a..1e542eb6f 100644 --- a/cmd/soroban-cli/src/commands/tx/send.rs +++ b/cmd/soroban-cli/src/commands/tx/send.rs @@ -1,3 +1,4 @@ +use crate::{print::Print, utils::transaction_hash}; use async_trait::async_trait; use soroban_rpc::GetTransactionResponse; @@ -46,7 +47,7 @@ impl NetworkRunnable for Cmd { type Result = GetTransactionResponse; async fn run_against_rpc_server( &self, - _: Option<&global::Args>, + globals: Option<&global::Args>, config: Option<&config::Args>, ) -> Result { let network = if let Some(config) = config { @@ -56,6 +57,14 @@ impl NetworkRunnable for Cmd { }; let client = network.rpc_client()?; let tx_env = super::xdr::tx_envelope_from_stdin()?; + + if let Ok(Ok(hash)) = super::xdr::unwrap_envelope_v1(tx_env.clone()) + .map(|tx| transaction_hash(&tx, &network.network_passphrase)) + { + let print = Print::new(globals.map_or(false, |g| g.quiet)); + print.infoln(format!("Transaction Hash: {}", hex::encode(hash))); + } + Ok(client.send_transaction_polling(&tx_env).await?) } } diff --git a/flake.nix b/flake.nix index 0a30ea556..8e5ace887 100644 --- a/flake.nix +++ b/flake.nix @@ -36,8 +36,8 @@ }; cargoLock.outputHashes = { - # The only git+https dependency in Cargo.lock - "stellar-rpc-client-21.4.0" = "sha256-ue7Ynux9YaDP3f/XkHz2OPd2g0iCX5R0yS5SaVHEYxQ"; + # This is needed for any git+https dependency in Cargo.lock + # "somepackage-1.2.3" = "sha256-somehash"; }; doCheck = false; From 506cf2e1d4e7dcd3ee2df00fbd49113cea55a6c0 Mon Sep 17 00:00:00 2001 From: Olexandr88 Date: Mon, 25 Nov 2024 07:16:10 +0200 Subject: [PATCH 45/77] docs: readme (#1752) Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8ba1f052..e60d71813 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Stellar CLI (stellar-cli) -![Apache 2.0 licensed](https://img.shields.io/badge/license-apache%202.0-blue.svg) +[![Apache 2.0 licensed](https://img.shields.io/badge/license-apache%202.0-blue.svg)](LICENSE) [![Crates.io Version](https://img.shields.io/crates/v/stellar-cli?label=version&color=04ac5b)](https://crates.io/crates/stellar-cli) This repo is home to the Stellar CLI, the command-line multi-tool for running and deploying Stellar contracts on the Stellar network. From a0d3fa44c3c27c95040d3d6a4c3ec2cf7f25595a Mon Sep 17 00:00:00 2001 From: Gleb Date: Sun, 24 Nov 2024 23:03:53 -0800 Subject: [PATCH 46/77] Add test to reproduce #1694 (#1727) Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- .../tests/fixtures/workspace/Cargo.lock | 89 ++++++++++++------- cmd/crates/soroban-test/tests/it/build.rs | 55 +++++++++--- 2 files changed, 102 insertions(+), 42 deletions(-) diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace/Cargo.lock b/cmd/crates/soroban-test/tests/fixtures/workspace/Cargo.lock index cc4bfbb58..ec70d9ccb 100644 --- a/cmd/crates/soroban-test/tests/fixtures/workspace/Cargo.lock +++ b/cmd/crates/soroban-test/tests/fixtures/workspace/Cargo.lock @@ -355,7 +355,6 @@ dependencies = [ "elliptic-curve", "rfc6979", "signature", - "spki", ] [[package]] @@ -370,15 +369,16 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7277392b266383ef8396db7fdeb1e77b6c52fed775f5df15bb24f35b72156980" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", "rand_core", "serde", "sha2", + "subtle", "zeroize", ] @@ -400,7 +400,6 @@ dependencies = [ "ff", "generic-array", "group", - "pkcs8", "rand_core", "sec1", "subtle", @@ -614,9 +613,7 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", - "once_cell", "sha2", - "signature", ] [[package]] @@ -717,6 +714,18 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "paste" version = "1.0.14" @@ -761,6 +770,15 @@ dependencies = [ "syn", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro2" version = "1.0.69" @@ -849,7 +867,6 @@ dependencies = [ "base16ct", "der", "generic-array", - "pkcs8", "subtle", "zeroize", ] @@ -959,9 +976,9 @@ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "soroban-builtin-sdk-macros" -version = "20.3.0" +version = "21.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc32c6e817f3ca269764ec0d7d14da6210b74a5bf14d4e745aa3ee860558900" +checksum = "2f57a68ef8777e28e274de0f3a88ad9a5a41d9a2eb461b4dd800b086f0e83b80" dependencies = [ "itertools", "proc-macro2", @@ -971,9 +988,9 @@ dependencies = [ [[package]] name = "soroban-env-common" -version = "20.3.0" +version = "21.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c14e18d879c520ff82612eaae0590acaf6a7f3b977407e1abb1c9e31f94c7814" +checksum = "2fd1c89463835fe6da996318156d39f424b4f167c725ec692e5a7a2d4e694b3d" dependencies = [ "arbitrary", "crate-git-revision", @@ -985,13 +1002,14 @@ dependencies = [ "soroban-wasmi", "static_assertions", "stellar-xdr", + "wasmparser", ] [[package]] name = "soroban-env-guest" -version = "20.3.0" +version = "21.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5122ca2abd5ebcc1e876a96b9b44f87ce0a0e06df8f7c09772ddb58b159b7454" +checksum = "6bfb2536811045d5cd0c656a324cbe9ce4467eb734c7946b74410d90dea5d0ce" dependencies = [ "soroban-env-common", "static_assertions", @@ -999,13 +1017,16 @@ dependencies = [ [[package]] name = "soroban-env-host" -version = "20.3.0" +version = "21.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "114a0fa0d0cc39d0be16b1ee35b6e5f4ee0592ddcf459bde69391c02b03cf520" +checksum = "2b7a32c28f281c423189f1298960194f0e0fc4eeb72378028171e556d8cd6160" dependencies = [ "backtrace", "curve25519-dalek", + "ecdsa", "ed25519-dalek", + "elliptic-curve", + "generic-array", "getrandom", "hex-literal", "hmac", @@ -1013,8 +1034,10 @@ dependencies = [ "num-derive", "num-integer", "num-traits", + "p256", "rand", "rand_chacha", + "sec1", "sha2", "sha3", "soroban-builtin-sdk-macros", @@ -1022,13 +1045,14 @@ dependencies = [ "soroban-wasmi", "static_assertions", "stellar-strkey", + "wasmparser", ] [[package]] name = "soroban-env-macros" -version = "20.3.0" +version = "21.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13e3f8c86f812e0669e78fcb3eae40c385c6a9dd1a4886a1de733230b4fcf27" +checksum = "242926fe5e0d922f12d3796cd7cd02dd824e5ef1caa088f45fce20b618309f64" dependencies = [ "itertools", "proc-macro2", @@ -1041,9 +1065,9 @@ dependencies = [ [[package]] name = "soroban-ledger-snapshot" -version = "20.5.0" +version = "21.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a54708f44890e0546180db6b4f530e2a88d83b05a9b38a131caa21d005e25a" +checksum = "43793d5deb5fc27c3e14e036e24cb3afcf7d1e2a172d9166e37f3d174b928749" dependencies = [ "serde", "serde_json", @@ -1055,9 +1079,9 @@ dependencies = [ [[package]] name = "soroban-sdk" -version = "20.5.0" +version = "21.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84fc8be9068dd4e0212d8b13ad61089ea87e69ac212c262914503a961c8dc3a3" +checksum = "69e39bf9e8ab05579c836e8e5be5f2f4c5ba75e7337ece20e975e82fc3a9d41e" dependencies = [ "arbitrary", "bytes-lit", @@ -1075,9 +1099,9 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "20.5.0" +version = "21.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db20def4ead836663633f58d817d0ed8e1af052c9650a04adf730525af85b964" +checksum = "a9ad528a770ec7adb524635d855b424ae2fd4fef04fb702bb0ab466a4c354d78" dependencies = [ "crate-git-revision", "darling", @@ -1095,9 +1119,9 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "20.5.0" +version = "21.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eefeb5d373b43f6828145d00f0c5cc35e96db56a6671ae9614f84beb2711cab" +checksum = "5b262c82d840552f71ee9254f2e928622fd803bd4df4815e65f73f73efc2fa9c" dependencies = [ "base64 0.13.1", "stellar-xdr", @@ -1107,9 +1131,9 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "20.5.0" +version = "21.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3152bca4737ef734ac37fe47b225ee58765c9095970c481a18516a2b287c7a33" +checksum = "85a061820c2dd0bd3ece9411e0dd3aeb6ed9ca2b7d64270eda9e798c3b6dec5f" dependencies = [ "prettyplease", "proc-macro2", @@ -1169,9 +1193,9 @@ dependencies = [ [[package]] name = "stellar-xdr" -version = "20.1.0" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e59cdf3eb4467fb5a4b00b52e7de6dca72f67fac6f9b700f55c95a5d86f09c9d" +checksum = "2675a71212ed39a806e415b0dbf4702879ff288ec7f5ee996dda42a135512b50" dependencies = [ "arbitrary", "base64 0.13.1", @@ -1353,11 +1377,12 @@ dependencies = [ [[package]] name = "wasmparser" -version = "0.88.0" +version = "0.116.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8cf7dd82407fe68161bedcd57fde15596f32ebf6e9b3bdbf3ae1da20e38e5e" +checksum = "a58e28b80dd8340cb07b8242ae654756161f6fc8d0038123d679b7b99964fa50" dependencies = [ - "indexmap 1.9.3", + "indexmap 2.1.0", + "semver", ] [[package]] diff --git a/cmd/crates/soroban-test/tests/it/build.rs b/cmd/crates/soroban-test/tests/it/build.rs index 925d88df1..cb63ae907 100644 --- a/cmd/crates/soroban-test/tests/it/build.rs +++ b/cmd/crates/soroban-test/tests/it/build.rs @@ -1,5 +1,8 @@ use predicates::prelude::predicate; +use soroban_cli::xdr::{Limited, Limits, ReadXdr, ScMetaEntry, ScMetaV0}; +use soroban_spec_tools::contract::Spec; use soroban_test::TestEnv; +use std::io::Cursor; #[test] fn build_all() { @@ -135,18 +138,50 @@ fn build_with_metadata() { .assert() .success(); - // verify that the metadata added in the contract code via contractmetadata! macro is present - // as well as the meta that is included on build - let wasm_path = fixture_path.join(&outdir).join("add.wasm"); sandbox .new_assert_cmd("contract") .current_dir(&fixture_path) - .arg("info") - .arg("meta") - .arg("--wasm") - .arg(wasm_path) + .arg("build") + .arg("--meta") + .arg("meta_replaced=some_new_meta") + .arg("--out-dir") + .arg(&outdir) .assert() - .success() - .stdout(predicate::str::contains("Description: A test add contract")) - .stdout(predicate::str::contains("contract meta: added on build")); + .success(); + + // verify that the metadata added in the contract code via contractmetadata! macro is present + // as well as the meta that is included on build + let wasm_path = fixture_path.join(&outdir).join("add.wasm"); + let wasm = std::fs::read(wasm_path).unwrap(); + let spec = Spec::new(&wasm).unwrap(); + let meta = spec.meta_base64.unwrap(); + let entries = ScMetaEntry::read_xdr_base64_iter(&mut Limited::new( + Cursor::new(meta.as_bytes()), + Limits::none(), + )) + .filter(|entry| match entry { + // Ignore the meta entries that the SDK embeds that capture the SDK and + // Rust version, since these will change often and are not really + // relevant to this test. + Ok(ScMetaEntry::ScMetaV0(ScMetaV0 { key, .. })) => { + let key = key.to_string(); + !matches!(key.as_str(), "rsver" | "rssdkver") + } + _ => true, + }) + .collect::, _>>() + .unwrap(); + + let expected_entries = vec![ + ScMetaEntry::ScMetaV0(ScMetaV0 { + key: "Description".try_into().unwrap(), + val: "A test add contract".try_into().unwrap(), + }), + ScMetaEntry::ScMetaV0(ScMetaV0 { + key: "meta_replaced".try_into().unwrap(), + val: "some_new_meta".try_into().unwrap(), + }), + ]; + + assert_eq!(entries, expected_entries); } From 670b370286d019930bb5e6a943566d558af58f38 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 26 Nov 2024 06:37:58 +1000 Subject: [PATCH 47/77] Ignore derivative unmaintained advisory (#1756) --- deny.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deny.toml b/deny.toml index 238e91a14..ae50f65ea 100644 --- a/deny.toml +++ b/deny.toml @@ -75,7 +75,7 @@ notice = "warn" # A list of advisory IDs to ignore. Note that ignored advisories will still # output a note when they are encountered. ignore = [ - #"RUSTSEC-0000-0000", + "RUSTSEC-2024-0388", # derivative is no longer maintained, but that has no known material impact on the this repo ] # Threshold for security vulnerabilities, any vulnerability with a CVSS score # lower than the range specified will be ignored. Note that ignored advisories From 82082a056bf7aad1cef10c935a9e60c375c3d8a3 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 26 Nov 2024 07:21:28 +1000 Subject: [PATCH 48/77] Update openssl (#1755) --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89cb82cdf..d5ca20513 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2951,11 +2951,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -2983,9 +2983,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", From 97cf235b5e3ecccf65de15d7bd642d568b15e908 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 27 Nov 2024 08:14:25 +1000 Subject: [PATCH 49/77] Update futures-util and co (#1754) --- Cargo.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d5ca20513..3f8fcf4ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1636,9 +1636,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1646,9 +1646,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" @@ -1663,9 +1663,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" @@ -1697,9 +1697,9 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -1708,21 +1708,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", From a11a924d310c1602e7b579377daa3e373010ac0e Mon Sep 17 00:00:00 2001 From: Jun Luo <4catcode@gmail.com> Date: Wed, 27 Nov 2024 22:54:01 +0800 Subject: [PATCH 50/77] Add Python bindings generation command (#1761) --- FULL_HELP_DOCS.md | 9 +++++++++ .../src/commands/contract/bindings.rs | 8 ++++++++ .../src/commands/contract/bindings/python.rs | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 cmd/soroban-cli/src/commands/contract/bindings/python.rs diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 1ba366ac0..27fb7bead 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -258,6 +258,7 @@ Generate code client bindings for a contract * `json` — Generate Json Bindings * `rust` — Generate Rust bindings * `typescript` — Generate a TypeScript / JavaScript package +* `python` — Generate Python bindings @@ -306,6 +307,14 @@ Generate a TypeScript / JavaScript package +## `stellar contract bindings python` + +Generate Python bindings + +**Usage:** `stellar contract bindings python` + + + ## `stellar contract build` Build a contract from source diff --git a/cmd/soroban-cli/src/commands/contract/bindings.rs b/cmd/soroban-cli/src/commands/contract/bindings.rs index 1da946979..a91c966aa 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings.rs @@ -1,4 +1,5 @@ pub mod json; +pub mod python; pub mod rust; pub mod typescript; @@ -12,6 +13,9 @@ pub enum Cmd { /// Generate a TypeScript / JavaScript package Typescript(typescript::Cmd), + + /// Generate Python bindings + Python(python::Cmd), } #[derive(thiserror::Error, Debug)] @@ -24,6 +28,9 @@ pub enum Error { #[error(transparent)] Typescript(#[from] typescript::Error), + + #[error(transparent)] + Python(#[from] python::Error), } impl Cmd { @@ -32,6 +39,7 @@ impl Cmd { Cmd::Json(json) => json.run()?, Cmd::Rust(rust) => rust.run()?, Cmd::Typescript(ts) => ts.run().await?, + Cmd::Python(python) => python.run()?, } Ok(()) } diff --git a/cmd/soroban-cli/src/commands/contract/bindings/python.rs b/cmd/soroban-cli/src/commands/contract/bindings/python.rs new file mode 100644 index 000000000..60a3e8dcb --- /dev/null +++ b/cmd/soroban-cli/src/commands/contract/bindings/python.rs @@ -0,0 +1,19 @@ +use std::fmt::Debug; + +use clap::Parser; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd {} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("python binding generation is not implemented in the stellar-cli, but is available via the tool located here: https://github.com/lightsail-network/stellar-contract-bindings")] + NotImplemented, +} + +impl Cmd { + pub fn run(&self) -> Result<(), Error> { + Err(Error::NotImplemented) + } +} From 390c220d7674b144a710228a3b7377e4722d30e5 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 29 Nov 2024 11:16:43 -0500 Subject: [PATCH 51/77] feat: Amount type (#1758) When entering amounts users will want to use `_`s to better read what they are typing. Also with this approach we could add more complex parsing for example `1 XLM`. --- FULL_HELP_DOCS.md | 4 +-- .../tests/it/integration/tx/operations.rs | 2 +- .../src/commands/tx/new/create_account.rs | 8 ++--- .../src/commands/tx/new/payment.rs | 6 ++-- cmd/soroban-cli/src/tx/builder.rs | 2 ++ cmd/soroban-cli/src/tx/builder/amount.rs | 35 +++++++++++++++++++ 6 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 cmd/soroban-cli/src/tx/builder/amount.rs diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 27fb7bead..55e093acc 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1663,7 +1663,7 @@ Creates and funds a new account with the specified starting balance * `--destination ` — Account Id to create, e.g. `GBX...` * `--starting-balance ` — Initial balance in stroops of the account, default 1 XLM - Default value: `10000000` + Default value: `10_000_000` @@ -1722,7 +1722,7 @@ Sends an amount in a specific asset to a destination account * `--asset ` — Asset to send, default native, e.i. XLM Default value: `native` -* `--amount ` — Amount of the aforementioned asset to send +* `--amount ` — Amount of the aforementioned asset to send. e.g. `10_000_000` (1 XLM) diff --git a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs index 0a0a103e8..9988b2cdd 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -93,7 +93,7 @@ async fn payment() { "--destination", test1.as_str(), "--amount", - ONE_XLM.to_string().as_str(), + "10_000_000", ]) .assert() .success(); diff --git a/cmd/soroban-cli/src/commands/tx/new/create_account.rs b/cmd/soroban-cli/src/commands/tx/new/create_account.rs index 9cc3a62ff..2826439e9 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -1,6 +1,6 @@ use clap::{command, Parser}; -use crate::{commands::tx, xdr}; +use crate::{commands::tx, tx::builder, xdr}; #[derive(Parser, Debug, Clone)] #[group(skip)] @@ -11,15 +11,15 @@ pub struct Cmd { #[arg(long)] pub destination: xdr::AccountId, /// Initial balance in stroops of the account, default 1 XLM - #[arg(long, default_value = "10000000")] - pub starting_balance: i64, + #[arg(long, default_value = "10_000_000")] + pub starting_balance: builder::Amount, } impl From<&Cmd> for xdr::OperationBody { fn from(cmd: &Cmd) -> Self { xdr::OperationBody::CreateAccount(xdr::CreateAccountOp { destination: cmd.destination.clone(), - starting_balance: cmd.starting_balance, + starting_balance: cmd.starting_balance.into(), }) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/payment.rs b/cmd/soroban-cli/src/commands/tx/new/payment.rs index c626d9ca8..3cebfa532 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -13,9 +13,9 @@ pub struct Cmd { /// Asset to send, default native, e.i. XLM #[arg(long, default_value = "native")] pub asset: builder::Asset, - /// Amount of the aforementioned asset to send. + /// Amount of the aforementioned asset to send. e.g. `10_000_000` (1 XLM) #[arg(long)] - pub amount: i64, + pub amount: builder::Amount, } impl From<&Cmd> for xdr::OperationBody { @@ -23,7 +23,7 @@ impl From<&Cmd> for xdr::OperationBody { xdr::OperationBody::Payment(xdr::PaymentOp { destination: cmd.destination.clone(), asset: cmd.asset.clone().into(), - amount: cmd.amount, + amount: cmd.amount.into(), }) } } diff --git a/cmd/soroban-cli/src/tx/builder.rs b/cmd/soroban-cli/src/tx/builder.rs index ad22737ea..c84bb7124 100644 --- a/cmd/soroban-cli/src/tx/builder.rs +++ b/cmd/soroban-cli/src/tx/builder.rs @@ -1,6 +1,8 @@ +pub mod amount; pub mod asset; pub mod transaction; +pub use amount::Amount; pub use asset::Asset; pub use transaction::TxExt; diff --git a/cmd/soroban-cli/src/tx/builder/amount.rs b/cmd/soroban-cli/src/tx/builder/amount.rs new file mode 100644 index 000000000..d3c204f50 --- /dev/null +++ b/cmd/soroban-cli/src/tx/builder/amount.rs @@ -0,0 +1,35 @@ +use std::str::FromStr; + +#[derive(Clone, Debug, Copy)] +pub struct Amount(i64); + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error("cannot start or end with `_`: {0}")] + CannotStartOrEndWithUnderscore(String), + #[error(transparent)] + IntParse(#[from] std::num::ParseIntError), +} + +impl FromStr for Amount { + type Err = Error; + + fn from_str(value: &str) -> Result { + if value.starts_with('_') || value.ends_with('_') { + return Err(Error::CannotStartOrEndWithUnderscore(value.to_string())); + } + Ok(Self(value.replace('_', "").parse::()?)) + } +} + +impl From for i64 { + fn from(builder: Amount) -> Self { + builder.0 + } +} + +impl From<&Amount> for i64 { + fn from(builder: &Amount) -> Self { + (*builder).into() + } +} From 9b8013acb3d3c218f578638579b9a0bfad684bee Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 29 Nov 2024 18:39:21 -0500 Subject: [PATCH 52/77] fix(tx-manage-data): copy/paste error for help docs (#1763) --- FULL_HELP_DOCS.md | 2 +- cmd/soroban-cli/src/commands/tx/new/manage_data.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 55e093acc..a755ef18a 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1690,7 +1690,7 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an * `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." -* `--data-name ` — Line to change, either 4 or 12 alphanumeric characters, or "native" if not specified +* `--data-name ` — String up to 64 bytes long. If this is a new Name it will add the given name/value pair to the account. If this Name is already present then the associated value will be modified * `--data-value ` — Up to 64 bytes long hex string If not present then the existing Name will be deleted. If present then this value will be set in the `DataEntry` diff --git a/cmd/soroban-cli/src/commands/tx/new/manage_data.rs b/cmd/soroban-cli/src/commands/tx/new/manage_data.rs index e0a029f02..4f4ab480d 100644 --- a/cmd/soroban-cli/src/commands/tx/new/manage_data.rs +++ b/cmd/soroban-cli/src/commands/tx/new/manage_data.rs @@ -7,7 +7,9 @@ use crate::{commands::tx, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, - /// Line to change, either 4 or 12 alphanumeric characters, or "native" if not specified + /// String up to 64 bytes long. + /// If this is a new Name it will add the given name/value pair to the account. + /// If this Name is already present then the associated value will be modified. #[arg(long)] pub data_name: xdr::StringM<64>, /// Up to 64 bytes long hex string From 68a8b466e5859a5b875fd90795795995f82817cf Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Mon, 2 Dec 2024 13:27:53 +1000 Subject: [PATCH 53/77] Add bitflags to deny and mark deny ban and licenses as required (#1753) --- .github/workflows/rust.yml | 2 +- deny.toml | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 595e6e817..f3c9b1920 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -36,7 +36,7 @@ jobs: fail-fast: false matrix: check: [advisories, bans, licenses, sources] - continue-on-error: ${{ matrix.check == 'advisories' || matrix.check == 'bans' || matrix.check == 'licenses' }} + continue-on-error: ${{ matrix.check == 'advisories' }} steps: - uses: actions/checkout@v3 - uses: EmbarkStudios/cargo-deny-action@b01e7a8cfb1f496c52d77361e84c1840d8246393 diff --git a/deny.toml b/deny.toml index ae50f65ea..9817c3e79 100644 --- a/deny.toml +++ b/deny.toml @@ -308,9 +308,7 @@ skip = [ # testcontainers { crate = "idna", reason = "temp", version = "0.5.0" }, - - # { name = "hashbrown", version = "=0.13.2" }, - # { name = "syn", version = "=1.0.109" }, + { crate = "bitflags", reason = "too many", version = "=1.3.2" }, ] # Similarly to `skip` allows you to skip certain crates during duplicate # detection. Unlike skip, it also includes the entire tree of transitive From 790dd3ceb2ce19a1bba59a6cadfa06987409f051 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 13:00:07 -0800 Subject: [PATCH 54/77] Bump version to 22.0.1 (#1772) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 32 +++++++++---------- Cargo.toml | 10 +++--- .../tests/fixtures/bye/Cargo.toml | 2 +- .../tests/fixtures/hello/Cargo.toml | 2 +- .../test-wasms/constructor/Cargo.toml | 2 +- .../test-wasms/custom_account/Cargo.toml | 2 +- .../test-wasms/custom_type/Cargo.toml | 2 +- .../test-wasms/hello_world/Cargo.toml | 2 +- .../tests/fixtures/test-wasms/swap/Cargo.toml | 2 +- .../fixtures/test-wasms/token/Cargo.toml | 2 +- 10 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f8fcf4ac..6789ea504 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4288,7 +4288,7 @@ dependencies = [ [[package]] name = "soroban-cli" -version = "22.0.0" +version = "22.0.1" dependencies = [ "assert_cmd", "assert_fs", @@ -4454,7 +4454,7 @@ dependencies = [ [[package]] name = "soroban-hello" -version = "0.0.0" +version = "22.0.1" [[package]] name = "soroban-ledger-snapshot" @@ -4525,7 +4525,7 @@ dependencies = [ [[package]] name = "soroban-spec-json" -version = "22.0.0" +version = "22.0.1" dependencies = [ "pretty_assertions", "serde", @@ -4555,7 +4555,7 @@ dependencies = [ [[package]] name = "soroban-spec-tools" -version = "22.0.0" +version = "22.0.1" dependencies = [ "base64 0.21.7", "ethnum", @@ -4573,7 +4573,7 @@ dependencies = [ [[package]] name = "soroban-spec-typescript" -version = "22.0.0" +version = "22.0.1" dependencies = [ "base64 0.21.7", "heck 0.4.1", @@ -4594,7 +4594,7 @@ dependencies = [ [[package]] name = "soroban-test" -version = "22.0.0" +version = "22.0.1" dependencies = [ "assert_cmd", "assert_fs", @@ -4665,18 +4665,18 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-bye" -version = "0.0.0" +version = "22.0.1" [[package]] name = "stellar-cli" -version = "22.0.0" +version = "22.0.1" dependencies = [ "soroban-cli", ] [[package]] name = "stellar-ledger" -version = "22.0.0" +version = "22.0.1" dependencies = [ "async-trait", "bollard", @@ -5023,42 +5023,42 @@ dependencies = [ [[package]] name = "test_constructor" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_account" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_types" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_hello_world" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_swap" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] [[package]] name = "test_token" -version = "0.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", "soroban-token-sdk", @@ -5066,7 +5066,7 @@ dependencies = [ [[package]] name = "test_udt" -version = "22.0.0" +version = "22.0.1" dependencies = [ "soroban-sdk", ] diff --git a/Cargo.toml b/Cargo.toml index d2572e9c0..cbfe6dd3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,24 +19,24 @@ exclude = [ ] [workspace.package] -version = "22.0.0" +version = "22.0.1" rust-version = "1.81.0" # Dependencies located in this repo: [workspace.dependencies.soroban-cli] -version = "=22.0.0" +version = "=22.0.1" path = "cmd/soroban-cli" [workspace.dependencies.soroban-spec-json] -version = "=22.0.0" +version = "=22.0.1" path = "./cmd/crates/soroban-spec-json" [workspace.dependencies.soroban-spec-typescript] -version = "22.0.0" +version = "22.0.1" path = "./cmd/crates/soroban-spec-typescript" [workspace.dependencies.soroban-spec-tools] -version = "22.0.0" +version = "22.0.1" path = "./cmd/crates/soroban-spec-tools" # Dependencies from the rs-stellar-xdr repo: diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml index deccb9c75..4756225d2 100644 --- a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stellar-bye" -version = "0.0.0" +version = "22.0.1" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml index fe7eb636a..a2fb7b15c 100644 --- a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "soroban-hello" -version = "0.0.0" +version = "22.0.1" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml index 69d8a6430..9ccbb23d0 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_constructor" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml index 765f671c6..e69dd96c9 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_account" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index b5a17c6a5..50b6d8a72 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_types" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index a13c98a39..a91a6ca62 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_hello_world" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml index 495a52d71..15c45c98e 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_swap" -version = "0.0.0" +version = "22.0.1" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml index 6456983e8..d4e7e7436 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_token" -version = "0.0.0" +version = "22.0.1" description = "Soroban standard token contract" authors = ["Stellar Development Foundation "] license = "Apache-2.0" From c940386ebb55ec5af672df3f0d24a22d4acf7f21 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Mon, 2 Dec 2024 17:09:44 -0800 Subject: [PATCH 55/77] Move windows installer once it is built. (#1773) --- .github/workflows/binaries.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index c008cc7b4..d913cf23d 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -132,12 +132,13 @@ jobs: $Env:Path += ";C:\Users\$Env:UserName\AppData\Local\Programs\Inno Setup 6" $Env:STELLAR_CLI_VERSION = "${{ env.VERSION }}" ISCC.exe installer.iss + mv Output/stellar-installer.exe ${{ env.STELLAR_CLI_INSTALLER }} - name: Upload Artifact uses: actions/upload-artifact@v4 with: name: ${{ env.STELLAR_CLI_INSTALLER }} - path: Output/stellar-installer.exe + path: ${{ env.STELLAR_CLI_INSTALLER }} - name: Build provenance for attestation (release only) if: github.event_name == 'release' From 5454d8454f3996c246bfe9d5624b54b51e6b75de Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 4 Dec 2024 08:34:17 +1000 Subject: [PATCH 56/77] Add a stale CI workflow (#1775) --- .github/workflows/stale.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 000000000..54c57da0e --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,23 @@ +name: 'Stale Issues / PRs' + +on: + workflow_dispatch: + schedule: + - cron: '0 18 * * *' # approx 9:30am daily + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v9 + with: + debug-only: false + days-before-stale: 30 + days-before-close: 30 + stale-issue-message: 'This issue is stale because it has been assigned for 30 days with no activity. It will be closed in 30 days unless the stale label is removed, and the assignee is removed or updated.' + stale-pr-message: 'This pull request is stale because it has been open for 30 days with no activity. It will be closed in 30 days unless the stale label is removed.' + stale-issue-label: stale + stale-pr-label: stale + remove-stale-when-updated: true + delete-branch: true + include-only-assigned: true From a03b1d7557251e6300b811c51f8b234f942d980a Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Wed, 4 Dec 2024 10:31:57 -0500 Subject: [PATCH 57/77] feat: add `tx op add` (#1663) Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Co-authored-by: Jane Wang --- FULL_HELP_DOCS.md | 375 ++++++++++++++---- .../tests/it/integration/hello_world.rs | 5 +- .../soroban-test/tests/it/integration/keys.rs | 9 +- .../tests/it/integration/tx/operations.rs | 98 +++++ cmd/crates/soroban-test/tests/it/main.rs | 2 +- cmd/soroban-cli/src/commands/tx/help.rs | 24 ++ cmd/soroban-cli/src/commands/tx/mod.rs | 28 +- .../src/commands/tx/new/account_merge.rs | 10 +- .../src/commands/tx/new/bump_sequence.rs | 10 +- .../src/commands/tx/new/change_trust.rs | 10 +- .../src/commands/tx/new/create_account.rs | 12 +- .../src/commands/tx/new/manage_data.rs | 10 +- cmd/soroban-cli/src/commands/tx/new/mod.rs | 62 ++- .../src/commands/tx/new/payment.rs | 12 +- .../src/commands/tx/new/set_options.rs | 12 +- .../commands/tx/new/set_trustline_flags.rs | 12 +- .../src/commands/tx/op/add/account_merge.rs | 14 + .../src/commands/tx/op/add/args.rs | 46 +++ .../src/commands/tx/op/add/bump_sequence.rs | 14 + .../src/commands/tx/op/add/change_trust.rs | 14 + .../src/commands/tx/op/add/create_account.rs | 14 + .../src/commands/tx/op/add/manage_data.rs | 14 + cmd/soroban-cli/src/commands/tx/op/add/mod.rs | 65 +++ .../src/commands/tx/op/add/payment.rs | 14 + .../src/commands/tx/op/add/set_options.rs | 14 + .../commands/tx/op/add/set_trustline_flags.rs | 14 + cmd/soroban-cli/src/commands/tx/op/mod.rs | 25 ++ cmd/soroban-cli/src/commands/tx/xdr.rs | 14 +- 28 files changed, 808 insertions(+), 145 deletions(-) create mode 100644 cmd/soroban-cli/src/commands/tx/help.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/args.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/create_account.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/mod.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/payment.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/set_options.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs create mode 100644 cmd/soroban-cli/src/commands/tx/op/mod.rs diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index a755ef18a..61686ab22 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1455,30 +1455,12 @@ Sign, Simulate, and Send transactions ###### **Subcommands:** -* `simulate` — Simulate a transaction envelope from stdin * `hash` — Calculate the hash of a transaction envelope from stdin -* `sign` — Sign a transaction envelope appending the signature to the envelope -* `send` — Send a transaction envelope to the network * `new` — Create a new transaction - - - -## `stellar tx simulate` - -Simulate a transaction envelope from stdin - -**Usage:** `stellar tx simulate [OPTIONS] --source-account ` - -###### **Options:** - -* `--rpc-url ` — RPC server endpoint -* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider -* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server -* `--network ` — Name of network to use from config -* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail -* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` -* `--global` — Use global config -* `--config-dir ` — Location of config directory, default is "." +* `operation` — Manipulate the operations in a transaction, including adding new operations +* `send` — Send a transaction envelope to the network +* `sign` — Sign a transaction envelope appending the signature to the envelope +* `simulate` — Simulate a transaction envelope from stdin @@ -1497,43 +1479,6 @@ Calculate the hash of a transaction envelope from stdin -## `stellar tx sign` - -Sign a transaction envelope appending the signature to the envelope - -**Usage:** `stellar tx sign [OPTIONS]` - -###### **Options:** - -* `--sign-with-key ` — Sign with a local key. Can be an identity (--sign-with-key alice), a secret key (--sign-with-key SC36…), or a seed phrase (--sign-with-key "kite urban…"). If using seed phrase, `--hd-path` defaults to the `0` path -* `--hd-path ` — If using a seed phrase to sign, sets which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` -* `--sign-with-lab` — Sign with https://lab.stellar.org -* `--rpc-url ` — RPC server endpoint -* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider -* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server -* `--network ` — Name of network to use from config -* `--global` — Use global config -* `--config-dir ` — Location of config directory, default is "." - - - -## `stellar tx send` - -Send a transaction envelope to the network - -**Usage:** `stellar tx send [OPTIONS]` - -###### **Options:** - -* `--rpc-url ` — RPC server endpoint -* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider -* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server -* `--network ` — Name of network to use from config -* `--global` — Use global config -* `--config-dir ` — Location of config directory, default is "." - - - ## `stellar tx new` Create a new transaction @@ -1544,12 +1489,26 @@ Create a new transaction * `account-merge` — Transfers the XLM balance of an account to another account and removes the source account from the ledger * `bump-sequence` — Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number -* `change-trust` — Creates, updates, or deletes a trustline Learn more about trustlines https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines +* `change-trust` — Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines * `create-account` — Creates and funds a new account with the specified starting balance -* `manage-data` — Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account Learn more about entries and subentries: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries +* `manage-data` — Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries * `payment` — Sends an amount in a specific asset to a destination account -* `set-options` — Set option for an account such as flags, inflation destination, signers, home domain, and master key weight Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags Learn more about the home domain: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md Learn more about signers operations and key weight: https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig -* `set-trustline-flags` — Allows issuing account to configure authorization and trustline flags to an asset The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags +* `set-options` — Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `set-trustline-flags` — Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags @@ -1609,7 +1568,9 @@ Bumps forward the sequence number of the source account to the given sequence nu ## `stellar tx new change-trust` -Creates, updates, or deletes a trustline Learn more about trustlines https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines +Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines **Usage:** `stellar tx new change-trust [OPTIONS] --source-account --line ` @@ -1669,7 +1630,9 @@ Creates and funds a new account with the specified starting balance ## `stellar tx new manage-data` -Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account Learn more about entries and subentries: https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries +Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries **Usage:** `stellar tx new manage-data [OPTIONS] --source-account --data-name ` @@ -1728,7 +1691,13 @@ Sends an amount in a specific asset to a destination account ## `stellar tx new set-options` -Set option for an account such as flags, inflation destination, signers, home domain, and master key weight Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags Learn more about the home domain: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md Learn more about signers operations and key weight: https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig **Usage:** `stellar tx new set-options [OPTIONS] --source-account ` @@ -1770,7 +1739,11 @@ Set option for an account such as flags, inflation destination, signers, home do ## `stellar tx new set-trustline-flags` -Allows issuing account to configure authorization and trustline flags to an asset The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. Learn more about flags: https://developers.stellar.org/docs/learn/glossary#flags +Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags **Usage:** `stellar tx new set-trustline-flags [OPTIONS] --source-account --trustor --asset ` @@ -1802,6 +1775,274 @@ Allows issuing account to configure authorization and trustline flags to an asse +## `stellar tx operation` + +Manipulate the operations in a transaction, including adding new operations + +**Usage:** `stellar tx operation ` + +###### **Subcommands:** + +* `add` — Add Operation to a transaction + + + +## `stellar tx operation add` + +Add Operation to a transaction + +**Usage:** `stellar tx operation add ` + +###### **Subcommands:** + +* `account-merge` — Transfers the XLM balance of an account to another account and removes the source account from the ledger +* `bump-sequence` — Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number +* `change-trust` — Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines +* `create-account` — Creates and funds a new account with the specified starting balance +* `manage-data` — Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries +* `payment` — Sends an amount in a specific asset to a destination account +* `set-options` — Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `set-trustline-flags` — Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags + + + +## `stellar tx operation add account-merge` + +Transfers the XLM balance of an account to another account and removes the source account from the ledger + +**Usage:** `stellar tx operation add account-merge [OPTIONS] --account ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--account ` — Muxed Account to merge with, e.g. `GBX...`, 'MBX...' + + + +## `stellar tx operation add bump-sequence` + +Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number + +**Usage:** `stellar tx operation add bump-sequence [OPTIONS] --bump-to ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--bump-to ` — Sequence number to bump to + + + +## `stellar tx operation add change-trust` + +Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines + +**Usage:** `stellar tx operation add change-trust [OPTIONS] --line ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--line ` +* `--limit ` — Limit for the trust line, 0 to remove the trust line + + Default value: `9223372036854775807` + + + +## `stellar tx operation add create-account` + +Creates and funds a new account with the specified starting balance + +**Usage:** `stellar tx operation add create-account [OPTIONS] --destination ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--destination ` — Account Id to create, e.g. `GBX...` +* `--starting-balance ` — Initial balance in stroops of the account, default 1 XLM + + Default value: `10_000_000` + + + +## `stellar tx operation add manage-data` + +Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries + +**Usage:** `stellar tx operation add manage-data [OPTIONS] --data-name ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--data-name ` — String up to 64 bytes long. If this is a new Name it will add the given name/value pair to the account. If this Name is already present then the associated value will be modified +* `--data-value ` — Up to 64 bytes long hex string If not present then the existing Name will be deleted. If present then this value will be set in the `DataEntry` + + + +## `stellar tx operation add payment` + +Sends an amount in a specific asset to a destination account + +**Usage:** `stellar tx operation add payment [OPTIONS] --destination --amount ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--destination ` — Account to send to, e.g. `GBX...` +* `--asset ` — Asset to send, default native, e.i. XLM + + Default value: `native` +* `--amount ` — Amount of the aforementioned asset to send. e.g. `10_000_000` (1 XLM) + + + +## `stellar tx operation add set-options` + +Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig + +**Usage:** `stellar tx operation add set-options [OPTIONS]` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--inflation-dest ` — Account of the inflation destination +* `--master-weight ` — A number from 0-255 (inclusive) representing the weight of the master key. If the weight of the master key is updated to 0, it is effectively disabled +* `--low-threshold ` — A number from 0-255 (inclusive) representing the threshold this account sets on all operations it performs that have a low threshold. https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `--med-threshold ` — A number from 0-255 (inclusive) representing the threshold this account sets on all operations it performs that have a medium threshold. https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `--high-threshold ` — A number from 0-255 (inclusive) representing the threshold this account sets on all operations it performs that have a high threshold. https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig +* `--home-domain ` — Sets the home domain of an account. See https://developers.stellar.org/docs/learn/encyclopedia/network-configuration/federation +* `--signer ` — Add, update, or remove a signer from an account +* `--signer-weight ` — Signer weight is a number from 0-255 (inclusive). The signer is deleted if the weight is 0 +* `--set-required` — When enabled, an issuer must approve an account before that account can hold its asset. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-required-0x1 +* `--set-revocable` — When enabled, an issuer can revoke an existing trustline's authorization, thereby freezing the asset held by an account. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-revocable-0x2 +* `--set-clawback-enabled` — Enables the issuing account to take back (burning) all of the asset. https://developers.stellar.org/docs/tokens/control-asset-access#clawback-enabled-0x8 +* `--set-immutable` — With this setting, none of the other authorization flags (`AUTH_REQUIRED_FLAG`, `AUTH_REVOCABLE_FLAG`) can be set, and the issuing account can't be merged. https://developers.stellar.org/docs/tokens/control-asset-access#authorization-immutable-0x4 +* `--clear-required` +* `--clear-revocable` +* `--clear-immutable` +* `--clear-clawback-enabled` + + + +## `stellar tx operation add set-trustline-flags` + +Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags + +**Usage:** `stellar tx operation add set-trustline-flags [OPTIONS] --trustor --asset ` + +###### **Options:** + +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." +* `--operation-source-account ` — Source account used for the operation +* `--trustor ` — Account to set trustline flags for +* `--asset ` — Asset to set trustline flags for +* `--set-authorize` — Signifies complete authorization allowing an account to transact freely with the asset to make and receive payments and place orders +* `--set-authorize-to-maintain-liabilities` — Denotes limited authorization that allows an account to maintain current orders but not to otherwise transact with the asset +* `--set-trustline-clawback-enabled` — Enables the issuing account to take back (burning) all of the asset. See our section on Clawbacks: https://developers.stellar.org/docs/learn/encyclopedia/transactions-specialized/clawbacks +* `--clear-authorize` +* `--clear-authorize-to-maintain-liabilities` +* `--clear-trustline-clawback-enabled` + + + +## `stellar tx send` + +Send a transaction envelope to the network + +**Usage:** `stellar tx send [OPTIONS]` + +###### **Options:** + +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `stellar tx sign` + +Sign a transaction envelope appending the signature to the envelope + +**Usage:** `stellar tx sign [OPTIONS]` + +###### **Options:** + +* `--sign-with-key ` — Sign with a local key. Can be an identity (--sign-with-key alice), a secret key (--sign-with-key SC36…), or a seed phrase (--sign-with-key "kite urban…"). If using seed phrase, `--hd-path` defaults to the `0` path +* `--hd-path ` — If using a seed phrase to sign, sets which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--sign-with-lab` — Sign with https://lab.stellar.org +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + +## `stellar tx simulate` + +Simulate a transaction envelope from stdin + +**Usage:** `stellar tx simulate [OPTIONS] --source-account ` + +###### **Options:** + +* `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider +* `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server +* `--network ` — Name of network to use from config +* `--source-account ` — Account that where transaction originates from. Alias `source`. Can be an identity (--source alice), a public key (--source GDKW...), a muxed account (--source MDA…), a secret key (--source SC36…), or a seed phrase (--source "kite urban…"). If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to sign the final transaction. In that case, trying to sign with public key will fail +* `--hd-path ` — If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." + + + ## `stellar xdr` Decode and encode XDR diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index fd38c2012..b9ed0196f 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -1,10 +1,9 @@ -use predicates::boolean::PredicateBooleanExt; use soroban_cli::{ commands::{ contract::{self, fetch}, txn_result::TxnResult, }, - config::{address::Address, locator, secret}, + config::{locator, secret}, }; use soroban_rpc::GetLatestLedgerResponse; use soroban_test::{AssertExt, TestEnv, LOCAL_NETWORK_PASSPHRASE}; @@ -19,7 +18,7 @@ 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); + let cmd = hello_world_cmd(&id, world); let res = sandbox.run_cmd_with(cmd, "").await.unwrap(); assert_eq!(res, TxnResult::Res(format!(r#"["Hello",{world:?}]"#))); } diff --git a/cmd/crates/soroban-test/tests/it/integration/keys.rs b/cmd/crates/soroban-test/tests/it/integration/keys.rs index 267a0b095..28723b3a1 100644 --- a/cmd/crates/soroban-test/tests/it/integration/keys.rs +++ b/cmd/crates/soroban-test/tests/it/integration/keys.rs @@ -3,13 +3,12 @@ use soroban_test::AssertExt; use soroban_test::TestEnv; fn pubkey_for_identity(sandbox: &TestEnv, name: &str) -> String { - let output = sandbox + sandbox .new_assert_cmd("keys") .arg("address") .arg(name) .assert() - .stdout_as_str(); - return output; + .stdout_as_str() } #[tokio::test] @@ -61,7 +60,7 @@ async fn overwrite_identity() { "error: An identity with the name 'test2' already exists", )); - assert_eq!(initial_pubkey, pubkey_for_identity(&sandbox, "test2")); + assert_eq!(initial_pubkey, pubkey_for_identity(sandbox, "test2")); sandbox .new_assert_cmd("keys") @@ -72,5 +71,5 @@ async fn overwrite_identity() { .stderr(predicate::str::contains("Overwriting identity 'test2'")) .success(); - assert_ne!(initial_pubkey, pubkey_for_identity(&sandbox, "test2")); + assert_ne!(initial_pubkey, pubkey_for_identity(sandbox, "test2")); } diff --git a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs index 9988b2cdd..1ce1f06c9 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -3,6 +3,7 @@ use soroban_cli::{ utils::contract_id_hash_from_asset, xdr::{self, ReadXdr, SequenceNumber}, }; +use soroban_rpc::LedgerEntryResult; use soroban_test::{AssertExt, TestEnv}; use crate::integration::{ @@ -30,6 +31,20 @@ fn new_account(sandbox: &TestEnv, name: &str) -> String { .stdout_as_str() } +fn gen_account_no_fund(sandbox: &TestEnv, name: &str) -> String { + sandbox + .new_assert_cmd("keys") + .args(["generate", "--no-fund", name]) + .assert() + .success(); + sandbox + .new_assert_cmd("keys") + .args(["address", name]) + .assert() + .success() + .stdout_as_str() +} + // returns test and test1 addresses fn setup_accounts(sandbox: &TestEnv) -> (String, String) { (test_address(sandbox), new_account(sandbox, "test1")) @@ -614,3 +629,86 @@ async fn issue_asset(sandbox: &TestEnv, test: &str, asset: &str, limit: u64, ini .assert() .success(); } + +#[tokio::test] +async fn multi_create_accounts() { + let sandbox = &TestEnv::new(); + let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let nums: Vec = (1..=3).collect(); + let mut accounts: Vec<(String, String)> = nums + .iter() + .map(|x| { + let name = format!("test_{x}"); + let address = gen_account_no_fund(sandbox, &name); + (name, address) + }) + .collect(); + let (_, test_99_address) = accounts.pop().unwrap(); + + let input = sandbox + .new_assert_cmd("tx") + .args([ + "new", + "create-account", + "--fee=1000000", + "--build-only", + "--destination", + &test_99_address, + ]) + .assert() + .success() + .stdout_as_str(); + + let final_tx = accounts.iter().fold(input, |tx_env, (_, address)| { + sandbox + .new_assert_cmd("tx") + .args(["op", "add", "create-account", "--destination", address]) + .write_stdin(tx_env.as_bytes()) + .assert() + .success() + .stdout_as_str() + }); + let out = sandbox + .new_assert_cmd("tx") + .arg("send") + .write_stdin( + sandbox + .new_assert_cmd("tx") + .arg("sign") + .arg("--sign-with-key=test") + .write_stdin(final_tx.as_bytes()) + .assert() + .success() + .stdout_as_str() + .as_bytes(), + ) + .assert() + .success() + .stdout_as_str(); + println!("{out}"); + let keys = accounts + .iter() + .map(|(_, address)| { + xdr::LedgerKey::Account(xdr::LedgerKeyAccount { + account_id: address.parse().unwrap(), + }) + }) + .collect::>(); + + let account = client.get_account(&test_99_address).await.unwrap(); + println!("{account:#?}"); + let entries = client.get_ledger_entries(&keys).await.unwrap(); + println!("{entries:#?}"); + entries + .entries + .unwrap() + .iter() + .for_each(|LedgerEntryResult { xdr, .. }| { + let xdr::LedgerEntryData::Account(value) = + xdr::LedgerEntryData::from_xdr_base64(xdr, xdr::Limits::none()).unwrap() + else { + panic!("Expected Account"); + }; + assert_eq!(value.balance, 10_000_000); + }); +} diff --git a/cmd/crates/soroban-test/tests/it/main.rs b/cmd/crates/soroban-test/tests/it/main.rs index 5a0b2a07f..e06c1a47d 100644 --- a/cmd/crates/soroban-test/tests/it/main.rs +++ b/cmd/crates/soroban-test/tests/it/main.rs @@ -3,7 +3,7 @@ mod build; mod config; mod help; mod init; -#[cfg(feature = "it")] +// #[cfg(feature = "it")] mod integration; mod plugin; mod util; diff --git a/cmd/soroban-cli/src/commands/tx/help.rs b/cmd/soroban-cli/src/commands/tx/help.rs new file mode 100644 index 000000000..c3d15d41d --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/help.rs @@ -0,0 +1,24 @@ +pub const ACCOUNT_MERGE:&str = "Transfers the XLM balance of an account to another account and removes the source account from the ledger"; +pub const BUMP_SEQUENCE: &str = "Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number"; +pub const CHANGE_TRUST: &str = r"Creates, updates, or deletes a trustline +Learn more about trustlines +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines"; + +pub const CREATE_ACCOUNT: &str = + "Creates and funds a new account with the specified starting balance"; +pub const MANAGE_DATA: &str = r"Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account +Learn more about entries and subentries: +https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries"; +pub const PAYMENT: &str = "Sends an amount in a specific asset to a destination account"; +pub const SET_OPTIONS: &str = r"Set option for an account such as flags, inflation destination, signers, home domain, and master key weight +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags +Learn more about the home domain: +https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md +Learn more about signers operations and key weight: +https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig"; +pub const SET_TRUSTLINE_FLAGS: &str = r"Allows issuing account to configure authorization and trustline flags to an asset +The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. +If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. +Learn more about flags: +https://developers.stellar.org/docs/learn/glossary#flags"; diff --git a/cmd/soroban-cli/src/commands/tx/mod.rs b/cmd/soroban-cli/src/commands/tx/mod.rs index c0390f92e..d9fd79faf 100644 --- a/cmd/soroban-cli/src/commands/tx/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/mod.rs @@ -2,7 +2,9 @@ use super::global; pub mod args; pub mod hash; +pub mod help; pub mod new; +pub mod op; pub mod send; pub mod sign; pub mod simulate; @@ -12,17 +14,20 @@ pub use args::Args; #[derive(Debug, clap::Subcommand)] pub enum Cmd { - /// Simulate a transaction envelope from stdin - Simulate(simulate::Cmd), /// Calculate the hash of a transaction envelope from stdin Hash(hash::Cmd), - /// Sign a transaction envelope appending the signature to the envelope - Sign(sign::Cmd), - /// Send a transaction envelope to the network - Send(send::Cmd), /// Create a new transaction #[command(subcommand)] New(new::Cmd), + /// Manipulate the operations in a transaction, including adding new operations + #[command(subcommand, visible_alias = "op")] + Operation(op::Cmd), + /// Send a transaction envelope to the network + Send(send::Cmd), + /// Sign a transaction envelope appending the signature to the envelope + Sign(sign::Cmd), + /// Simulate a transaction envelope from stdin + Simulate(simulate::Cmd), } #[derive(thiserror::Error, Debug)] @@ -32,21 +37,24 @@ pub enum Error { #[error(transparent)] New(#[from] new::Error), #[error(transparent)] - Simulate(#[from] simulate::Error), + Op(#[from] op::Error), + #[error(transparent)] + Send(#[from] send::Error), #[error(transparent)] Sign(#[from] sign::Error), #[error(transparent)] - Send(#[from] send::Error), + Simulate(#[from] simulate::Error), } impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match self { - Cmd::Simulate(cmd) => cmd.run(global_args).await?, Cmd::Hash(cmd) => cmd.run(global_args)?, Cmd::New(cmd) => cmd.run(global_args).await?, - Cmd::Sign(cmd) => cmd.run(global_args).await?, + Cmd::Operation(cmd) => cmd.run(global_args)?, Cmd::Send(cmd) => cmd.run(global_args).await?, + Cmd::Sign(cmd) => cmd.run(global_args).await?, + Cmd::Simulate(cmd) => cmd.run(global_args).await?, }; Ok(()) } diff --git a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs index ce01f5e1f..0d07fce91 100644 --- a/cmd/soroban-cli/src/commands/tx/new/account_merge.rs +++ b/cmd/soroban-cli/src/commands/tx/new/account_merge.rs @@ -7,13 +7,19 @@ use crate::{commands::tx, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// Muxed Account to merge with, e.g. `GBX...`, 'MBX...' #[arg(long)] pub account: xdr::MuxedAccount, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { xdr::OperationBody::AccountMerge(cmd.account.clone()) } } diff --git a/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs b/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs index dfb521f23..ff04e96a0 100644 --- a/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs +++ b/cmd/soroban-cli/src/commands/tx/new/bump_sequence.rs @@ -7,13 +7,19 @@ use crate::{commands::tx, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// Sequence number to bump to #[arg(long)] pub bump_to: i64, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { xdr::OperationBody::BumpSequence(xdr::BumpSequenceOp { bump_to: cmd.bump_to.into(), }) diff --git a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs index da9acc8cf..2013db75b 100644 --- a/cmd/soroban-cli/src/commands/tx/new/change_trust.rs +++ b/cmd/soroban-cli/src/commands/tx/new/change_trust.rs @@ -7,6 +7,12 @@ use crate::{commands::tx, tx::builder, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { #[arg(long)] pub line: builder::Asset, /// Limit for the trust line, 0 to remove the trust line @@ -14,8 +20,8 @@ pub struct Cmd { pub limit: i64, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { let line = match cmd.line.0.clone() { xdr::Asset::CreditAlphanum4(asset) => xdr::ChangeTrustAsset::CreditAlphanum4(asset), xdr::Asset::CreditAlphanum12(asset) => xdr::ChangeTrustAsset::CreditAlphanum12(asset), diff --git a/cmd/soroban-cli/src/commands/tx/new/create_account.rs b/cmd/soroban-cli/src/commands/tx/new/create_account.rs index 2826439e9..acdfd6e2d 100644 --- a/cmd/soroban-cli/src/commands/tx/new/create_account.rs +++ b/cmd/soroban-cli/src/commands/tx/new/create_account.rs @@ -7,16 +7,22 @@ use crate::{commands::tx, tx::builder, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// Account Id to create, e.g. `GBX...` - #[arg(long)] + #[arg(long, alias = "dest")] pub destination: xdr::AccountId, /// Initial balance in stroops of the account, default 1 XLM #[arg(long, default_value = "10_000_000")] pub starting_balance: builder::Amount, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { xdr::OperationBody::CreateAccount(xdr::CreateAccountOp { destination: cmd.destination.clone(), starting_balance: cmd.starting_balance.into(), diff --git a/cmd/soroban-cli/src/commands/tx/new/manage_data.rs b/cmd/soroban-cli/src/commands/tx/new/manage_data.rs index 4f4ab480d..30e9a36fd 100644 --- a/cmd/soroban-cli/src/commands/tx/new/manage_data.rs +++ b/cmd/soroban-cli/src/commands/tx/new/manage_data.rs @@ -7,6 +7,12 @@ use crate::{commands::tx, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// String up to 64 bytes long. /// If this is a new Name it will add the given name/value pair to the account. /// If this Name is already present then the associated value will be modified. @@ -19,8 +25,8 @@ pub struct Cmd { pub data_value: Option>, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { let data_value = cmd.data_value.clone().map(Into::into); let data_name = cmd.data_name.clone().into(); xdr::OperationBody::ManageData(xdr::ManageDataOp { diff --git a/cmd/soroban-cli/src/commands/tx/new/mod.rs b/cmd/soroban-cli/src/commands/tx/new/mod.rs index e5923f4ec..24c25995f 100644 --- a/cmd/soroban-cli/src/commands/tx/new/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/new/mod.rs @@ -2,47 +2,33 @@ use clap::Parser; use super::global; -mod account_merge; -mod bump_sequence; -mod change_trust; -mod create_account; -mod manage_data; -mod payment; -mod set_options; -mod set_trustline_flags; +pub mod account_merge; +pub mod bump_sequence; +pub mod change_trust; +pub mod create_account; +pub mod manage_data; +pub mod payment; +pub mod set_options; +pub mod set_trustline_flags; #[derive(Debug, Parser)] #[allow(clippy::doc_markdown)] pub enum Cmd { - /// Transfers the XLM balance of an account to another account and removes the source account from the ledger + #[command(about = super::help::ACCOUNT_MERGE)] AccountMerge(account_merge::Cmd), - /// Bumps forward the sequence number of the source account to the given sequence number, invalidating any transaction with a smaller sequence number + #[command(about = super::help::BUMP_SEQUENCE)] BumpSequence(bump_sequence::Cmd), - /// Creates, updates, or deletes a trustline - /// Learn more about trustlines - /// https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#trustlines + #[command(about = super::help::CHANGE_TRUST)] ChangeTrust(change_trust::Cmd), - /// Creates and funds a new account with the specified starting balance + #[command(about = super::help::CREATE_ACCOUNT)] CreateAccount(create_account::Cmd), - /// Sets, modifies, or deletes a data entry (name/value pair) that is attached to an account - /// Learn more about entries and subentries: - /// https://developers.stellar.org/docs/learn/fundamentals/stellar-data-structures/accounts#subentries + #[command(about = super::help::MANAGE_DATA)] ManageData(manage_data::Cmd), - /// Sends an amount in a specific asset to a destination account + #[command(about = super::help::PAYMENT)] Payment(payment::Cmd), - /// Set option for an account such as flags, inflation destination, signers, home domain, and master key weight - /// Learn more about flags: - /// https://developers.stellar.org/docs/learn/glossary#flags - /// Learn more about the home domain: - /// https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md - /// Learn more about signers operations and key weight: - /// https://developers.stellar.org/docs/learn/encyclopedia/security/signatures-multisig#multisig + #[command(about = super::help::SET_OPTIONS)] SetOptions(set_options::Cmd), - /// Allows issuing account to configure authorization and trustline flags to an asset - /// The Asset parameter is of the `TrustLineAsset` type. If you are modifying a trustline to a regular asset (i.e. one in a Code:Issuer format), this is equivalent to the Asset type. - /// If you are modifying a trustline to a pool share, however, this is composed of the liquidity pool's unique ID. - /// Learn more about flags: - /// https://developers.stellar.org/docs/learn/glossary#flags + #[command(about = super::help::SET_TRUSTLINE_FLAGS)] SetTrustlineFlags(set_trustline_flags::Cmd), } @@ -55,14 +41,14 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match self { - Cmd::AccountMerge(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::BumpSequence(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::ChangeTrust(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::CreateAccount(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::ManageData(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::Payment(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::SetOptions(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, - Cmd::SetTrustlineFlags(cmd) => cmd.tx.handle_and_print(cmd, global_args).await, + Cmd::AccountMerge(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::BumpSequence(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::ChangeTrust(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::CreateAccount(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::ManageData(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::Payment(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::SetOptions(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, + Cmd::SetTrustlineFlags(cmd) => cmd.tx.handle_and_print(&cmd.op, global_args).await, }?; Ok(()) } diff --git a/cmd/soroban-cli/src/commands/tx/new/payment.rs b/cmd/soroban-cli/src/commands/tx/new/payment.rs index 3cebfa532..683b2731c 100644 --- a/cmd/soroban-cli/src/commands/tx/new/payment.rs +++ b/cmd/soroban-cli/src/commands/tx/new/payment.rs @@ -7,8 +7,14 @@ use crate::{commands::tx, tx::builder, xdr}; pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +pub struct Args { /// Account to send to, e.g. `GBX...` - #[arg(long)] + #[arg(long, visible_alias = "dest")] pub destination: xdr::MuxedAccount, /// Asset to send, default native, e.i. XLM #[arg(long, default_value = "native")] @@ -18,8 +24,8 @@ pub struct Cmd { pub amount: builder::Amount, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { xdr::OperationBody::Payment(xdr::PaymentOp { destination: cmd.destination.clone(), asset: cmd.asset.clone().into(), diff --git a/cmd/soroban-cli/src/commands/tx/new/set_options.rs b/cmd/soroban-cli/src/commands/tx/new/set_options.rs index 69cd10745..77c7c0895 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_options.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_options.rs @@ -3,11 +3,17 @@ use clap::{command, Parser}; use crate::{commands::tx, xdr}; #[derive(Parser, Debug, Clone)] -#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] +pub struct Args { #[arg(long)] /// Account of the inflation destination. pub inflation_dest: Option, @@ -61,8 +67,8 @@ pub struct Cmd { pub clear_clawback_enabled: bool, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { let mut set_flags = None; let mut set_flag = |flag: xdr::AccountFlags| { *set_flags.get_or_insert(0) |= flag as u32; diff --git a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs index d9b70ecbd..482dd3a90 100644 --- a/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs +++ b/cmd/soroban-cli/src/commands/tx/new/set_trustline_flags.rs @@ -2,12 +2,18 @@ use clap::{command, Parser}; use crate::{commands::tx, tx::builder, xdr}; -#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { #[command(flatten)] pub tx: tx::Args, + #[clap(flatten)] + pub op: Args, +} + +#[derive(Debug, clap::Args, Clone)] +#[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] +pub struct Args { /// Account to set trustline flags for #[arg(long)] pub trustor: xdr::AccountId, @@ -32,8 +38,8 @@ pub struct Cmd { pub clear_trustline_clawback_enabled: bool, } -impl From<&Cmd> for xdr::OperationBody { - fn from(cmd: &Cmd) -> Self { +impl From<&Args> for xdr::OperationBody { + fn from(cmd: &Args) -> Self { let mut set_flags = 0; let mut set_flag = |flag: xdr::TrustLineFlags| set_flags |= flag as u32; diff --git a/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs b/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs new file mode 100644 index 000000000..bd643c199 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/account_merge.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::account_merge::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/args.rs b/cmd/soroban-cli/src/commands/tx/op/add/args.rs new file mode 100644 index 000000000..f1858e0b0 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/args.rs @@ -0,0 +1,46 @@ +use super::xdr::add_op; +use crate::{ + config::{address, locator}, + xdr, +}; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Address(#[from] address::Error), + #[error(transparent)] + TxXdr(#[from] super::xdr::Error), +} + +#[derive(Debug, clap::Args, Clone)] +#[group(skip)] +pub struct Args { + #[clap(flatten)] + pub locator: locator::Args, + /// Source account used for the operation + #[arg( + long, + visible_alias = "op-source", + env = "STELLAR_OPERATION_SOURCE_ACCOUNT" + )] + pub operation_source_account: Option, +} + +impl Args { + pub fn add_op( + &self, + op_body: impl Into, + tx_env: xdr::TransactionEnvelope, + ) -> Result { + let source_account = self + .operation_source_account + .as_ref() + .map(|a| a.resolve_muxed_account(&self.locator, None)) + .transpose()?; + let op = xdr::Operation { + source_account, + body: op_body.into(), + }; + Ok(add_op(tx_env, op)?) + } +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs b/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs new file mode 100644 index 000000000..907d8d2d6 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/bump_sequence.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::bump_sequence::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs b/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs new file mode 100644 index 000000000..af9afae1b --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/change_trust.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::change_trust::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs b/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs new file mode 100644 index 000000000..e30ff20a1 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/create_account.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::create_account::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs b/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs new file mode 100644 index 000000000..962233a84 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/manage_data.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::manage_data::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/mod.rs b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs new file mode 100644 index 000000000..b94fc74ce --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/mod.rs @@ -0,0 +1,65 @@ +use clap::Parser; + +use super::super::{global, help, xdr::tx_envelope_from_stdin}; +use crate::xdr::WriteXdr; + +pub(crate) use super::super::{new, xdr}; + +mod account_merge; +mod args; +mod bump_sequence; +mod change_trust; +mod create_account; +mod manage_data; +mod payment; +mod set_options; +mod set_trustline_flags; + +#[derive(Debug, Parser)] +#[allow(clippy::doc_markdown)] +pub enum Cmd { + #[command(about = help::ACCOUNT_MERGE)] + AccountMerge(account_merge::Cmd), + #[command(about = help::BUMP_SEQUENCE)] + BumpSequence(bump_sequence::Cmd), + #[command(about = help::CHANGE_TRUST)] + ChangeTrust(change_trust::Cmd), + #[command(about = help::CREATE_ACCOUNT)] + CreateAccount(create_account::Cmd), + #[command(about = help::MANAGE_DATA)] + ManageData(manage_data::Cmd), + #[command(about = help::PAYMENT)] + Payment(payment::Cmd), + #[command(about = help::SET_OPTIONS)] + SetOptions(set_options::Cmd), + #[command(about = help::SET_TRUSTLINE_FLAGS)] + SetTrustlineFlags(set_trustline_flags::Cmd), +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Args(#[from] args::Error), + #[error(transparent)] + TxXdr(#[from] super::super::xdr::Error), + #[error(transparent)] + Xdr(#[from] crate::xdr::Error), +} + +impl Cmd { + pub fn run(&self, _: &global::Args) -> Result<(), Error> { + let tx_env = tx_envelope_from_stdin()?; + let res = match self { + Cmd::AccountMerge(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::BumpSequence(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::ChangeTrust(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::CreateAccount(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::ManageData(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::Payment(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::SetOptions(cmd) => cmd.args.add_op(&cmd.op, tx_env), + Cmd::SetTrustlineFlags(cmd) => cmd.args.add_op(&cmd.op, tx_env), + }?; + println!("{}", res.to_xdr_base64(crate::xdr::Limits::none())?); + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/payment.rs b/cmd/soroban-cli/src/commands/tx/op/add/payment.rs new file mode 100644 index 000000000..d8146c91a --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/payment.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::payment::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs b/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs new file mode 100644 index 000000000..75b43124a --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/set_options.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::set_options::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs b/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs new file mode 100644 index 000000000..8ffee7a7b --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/add/set_trustline_flags.rs @@ -0,0 +1,14 @@ +use clap::{command, Parser}; + +use std::fmt::Debug; + +use super::new; + +#[derive(Parser, Debug, Clone)] +#[group(skip)] +pub struct Cmd { + #[command(flatten)] + pub args: super::args::Args, + #[command(flatten)] + pub op: new::set_trustline_flags::Args, +} diff --git a/cmd/soroban-cli/src/commands/tx/op/mod.rs b/cmd/soroban-cli/src/commands/tx/op/mod.rs new file mode 100644 index 000000000..9c38ecfd3 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/op/mod.rs @@ -0,0 +1,25 @@ +use super::global; + +pub mod add; + +#[derive(Debug, clap::Subcommand)] +pub enum Cmd { + /// Add Operation to a transaction + #[command(subcommand)] + Add(add::Cmd), +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Add(#[from] add::Error), +} + +impl Cmd { + pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { + match self { + Cmd::Add(cmd) => cmd.run(global_args)?, + }; + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/tx/xdr.rs b/cmd/soroban-cli/src/commands/tx/xdr.rs index fcacce9ac..0e6e253e6 100644 --- a/cmd/soroban-cli/src/commands/tx/xdr.rs +++ b/cmd/soroban-cli/src/commands/tx/xdr.rs @@ -3,7 +3,9 @@ use std::{ path::PathBuf, }; -use crate::xdr::{Limits, ReadXdr, Transaction, TransactionEnvelope, TransactionV1Envelope}; +use crate::xdr::{ + Limits, Operation, ReadXdr, Transaction, TransactionEnvelope, TransactionV1Envelope, +}; #[derive(Debug, thiserror::Error)] pub enum Error { @@ -17,6 +19,8 @@ pub enum Error { Io(#[from] std::io::Error), #[error("only transaction v1 is supported")] OnlyTransactionV1Supported, + #[error("too many operations, limited to 100 operations in a transaction")] + TooManyOperations, } pub fn tx_envelope_from_stdin() -> Result { @@ -36,3 +40,11 @@ pub fn unwrap_envelope_v1(tx_env: TransactionEnvelope) -> Result Result { + let mut tx = unwrap_envelope_v1(tx_env)?; + let mut ops = tx.operations.to_vec(); + ops.push(op); + tx.operations = ops.try_into().map_err(|_| Error::TooManyOperations)?; + Ok(tx.into()) +} From ba4687c13b89e3718845d78235189f21777be837 Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:46:52 -0500 Subject: [PATCH 58/77] feat(ts-bindings): Client.deploy with constructor args (#1745) - allow omiting `--contract-id` flag to `stellar contract bindings typescript` command, passing only `--wasm` instead - if no `--contract-id` is included, then the contract will not be fetched from a network, so no network information is logged in this case - this means it's possible to create TS Bindings libraries for contracts that have not yet been deployed, which makes it useful to add types for `Client.deploy` to the generated TS Bindings - add fixture example of `test_constructor` from test-wasms Co-authored-by: Willem Wyndham --- .github/workflows/bindings-ts.yml | 3 + FULL_HELP_DOCS.md | 10 +- Makefile | 6 +- .../fixtures/test_constructor/.gitignore | 2 + .../fixtures/test_constructor/README.md | 54 ++ .../fixtures/test_constructor/package.json | 17 + .../fixtures/test_constructor/src/index.ts | 90 +++ .../fixtures/test_constructor/tsconfig.json | 98 +++ .../fixtures/test_custom_types/README.md | 8 +- .../test_custom_types/dist/index.d.ts | 628 ------------------ .../fixtures/test_custom_types/dist/index.js | 97 --- .../test_custom_types/package-lock.json | 355 ---------- .../fixtures/test_custom_types/src/index.ts | 22 +- .../src/boilerplate.rs | 47 +- cmd/crates/soroban-spec-typescript/src/lib.rs | 70 +- .../src/project_template/src/index.ts | 1 + .../ts-tests/initialize.sh | 15 +- .../ts-tests/package-lock.json | 6 +- .../ts-tests/src/test-constructor-args.ts | 29 + .../commands/contract/bindings/typescript.rs | 84 ++- 20 files changed, 476 insertions(+), 1166 deletions(-) create mode 100644 cmd/crates/soroban-spec-typescript/fixtures/test_constructor/.gitignore create mode 100644 cmd/crates/soroban-spec-typescript/fixtures/test_constructor/README.md create mode 100644 cmd/crates/soroban-spec-typescript/fixtures/test_constructor/package.json create mode 100644 cmd/crates/soroban-spec-typescript/fixtures/test_constructor/src/index.ts create mode 100644 cmd/crates/soroban-spec-typescript/fixtures/test_constructor/tsconfig.json delete mode 100644 cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.d.ts delete mode 100644 cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.js delete mode 100644 cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json create mode 100644 cmd/crates/soroban-spec-typescript/ts-tests/src/test-constructor-args.ts diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index 957661c4c..9b5f767ac 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -24,6 +24,9 @@ jobs: --health-timeout 5s --health-retries 50 steps: + - uses: actions/setup-node@v4 + with: + node-version: '22.x' - uses: actions/checkout@v4 - uses: actions/cache@v4 with: diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 61686ab22..fc2a84335 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -290,20 +290,20 @@ Generate Rust bindings Generate a TypeScript / JavaScript package -**Usage:** `stellar contract bindings typescript [OPTIONS] --output-dir --contract-id ` +**Usage:** `stellar contract bindings typescript [OPTIONS] --output-dir ` ###### **Options:** -* `--wasm ` — Path to optional wasm binary +* `--wasm ` — Path to wasm file on local filesystem. You must either include this OR `--contract-id` +* `--contract-id ` — A contract ID/address on a network (if no network settings provided, Testnet will be assumed). You must either include this OR `--wasm` * `--output-dir ` — Where to place generated project * `--overwrite` — Whether to overwrite output directory if it already exists -* `--contract-id ` — The contract ID/address on the network -* `--global` — Use global config -* `--config-dir ` — Location of config directory, default is "." * `--rpc-url ` — RPC server endpoint * `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config +* `--global` — Use global config +* `--config-dir ` — Location of config directory, default is "." diff --git a/Makefile b/Makefile index 92cdacd73..7aa1832ba 100644 --- a/Makefile +++ b/Makefile @@ -71,9 +71,11 @@ publish: typescript-bindings-fixtures: build-test-wasms cargo run -- contract bindings typescript \ --wasm ./target/wasm32-unknown-unknown/test-wasms/test_custom_types.wasm \ - --contract-id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK \ - --network futurenet \ --output-dir ./cmd/crates/soroban-spec-typescript/fixtures/test_custom_types \ + --overwrite && \ + cargo run -- contract bindings typescript \ + --wasm ./target/wasm32-unknown-unknown/test-wasms/test_constructor.wasm \ + --output-dir ./cmd/crates/soroban-spec-typescript/fixtures/test_constructor \ --overwrite diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/.gitignore b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/.gitignore new file mode 100644 index 000000000..72aae85fa --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +out/ diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/README.md b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/README.md new file mode 100644 index 000000000..28bfd61c9 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/README.md @@ -0,0 +1,54 @@ +# test_constructor JS + +JS library for interacting with [Soroban](https://soroban.stellar.org/) smart contract `test_constructor` via Soroban RPC. + +This library was automatically generated by Soroban CLI using a command similar to: + +```bash +soroban contract bindings ts \ + --rpc-url INSERT_RPC_URL_HERE \ + --network-passphrase "INSERT_NETWORK_PASSPHRASE_HERE" \ + --contract-id INSERT_CONTRACT_ID_HERE \ + --output-dir ./path/to/test_constructor +``` + +The network passphrase and contract ID are exported from [index.ts](./src/index.ts) in the `networks` constant. If you are the one who generated this library and you know that this contract is also deployed to other networks, feel free to update `networks` with other valid options. This will help your contract consumers use this library more easily. + +# To publish or not to publish + +This library is suitable for publishing to NPM. You can publish it to NPM using the `npm publish` command. + +But you don't need to publish this library to NPM to use it. You can add it to your project's `package.json` using a file path: + +```json +"dependencies": { + "test_constructor": "./path/to/this/folder" +} +``` + +However, we've actually encountered [frustration](https://github.com/stellar/soroban-example-dapp/pull/117#discussion_r1232873560) using local libraries with NPM in this way. Though it seems a bit messy, we suggest generating the library directly to your `node_modules` folder automatically after each install by using a `postinstall` script. We've had the least trouble with this approach. NPM will automatically remove what it sees as erroneous directories during the `install` step, and then regenerate them when it gets to your `postinstall` step, which will keep the library up-to-date with your contract. + +```json +"scripts": { + "postinstall": "soroban contract bindings ts --rpc-url INSERT_RPC_URL_HERE --network-passphrase \"INSERT_NETWORK_PASSPHRASE_HERE\" --id INSERT_CONTRACT_ID_HERE --name test_constructor" +} +``` + +Obviously you need to adjust the above command based on the actual command you used to generate the library. + +# Use it + +Now that you have your library up-to-date and added to your project, you can import it in a file and see inline documentation for all of its exported methods: + +```js +import { Contract, networks } from "test_constructor" + +const contract = new Contract({ + ...networks.futurenet, // for example; check which networks this library exports + rpcUrl: '...', // use your own, or find one for testing at https://soroban.stellar.org/docs/reference/rpc#public-rpc-providers +}) + +contract.| +``` + +As long as your editor is configured to show JavaScript/TypeScript documentation, you can pause your typing at that `|` to get a list of all exports and inline-documentation for each. It exports a separate [async](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) function for each method in the smart contract, with documentation for each generated from the comments the contract's author included in the original source code. diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/package.json b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/package.json new file mode 100644 index 000000000..8db466c05 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/package.json @@ -0,0 +1,17 @@ +{ + "version": "0.0.0", + "name": "test_constructor", + "type": "module", + "exports": "./dist/index.js", + "typings": "dist/index.d.ts", + "scripts": { + "build": "tsc" + }, + "dependencies": { + "@stellar/stellar-sdk": "13.0.0", + "buffer": "6.0.3" + }, + "devDependencies": { + "typescript": "^5.6.2" + } +} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/src/index.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/src/index.ts new file mode 100644 index 000000000..f416e5a24 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/src/index.ts @@ -0,0 +1,90 @@ +import { Buffer } from "buffer"; +import { Address } from '@stellar/stellar-sdk'; +import { + AssembledTransaction, + Client as ContractClient, + ClientOptions as ContractClientOptions, + MethodOptions, + Result, + Spec as ContractSpec, +} from '@stellar/stellar-sdk/contract'; +import type { + u32, + i32, + u64, + i64, + u128, + i128, + u256, + i256, + Option, + Typepoint, + Duration, +} from '@stellar/stellar-sdk/contract'; +export * from '@stellar/stellar-sdk' +export * as contract from '@stellar/stellar-sdk/contract' +export * as rpc from '@stellar/stellar-sdk/rpc' + +if (typeof window !== 'undefined') { + //@ts-ignore Buffer exists + window.Buffer = window.Buffer || Buffer; +} + + + + +export const Errors = { + +} + +export interface Client { + /** + * Construct and simulate a counter transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. + * Counter value + */ + counter: (options?: { + /** + * The fee to pay for the transaction. Default: BASE_FEE + */ + fee?: number; + + /** + * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT + */ + timeoutInSeconds?: number; + + /** + * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true + */ + simulate?: boolean; + }) => Promise> + +} +export class Client extends ContractClient { + static async deploy( + /** Constructor/Initialization Args for the contract's `__constructor` method */ + {counter}: {counter: u32}, + /** Options for initalizing a Client as well as for calling a method, with extras specific to deploying. */ + options: MethodOptions & + Omit & { + /** The hash of the Wasm blob, which must already be installed on-chain. */ + wasmHash: Buffer | string; + /** Salt used to generate the contract's ID. Passed through to {@link Operation.createCustomContract}. Default: random. */ + salt?: Buffer | Uint8Array; + /** The format used to decode `wasmHash`, if it's provided as a string. */ + format?: "hex" | "base64"; + } + ): Promise> { + return ContractClient.deploy({counter}, options) + } + constructor(public readonly options: ContractClientOptions) { + super( + new ContractSpec([ "AAAAAAAAABNFeGFtcGxlIGNvbnN0cnVjdG9yAAAAAA1fX2NvbnN0cnVjdG9yAAAAAAAAAQAAAAAAAAAHY291bnRlcgAAAAAEAAAAAA==", + "AAAAAAAAAA1Db3VudGVyIHZhbHVlAAAAAAAAB2NvdW50ZXIAAAAAAAAAAAEAAAAE" ]), + options + ) + } + public readonly fromJSON = { + counter: this.txFromJSON + } +} \ No newline at end of file diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/tsconfig.json b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/tsconfig.json new file mode 100644 index 000000000..acac14220 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_constructor/tsconfig.json @@ -0,0 +1,98 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "ESNext", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "NodeNext", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "nodenext", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + // "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + // "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + /* Type Checking */ + // "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + }, + "include": [ + "src/*" + ] +} \ No newline at end of file diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md index 03f87f30b..5f90613a7 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/README.md @@ -6,9 +6,9 @@ This library was automatically generated by Soroban CLI using a command similar ```bash soroban contract bindings ts \ - --rpc-url https://rpc-futurenet.stellar.org:443 \ - --network-passphrase "Test SDF Future Network ; October 2022" \ - --contract-id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK \ + --rpc-url INSERT_RPC_URL_HERE \ + --network-passphrase "INSERT_NETWORK_PASSPHRASE_HERE" \ + --contract-id INSERT_CONTRACT_ID_HERE \ --output-dir ./path/to/test_custom_types ``` @@ -30,7 +30,7 @@ However, we've actually encountered [frustration](https://github.com/stellar/sor ```json "scripts": { - "postinstall": "soroban contract bindings ts --rpc-url https://rpc-futurenet.stellar.org:443 --network-passphrase \"Test SDF Future Network ; October 2022\" --id CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK --name test_custom_types" + "postinstall": "soroban contract bindings ts --rpc-url INSERT_RPC_URL_HERE --network-passphrase \"INSERT_NETWORK_PASSPHRASE_HERE\" --id INSERT_CONTRACT_ID_HERE --name test_custom_types" } ``` diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.d.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.d.ts deleted file mode 100644 index cd888cc04..000000000 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.d.ts +++ /dev/null @@ -1,628 +0,0 @@ -import { Buffer } from "buffer"; -import { AssembledTransaction, Client as ContractClient, ClientOptions as ContractClientOptions, Result } from '@stellar/stellar-sdk/contract'; -import type { u32, i32, i64, u128, i128, u256, i256, Option } from '@stellar/stellar-sdk/contract'; -export * from '@stellar/stellar-sdk'; -export * as contract from '@stellar/stellar-sdk/contract'; -export * as rpc from '@stellar/stellar-sdk/rpc'; -export declare const networks: { - readonly futurenet: { - readonly networkPassphrase: "Test SDF Future Network ; October 2022"; - readonly contractId: "CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK"; - }; -}; -/** - * This is from the rust doc above the struct Test - */ -export interface Test { - a: u32; - b: boolean; - c: string; -} -export type SimpleEnum = { - tag: "First"; - values: void; -} | { - tag: "Second"; - values: void; -} | { - tag: "Third"; - values: void; -}; -export declare enum RoyalCard { - Jack = 11, - Queen = 12, - King = 13 -} -export type TupleStruct = readonly [Test, SimpleEnum]; -export type ComplexEnum = { - tag: "Struct"; - values: readonly [Test]; -} | { - tag: "Tuple"; - values: readonly [TupleStruct]; -} | { - tag: "Enum"; - values: readonly [SimpleEnum]; -} | { - tag: "Asset"; - values: readonly [string, i128]; -} | { - tag: "Void"; - values: void; -}; -export declare const Errors: { - /** - * Please provide an odd number - */ - 1: { - message: string; - }; -}; -export interface Client { - /** - * Construct and simulate a hello transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - hello: ({ hello }: { - hello: string; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a woid transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - woid: (options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a val transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - val: (options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a u32_fail_on_even transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - u32_fail_on_even: ({ u32_ }: { - u32_: u32; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a u32_ transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - u32_: ({ u32_ }: { - u32_: u32; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a i32_ transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - i32_: ({ i32_ }: { - i32_: i32; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a i64_ transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - i64_: ({ i64_ }: { - i64_: i64; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a strukt_hel transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - * Example contract method which takes a struct - */ - strukt_hel: ({ strukt }: { - strukt: Test; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a strukt transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - strukt: ({ strukt }: { - strukt: Test; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a simple transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - simple: ({ simple }: { - simple: SimpleEnum; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a complex transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - complex: ({ complex }: { - complex: ComplexEnum; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a addresse transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - addresse: ({ addresse }: { - addresse: string; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a bytes transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - bytes: ({ bytes }: { - bytes: Buffer; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a bytes_n transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - bytes_n: ({ bytes_n }: { - bytes_n: Buffer; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a card transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - card: ({ card }: { - card: RoyalCard; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a boolean transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - boolean: ({ boolean }: { - boolean: boolean; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a not transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - * Negates a boolean value - */ - not: ({ boolean }: { - boolean: boolean; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a i128 transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - i128: ({ i128 }: { - i128: i128; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a u128 transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - u128: ({ u128 }: { - u128: u128; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a multi_args transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - multi_args: ({ a, b }: { - a: u32; - b: boolean; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a map transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - map: ({ map }: { - map: Map; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a vec transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - vec: ({ vec }: { - vec: Array; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a tuple transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - tuple: ({ tuple }: { - tuple: readonly [string, u32]; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a option transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - * Example of an optional argument - */ - option: ({ option }: { - option: Option; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>>; - /** - * Construct and simulate a u256 transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - u256: ({ u256 }: { - u256: u256; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a i256 transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - i256: ({ i256 }: { - i256: i256; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a string transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - string: ({ string }: { - string: string; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; - /** - * Construct and simulate a tuple_strukt transaction. Returns an `AssembledTransaction` object which will have a `result` field containing the result of the simulation. If this transaction changes contract state, you will need to call `signAndSend()` on the returned object. - */ - tuple_strukt: ({ tuple_strukt }: { - tuple_strukt: TupleStruct; - }, options?: { - /** - * The fee to pay for the transaction. Default: BASE_FEE - */ - fee?: number; - /** - * The maximum amount of time to wait for the transaction to complete. Default: DEFAULT_TIMEOUT - */ - timeoutInSeconds?: number; - /** - * Whether to automatically simulate the transaction when constructing the AssembledTransaction. Default: true - */ - simulate?: boolean; - }) => Promise>; -} -export declare class Client extends ContractClient { - readonly options: ContractClientOptions; - constructor(options: ContractClientOptions); - readonly fromJSON: { - hello: (json: string) => AssembledTransaction; - woid: (json: string) => AssembledTransaction; - val: (json: string) => AssembledTransaction; - u32_fail_on_even: (json: string) => AssembledTransaction>; - u32_: (json: string) => AssembledTransaction; - i32_: (json: string) => AssembledTransaction; - i64_: (json: string) => AssembledTransaction; - strukt_hel: (json: string) => AssembledTransaction; - strukt: (json: string) => AssembledTransaction; - simple: (json: string) => AssembledTransaction; - complex: (json: string) => AssembledTransaction; - addresse: (json: string) => AssembledTransaction; - bytes: (json: string) => AssembledTransaction; - bytes_n: (json: string) => AssembledTransaction; - card: (json: string) => AssembledTransaction; - boolean: (json: string) => AssembledTransaction; - not: (json: string) => AssembledTransaction; - i128: (json: string) => AssembledTransaction; - u128: (json: string) => AssembledTransaction; - multi_args: (json: string) => AssembledTransaction; - map: (json: string) => AssembledTransaction>; - vec: (json: string) => AssembledTransaction; - tuple: (json: string) => AssembledTransaction; - option: (json: string) => AssembledTransaction>; - u256: (json: string) => AssembledTransaction; - i256: (json: string) => AssembledTransaction; - string: (json: string) => AssembledTransaction; - tuple_strukt: (json: string) => AssembledTransaction; - }; -} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.js b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.js deleted file mode 100644 index 4286b2a68..000000000 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/dist/index.js +++ /dev/null @@ -1,97 +0,0 @@ -import { Buffer } from "buffer"; -import { Client as ContractClient, Spec as ContractSpec, } from '@stellar/stellar-sdk/contract'; -export * from '@stellar/stellar-sdk'; -export * as contract from '@stellar/stellar-sdk/contract'; -export * as rpc from '@stellar/stellar-sdk/rpc'; -if (typeof window !== 'undefined') { - //@ts-ignore Buffer exists - window.Buffer = window.Buffer || Buffer; -} -export const networks = { - futurenet: { - networkPassphrase: "Test SDF Future Network ; October 2022", - contractId: "CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK", - } -}; -export var RoyalCard; -(function (RoyalCard) { - RoyalCard[RoyalCard["Jack"] = 11] = "Jack"; - RoyalCard[RoyalCard["Queen"] = 12] = "Queen"; - RoyalCard[RoyalCard["King"] = 13] = "King"; -})(RoyalCard || (RoyalCard = {})); -export const Errors = { - /** - * Please provide an odd number - */ - 1: { message: "NumberMustBeOdd" } -}; -export class Client extends ContractClient { - options; - constructor(options) { - super(new ContractSpec(["AAAAAQAAAC9UaGlzIGlzIGZyb20gdGhlIHJ1c3QgZG9jIGFib3ZlIHRoZSBzdHJ1Y3QgVGVzdAAAAAAAAAAABFRlc3QAAAADAAAAAAAAAAFhAAAAAAAABAAAAAAAAAABYgAAAAAAAAEAAAAAAAAAAWMAAAAAAAAR", - "AAAAAgAAAAAAAAAAAAAAClNpbXBsZUVudW0AAAAAAAMAAAAAAAAAAAAAAAVGaXJzdAAAAAAAAAAAAAAAAAAABlNlY29uZAAAAAAAAAAAAAAAAAAFVGhpcmQAAAA=", - "AAAAAwAAAAAAAAAAAAAACVJveWFsQ2FyZAAAAAAAAAMAAAAAAAAABEphY2sAAAALAAAAAAAAAAVRdWVlbgAAAAAAAAwAAAAAAAAABEtpbmcAAAAN", - "AAAAAQAAAAAAAAAAAAAAC1R1cGxlU3RydWN0AAAAAAIAAAAAAAAAATAAAAAAAAfQAAAABFRlc3QAAAAAAAAAATEAAAAAAAfQAAAAClNpbXBsZUVudW0AAA==", - "AAAAAgAAAAAAAAAAAAAAC0NvbXBsZXhFbnVtAAAAAAUAAAABAAAAAAAAAAZTdHJ1Y3QAAAAAAAEAAAfQAAAABFRlc3QAAAABAAAAAAAAAAVUdXBsZQAAAAAAAAEAAAfQAAAAC1R1cGxlU3RydWN0AAAAAAEAAAAAAAAABEVudW0AAAABAAAH0AAAAApTaW1wbGVFbnVtAAAAAAABAAAAAAAAAAVBc3NldAAAAAAAAAIAAAATAAAACwAAAAAAAAAAAAAABFZvaWQ=", - "AAAABAAAAAAAAAAAAAAABUVycm9yAAAAAAAAAQAAABxQbGVhc2UgcHJvdmlkZSBhbiBvZGQgbnVtYmVyAAAAD051bWJlck11c3RCZU9kZAAAAAAB", - "AAAAAAAAAAAAAAAFaGVsbG8AAAAAAAABAAAAAAAAAAVoZWxsbwAAAAAAABEAAAABAAAAEQ==", - "AAAAAAAAAAAAAAAEd29pZAAAAAAAAAAA", - "AAAAAAAAAAAAAAADdmFsAAAAAAAAAAABAAAAAA==", - "AAAAAAAAAAAAAAAQdTMyX2ZhaWxfb25fZXZlbgAAAAEAAAAAAAAABHUzMl8AAAAEAAAAAQAAA+kAAAAEAAAAAw==", - "AAAAAAAAAAAAAAAEdTMyXwAAAAEAAAAAAAAABHUzMl8AAAAEAAAAAQAAAAQ=", - "AAAAAAAAAAAAAAAEaTMyXwAAAAEAAAAAAAAABGkzMl8AAAAFAAAAAQAAAAU=", - "AAAAAAAAAAAAAAAEaTY0XwAAAAEAAAAAAAAABGk2NF8AAAAHAAAAAQAAAAc=", - "AAAAAAAAACxFeGFtcGxlIGNvbnRyYWN0IG1ldGhvZCB3aGljaCB0YWtlcyBhIHN0cnVjdAAAAApzdHJ1a3RfaGVsAAAAAAABAAAAAAAAAAZzdHJ1a3QAAAAAB9AAAAAEVGVzdAAAAAEAAAPqAAAAEQ==", - "AAAAAAAAAAAAAAAGc3RydWt0AAAAAAABAAAAAAAAAAZzdHJ1a3QAAAAAB9AAAAAEVGVzdAAAAAEAAAfQAAAABFRlc3Q=", - "AAAAAAAAAAAAAAAGc2ltcGxlAAAAAAABAAAAAAAAAAZzaW1wbGUAAAAAB9AAAAAKU2ltcGxlRW51bQAAAAAAAQAAB9AAAAAKU2ltcGxlRW51bQAA", - "AAAAAAAAAAAAAAAHY29tcGxleAAAAAABAAAAAAAAAAdjb21wbGV4AAAAB9AAAAALQ29tcGxleEVudW0AAAAAAQAAB9AAAAALQ29tcGxleEVudW0A", - "AAAAAAAAAAAAAAAIYWRkcmVzc2UAAAABAAAAAAAAAAhhZGRyZXNzZQAAABMAAAABAAAAEw==", - "AAAAAAAAAAAAAAAFYnl0ZXMAAAAAAAABAAAAAAAAAAVieXRlcwAAAAAAAA4AAAABAAAADg==", - "AAAAAAAAAAAAAAAHYnl0ZXNfbgAAAAABAAAAAAAAAAdieXRlc19uAAAAA+4AAAAJAAAAAQAAA+4AAAAJ", - "AAAAAAAAAAAAAAAEY2FyZAAAAAEAAAAAAAAABGNhcmQAAAfQAAAACVJveWFsQ2FyZAAAAAAAAAEAAAfQAAAACVJveWFsQ2FyZAAAAA==", - "AAAAAAAAAAAAAAAHYm9vbGVhbgAAAAABAAAAAAAAAAdib29sZWFuAAAAAAEAAAABAAAAAQ==", - "AAAAAAAAABdOZWdhdGVzIGEgYm9vbGVhbiB2YWx1ZQAAAAADbm90AAAAAAEAAAAAAAAAB2Jvb2xlYW4AAAAAAQAAAAEAAAAB", - "AAAAAAAAAAAAAAAEaTEyOAAAAAEAAAAAAAAABGkxMjgAAAALAAAAAQAAAAs=", - "AAAAAAAAAAAAAAAEdTEyOAAAAAEAAAAAAAAABHUxMjgAAAAKAAAAAQAAAAo=", - "AAAAAAAAAAAAAAAKbXVsdGlfYXJncwAAAAAAAgAAAAAAAAABYQAAAAAAAAQAAAAAAAAAAWIAAAAAAAABAAAAAQAAAAQ=", - "AAAAAAAAAAAAAAADbWFwAAAAAAEAAAAAAAAAA21hcAAAAAPsAAAABAAAAAEAAAABAAAD7AAAAAQAAAAB", - "AAAAAAAAAAAAAAADdmVjAAAAAAEAAAAAAAAAA3ZlYwAAAAPqAAAABAAAAAEAAAPqAAAABA==", - "AAAAAAAAAAAAAAAFdHVwbGUAAAAAAAABAAAAAAAAAAV0dXBsZQAAAAAAA+0AAAACAAAAEQAAAAQAAAABAAAD7QAAAAIAAAARAAAABA==", - "AAAAAAAAAB9FeGFtcGxlIG9mIGFuIG9wdGlvbmFsIGFyZ3VtZW50AAAAAAZvcHRpb24AAAAAAAEAAAAAAAAABm9wdGlvbgAAAAAD6AAAAAQAAAABAAAD6AAAAAQ=", - "AAAAAAAAAAAAAAAEdTI1NgAAAAEAAAAAAAAABHUyNTYAAAAMAAAAAQAAAAw=", - "AAAAAAAAAAAAAAAEaTI1NgAAAAEAAAAAAAAABGkyNTYAAAANAAAAAQAAAA0=", - "AAAAAAAAAAAAAAAGc3RyaW5nAAAAAAABAAAAAAAAAAZzdHJpbmcAAAAAABAAAAABAAAAEA==", - "AAAAAAAAAAAAAAAMdHVwbGVfc3RydWt0AAAAAQAAAAAAAAAMdHVwbGVfc3RydWt0AAAH0AAAAAtUdXBsZVN0cnVjdAAAAAABAAAH0AAAAAtUdXBsZVN0cnVjdAA="]), options); - this.options = options; - } - fromJSON = { - hello: (this.txFromJSON), - woid: (this.txFromJSON), - val: (this.txFromJSON), - u32_fail_on_even: (this.txFromJSON), - u32_: (this.txFromJSON), - i32_: (this.txFromJSON), - i64_: (this.txFromJSON), - strukt_hel: (this.txFromJSON), - strukt: (this.txFromJSON), - simple: (this.txFromJSON), - complex: (this.txFromJSON), - addresse: (this.txFromJSON), - bytes: (this.txFromJSON), - bytes_n: (this.txFromJSON), - card: (this.txFromJSON), - boolean: (this.txFromJSON), - not: (this.txFromJSON), - i128: (this.txFromJSON), - u128: (this.txFromJSON), - multi_args: (this.txFromJSON), - map: (this.txFromJSON), - vec: (this.txFromJSON), - tuple: (this.txFromJSON), - option: (this.txFromJSON), - u256: (this.txFromJSON), - i256: (this.txFromJSON), - string: (this.txFromJSON), - tuple_strukt: (this.txFromJSON) - }; -} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json deleted file mode 100644 index a4e3759e2..000000000 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/package-lock.json +++ /dev/null @@ -1,355 +0,0 @@ -{ - "name": "test_custom_types", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "test_custom_types", - "version": "0.0.0", - "dependencies": { - "@stellar/stellar-sdk": "13.0.0", - "buffer": "6.0.3" - }, - "devDependencies": { - "typescript": "^5.6.2" - } - }, - "node_modules/@stellar/js-xdr": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@stellar/js-xdr/-/js-xdr-3.1.2.tgz", - "integrity": "sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==", - "license": "Apache-2.0" - }, - "node_modules/@stellar/stellar-base": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/@stellar/stellar-base/-/stellar-base-13.0.1.tgz", - "integrity": "sha512-Xbd12mc9Oj/130Tv0URmm3wXG77XMshZtZ2yNCjqX5ZbMD5IYpbBs3DVCteLU/4SLj/Fnmhh1dzhrQXnk4r+pQ==", - "license": "Apache-2.0", - "dependencies": { - "@stellar/js-xdr": "^3.1.2", - "base32.js": "^0.1.0", - "bignumber.js": "^9.1.2", - "buffer": "^6.0.3", - "sha.js": "^2.3.6", - "tweetnacl": "^1.0.3" - }, - "optionalDependencies": { - "sodium-native": "^4.3.0" - } - }, - "node_modules/@stellar/stellar-sdk": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-13.0.0.tgz", - "integrity": "sha512-+wvmKi+XWwu27nLYTM17EgBdpbKohEkOfCIK4XKfsI4WpMXAqvnqSm98i9h5dAblNB+w8BJqzGs1JY0PtTGm4A==", - "license": "Apache-2.0", - "dependencies": { - "@stellar/stellar-base": "^13.0.1", - "axios": "^1.7.7", - "bignumber.js": "^9.1.2", - "eventsource": "^2.0.2", - "feaxios": "^0.0.20", - "randombytes": "^2.1.0", - "toml": "^3.0.0", - "urijs": "^1.19.1" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/base32.js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", - "integrity": "sha512-n3TkB02ixgBOhTvANakDb4xaMXnYUVkNoRFJjQflcqMQhyEKxEHdj3E6N8t8sUQ0mjH/3/JxzlXuz3ul/J90pQ==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eventsource": { - "version": "2.0.2", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/feaxios": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/feaxios/-/feaxios-0.0.20.tgz", - "integrity": "sha512-g3hm2YDNffNxA3Re3Hd8ahbpmDee9Fv1Pb1C/NoWsjY7mtD8nyNeJytUzn+DK0Hyl9o6HppeWOrtnqgmhOYfWA==", - "license": "MIT", - "dependencies": { - "is-retry-allowed": "^3.0.0" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/is-retry-allowed": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-3.0.0.tgz", - "integrity": "sha512-9xH0xvoggby+u0uGF7cZXdrutWiBiaFG8ZT4YFPXL8NzkyAwX3AKGLeFQLvzDpM430+nDFBZ1LHkie/8ocL06A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.3.tgz", - "integrity": "sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw==", - "license": "MIT", - "optional": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "license": "(MIT AND BSD-3-Clause)", - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/sodium-native": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-4.3.1.tgz", - "integrity": "sha512-YdP64gAdpIKHfL4ttuX4aIfjeunh9f+hNeQJpE9C8UMndB3zkgZ7YmmGT4J2+v6Ibyp6Wem8D1TcSrtdW0bqtg==", - "license": "MIT", - "optional": true, - "dependencies": { - "node-gyp-build": "^4.8.0" - } - }, - "node_modules/toml": { - "version": "3.0.0", - "license": "MIT" - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", - "license": "Unlicense" - }, - "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/urijs": { - "version": "1.19.11", - "license": "MIT" - } - } -} diff --git a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts index 7f2d5b000..92a28ee5a 100644 --- a/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts +++ b/cmd/crates/soroban-spec-typescript/fixtures/test_custom_types/src/index.ts @@ -4,6 +4,7 @@ import { AssembledTransaction, Client as ContractClient, ClientOptions as ContractClientOptions, + MethodOptions, Result, Spec as ContractSpec, } from '@stellar/stellar-sdk/contract'; @@ -30,12 +31,7 @@ if (typeof window !== 'undefined') { } -export const networks = { - futurenet: { - networkPassphrase: "Test SDF Future Network ; October 2022", - contractId: "CBYMYMSDF6FBDNCFJCRC7KMO4REYFPOH2U4N7FXI3GJO6YXNCQ43CDSK", - } -} as const + /** @@ -631,6 +627,20 @@ export interface Client { } export class Client extends ContractClient { + static async deploy( + /** Options for initalizing a Client as well as for calling a method, with extras specific to deploying. */ + options: MethodOptions & + Omit & { + /** The hash of the Wasm blob, which must already be installed on-chain. */ + wasmHash: Buffer | string; + /** Salt used to generate the contract's ID. Passed through to {@link Operation.createCustomContract}. Default: random. */ + salt?: Buffer | Uint8Array; + /** The format used to decode `wasmHash`, if it's provided as a string. */ + format?: "hex" | "base64"; + } + ): Promise> { + return ContractClient.deploy(null, options) + } constructor(public readonly options: ContractClientOptions) { super( new ContractSpec([ "AAAAAQAAAC9UaGlzIGlzIGZyb20gdGhlIHJ1c3QgZG9jIGFib3ZlIHRoZSBzdHJ1Y3QgVGVzdAAAAAAAAAAABFRlc3QAAAADAAAAAAAAAAFhAAAAAAAABAAAAAAAAAABYgAAAAAAAAEAAAAAAAAAAWMAAAAAAAAR", diff --git a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs index 501d51434..bf5631eda 100644 --- a/cmd/crates/soroban-spec-typescript/src/boilerplate.rs +++ b/cmd/crates/soroban-spec-typescript/src/boilerplate.rs @@ -47,9 +47,9 @@ impl Project { pub fn init( &self, contract_name: &str, - contract_id: &str, - rpc_url: &str, - network_passphrase: &str, + contract_id: Option<&str>, + rpc_url: Option<&str>, + network_passphrase: Option<&str>, spec: &[ScSpecEntry], ) -> std::io::Result<()> { self.replace_placeholder_patterns(contract_name, contract_id, rpc_url, network_passphrase)?; @@ -59,9 +59,9 @@ impl Project { fn replace_placeholder_patterns( &self, contract_name: &str, - contract_id: &str, - rpc_url: &str, - network_passphrase: &str, + contract_id: Option<&str>, + rpc_url: Option<&str>, + network_passphrase: Option<&str>, ) -> std::io::Result<()> { let replacement_strings = &[ ("INSERT_CONTRACT_NAME_HERE", contract_name), @@ -73,9 +73,18 @@ impl Project { "INSERT_CAMEL_CASE_CONTRACT_NAME_HERE", &contract_name.to_lower_camel_case(), ), - ("INSERT_CONTRACT_ID_HERE", contract_id), - ("INSERT_NETWORK_PASSPHRASE_HERE", network_passphrase), - ("INSERT_RPC_URL_HERE", rpc_url), + ( + "INSERT_CONTRACT_ID_HERE", + contract_id.unwrap_or("INSERT_CONTRACT_ID_HERE"), + ), + ( + "INSERT_RPC_URL_HERE", + rpc_url.unwrap_or("INSERT_RPC_URL_HERE"), + ), + ( + "INSERT_NETWORK_PASSPHRASE_HERE", + network_passphrase.unwrap_or("INSERT_NETWORK_PASSPHRASE_HERE"), + ), ]; let root: &Path = self.as_ref(); ["package.json", "README.md", "src/index.ts"] @@ -93,8 +102,8 @@ impl Project { fn append_index_ts( &self, spec: &[ScSpecEntry], - contract_id: &str, - network_passphrase: &str, + contract_id: Option<&str>, + network_passphrase: Option<&str>, ) -> std::io::Result<()> { let networks = Project::format_networks_object(contract_id, network_passphrase); let types_and_fns = generate(spec); @@ -104,7 +113,15 @@ impl Project { .write_all(format!("\n\n{networks}\n\n{types_and_fns}").as_bytes()) } - fn format_networks_object(contract_id: &str, network_passphrase: &str) -> String { + fn format_networks_object( + contract_id: Option<&str>, + network_passphrase: Option<&str>, + ) -> String { + if contract_id.is_none() || network_passphrase.is_none() { + return String::new(); + } + let contract_id = contract_id.unwrap(); + let network_passphrase = network_passphrase.unwrap(); let network = match network_passphrase { NETWORK_PASSPHRASE_TESTNET => "testnet", NETWORK_PASSPHRASE_FUTURENET => "futurenet", @@ -138,9 +155,9 @@ mod test { let p: Project = root.as_ref().to_path_buf().try_into()?; p.init( "test_custom_types", - "CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE", - "https://rpc-futurenet.stellar.org:443", - "Test SDF Future Network ; October 2022", + Some("CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE"), + Some("https://rpc-futurenet.stellar.org:443"), + Some("Test SDF Future Network ; October 2022"), &spec, ) .unwrap(); diff --git a/cmd/crates/soroban-spec-typescript/src/lib.rs b/cmd/crates/soroban-spec-typescript/src/lib.rs index 94b5bb192..ee98a514d 100644 --- a/cmd/crates/soroban-spec-typescript/src/lib.rs +++ b/cmd/crates/soroban-spec-typescript/src/lib.rs @@ -59,7 +59,26 @@ pub fn generate_from_wasm(wasm: &[u8]) -> Result { Ok(json) } -fn generate_class(fns: &[Entry], spec: &[ScSpecEntry]) -> String { +fn generate_class( + fns: &[Entry], + constructor_args: Option>, + spec: &[ScSpecEntry], +) -> String { + let (constructor_args_in, constructor_args_out) = if let Some(inputs) = constructor_args { + let Some((args, arg_types)) = args_to_ts(&inputs) else { + panic!("inputs is present but couldn't be parsed by args_to_ts()"); + }; + ( + format!( + " + /** Constructor/Initialization Args for the contract's `__constructor` method */ + {args}: {arg_types},", + ), + args, + ) + } else { + (String::new(), "null".to_string()) + }; let method_types = fns.iter().map(entry_to_method_type).join(""); let from_jsons = fns .iter() @@ -74,6 +93,20 @@ fn generate_class(fns: &[Entry], spec: &[ScSpecEntry]) -> String { r#"export interface Client {{{method_types} }} export class Client extends ContractClient {{ + static async deploy({constructor_args_in} + /** Options for initalizing a Client as well as for calling a method, with extras specific to deploying. */ + options: MethodOptions & + Omit & {{ + /** The hash of the Wasm blob, which must already be installed on-chain. */ + wasmHash: Buffer | string; + /** Salt used to generate the contract's ID. Passed through to {{@link Operation.createCustomContract}}. Default: random. */ + salt?: Buffer | Uint8Array; + /** The format used to decode `wasmHash`, if it's provided as a string. */ + format?: "hex" | "base64"; + }} + ): Promise> {{ + return ContractClient.deploy({constructor_args_out}, options) + }} constructor(public readonly options: ContractClientOptions) {{ super( new ContractSpec([ {spec} ]), @@ -96,13 +129,20 @@ pub fn generate(spec: &[ScSpecEntry]) -> String { cases: vec![], }); } + let mut constructor_args: Option> = None; // Filter out function entries with names that start with "__" and partition the results + collected.iter().for_each(|entry| match entry { + Entry::Function { name, inputs, .. } if name == "__constructor" => { + constructor_args = Some(inputs.clone()); + } + _ => {} + }); let (fns, other): (Vec<_>, Vec<_>) = collected .into_iter() .filter(|entry| !matches!(entry, Entry::Function { name, .. } if name.starts_with("__"))) .partition(|entry| matches!(entry, Entry::Function { .. })); let top = other.iter().map(entry_to_method_type).join("\n"); - let bottom = generate_class(&fns, spec); + let bottom = generate_class(&fns, constructor_args, spec); format!("{top}\n\n{bottom}") } @@ -174,6 +214,18 @@ pub fn outputs_to_return_type(outputs: &[Type]) -> String { } } +/// Convert a function's inputs to TypeScript arguments. Returns a tuple with the arguments +/// as they'll actually be used in JS, as well as TS type definitions for the arguments. +pub fn args_to_ts(inputs: &[types::FunctionInput]) -> Option<(String, String)> { + if inputs.is_empty() { + None + } else { + let input_vals = inputs.iter().map(func_input_to_arg_name).join(", "); + let input_types = inputs.iter().map(func_input_to_ts).join(", "); + Some((format!("{{{input_vals}}}"), format!("{{{input_types}}}"))) + } +} + #[allow(clippy::too_many_lines)] pub fn entry_to_method_type(entry: &Entry) -> String { match entry { @@ -184,15 +236,11 @@ pub fn entry_to_method_type(entry: &Entry) -> String { outputs, .. } => { - let input_vals = inputs.iter().map(func_input_to_arg_name).join(", "); - let input = (!inputs.is_empty()) - .then(|| { - format!( - "{{{input_vals}}}: {{{}}}, ", - inputs.iter().map(func_input_to_ts).join(", ") - ) - }) - .unwrap_or_default(); + let input = if let Some((args, arg_types)) = args_to_ts(inputs) { + format!("{args}: {arg_types}, ") + } else { + String::new() + }; let doc = doc_to_ts_doc(doc, Some(name), 0); let return_type = outputs_to_return_type(outputs); format!( diff --git a/cmd/crates/soroban-spec-typescript/src/project_template/src/index.ts b/cmd/crates/soroban-spec-typescript/src/project_template/src/index.ts index 057d4ef72..b344a1c60 100644 --- a/cmd/crates/soroban-spec-typescript/src/project_template/src/index.ts +++ b/cmd/crates/soroban-spec-typescript/src/project_template/src/index.ts @@ -4,6 +4,7 @@ import { AssembledTransaction, Client as ContractClient, ClientOptions as ContractClientOptions, + MethodOptions, Result, Spec as ContractSpec, } from '@stellar/stellar-sdk/contract'; diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh index 031061cca..e872923c6 100755 --- a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh +++ b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh @@ -29,18 +29,21 @@ function fund_all() { exe eval "./soroban keys generate root" exe eval "./soroban keys fund root" } -function deploy() { - exe eval "(./soroban contract deploy --quiet --source root --wasm $1 --ignore-checks) > $2" +function upload() { + exe eval "(./soroban contract $1 --quiet --source root --wasm $2 --ignore-checks) > $3" } function deploy_all() { - deploy ../../../../target/wasm32-unknown-unknown/test-wasms/test_custom_types.wasm contract-id-custom-types.txt + upload deploy ../../../../target/wasm32-unknown-unknown/test-wasms/test_custom_types.wasm contract-id-custom-types.txt + # TODO: support `--wasm-hash` with `contract bindings` + upload install ../../../../target/wasm32-unknown-unknown/test-wasms/test_constructor.wasm contract-wasm-hash-constructor.txt } function bind() { - exe eval "./soroban contract bindings typescript --contract-id $(cat $1) --output-dir ./node_modules/$2 --overwrite" - exe eval "sh -c \"cd ./node_modules/$2 && npm install && npm run build\"" + exe eval "./soroban contract bindings typescript $1 $2 --output-dir ./node_modules/$3 --overwrite" + exe eval "sh -c \"cd ./node_modules/$3 && npm install && npm run build\"" } function bind_all() { - bind contract-id-custom-types.txt test-custom-types + bind --contract-id $(cat contract-id-custom-types.txt) test-custom-types + bind --wasm ../../../../target/wasm32-unknown-unknown/test-wasms/test_constructor.wasm test-constructor } fund_all diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json index 45cc97a67..786edd8ee 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json +++ b/cmd/crates/soroban-spec-typescript/ts-tests/package-lock.json @@ -2340,9 +2340,9 @@ "dev": true }, "node_modules/node-gyp-build": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.3.tgz", - "integrity": "sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", "dev": true, "license": "MIT", "optional": true, diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-constructor-args.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-constructor-args.ts new file mode 100644 index 000000000..a4f8bbfc4 --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-constructor-args.ts @@ -0,0 +1,29 @@ +import { readFileSync } from "node:fs" +import { join } from "node:path" +import test from "ava" +import { networkPassphrase, rpcUrl, root, signer } from "./util.js" +import { Client } from "test-constructor" + +const wasmHash = readFileSync( + join(import.meta.dirname, "..", "contract-wasm-hash-constructor.txt"), + { encoding: "utf8" } +); + +const INIT_VALUE = 42; + +test("has correctly-typed result", async (t) => { + const deploy = await Client.deploy( + { counter: INIT_VALUE }, + { + networkPassphrase, + rpcUrl, + allowHttp: true, + wasmHash, + publicKey: root.keypair.publicKey(), + ...signer, + }, + ); + const { result: client } = await deploy.signAndSend(); + const { result } = await client.counter(); + t.is(result, INIT_VALUE); +}); diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index 679e757f4..ea1f63eed 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -17,22 +17,22 @@ use crate::{ #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { - /// Path to optional wasm binary + /// Path to wasm file on local filesystem. You must either include this OR `--contract-id`. #[arg(long)] pub wasm: Option, + /// A contract ID/address on a network (if no network settings provided, Testnet will be assumed). You must either include this OR `--wasm`. + #[arg(long, visible_alias = "id")] + pub contract_id: Option, /// Where to place generated project #[arg(long)] pub output_dir: PathBuf, /// Whether to overwrite output directory if it already exists #[arg(long)] pub overwrite: bool, - /// The contract ID/address on the network - #[arg(long, visible_alias = "id")] - pub contract_id: String, - #[command(flatten)] - pub locator: locator::Args, #[command(flatten)] pub network: network::Args, + #[command(flatten)] + pub locator: locator::Args, } #[derive(thiserror::Error, Debug)] @@ -51,6 +51,9 @@ pub enum Error { #[error("--output-dir filepath not representable as utf-8: {0:?}")] NotUtf8(OsString), + #[error("must include either --wasm or --contract-id")] + MissingWasmOrContractId, + #[error(transparent)] Network(#[from] network::Error), @@ -84,34 +87,46 @@ impl NetworkRunnable for Cmd { ) -> Result<(), Error> { let print = Print::new(global_args.is_some_and(|a| a.quiet)); - let network = self.network.get(&self.locator).ok().unwrap_or_else(|| { - network::DEFAULTS - .get("testnet") - .expect("no network specified and testnet network not found") - .into() - }); - - let contract_id = self - .locator - .resolve_contract_id(&self.contract_id, &network.network_passphrase)? - .0; - let contract_address = ScAddress::Contract(Hash(contract_id)); - - let spec = if let Some(wasm) = &self.wasm { + let (spec, contract_address, rpc_url, network_passphrase) = if let Some(wasm) = &self.wasm { print.infoln("Loading contract spec from file..."); let wasm: wasm::Args = wasm.into(); - wasm.parse()?.spec + (wasm.parse()?.spec, None, None, None) } else { + let contract_id = self + .contract_id + .as_ref() + .ok_or(Error::MissingWasmOrContractId)?; + + let network = self.network.get(&self.locator).ok().unwrap_or_else(|| { + network::DEFAULTS + .get("testnet") + .expect("no network specified and testnet network not found") + .into() + }); + print.infoln(format!("Network: {}", network.network_passphrase)); + + let contract_id = self + .locator + .resolve_contract_id(contract_id, &network.network_passphrase)? + .0; + + let contract_address = ScAddress::Contract(Hash(contract_id)).to_string(); print.globeln(format!("Downloading contract spec: {contract_address}")); - get_remote_contract_spec( - &contract_id, - &self.locator, - &self.network, - global_args, - config, + + ( + get_remote_contract_spec( + &contract_id, + &self.locator, + &self.network, + global_args, + config, + ) + .await + .map_err(Error::from)?, + Some(contract_address), + Some(network.rpc_url), + Some(network.network_passphrase), ) - .await - .map_err(Error::from)? }; if self.output_dir.is_file() { return Err(Error::IsFile(self.output_dir.clone())); @@ -125,7 +140,6 @@ impl NetworkRunnable for Cmd { } std::fs::create_dir_all(&self.output_dir)?; let p: Project = self.output_dir.clone().try_into()?; - print.infoln(format!("Network: {}", network.network_passphrase)); let absolute_path = self.output_dir.canonicalize()?; let file_name = absolute_path .file_name() @@ -133,12 +147,14 @@ impl NetworkRunnable for Cmd { let contract_name = &file_name .to_str() .ok_or_else(|| Error::NotUtf8(file_name.to_os_string()))?; - print.infoln(format!("Embedding contract address: {contract_address}")); + if let Some(contract_address) = contract_address.clone() { + print.infoln(format!("Embedding contract address: {contract_address}")); + } p.init( contract_name, - &contract_address.to_string(), - &network.rpc_url, - &network.network_passphrase, + contract_address.as_deref(), + rpc_url.as_deref(), + network_passphrase.as_deref(), &spec, )?; print.checkln("Generated!"); From 9ec9b022b508ae32b6ac1f2b4b82a93a608c5485 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Thu, 12 Dec 2024 07:11:08 +1000 Subject: [PATCH 59/77] fix setting of protocol version in created snapshots (#1787) --- cmd/soroban-cli/src/commands/snapshot/create.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/commands/snapshot/create.rs b/cmd/soroban-cli/src/commands/snapshot/create.rs index 6ce48d3f2..a3ba865fa 100644 --- a/cmd/soroban-cli/src/commands/snapshot/create.rs +++ b/cmd/soroban-cli/src/commands/snapshot/create.rs @@ -274,7 +274,13 @@ impl Cmd { } BucketEntry::Deadentry(k) => (k, None), BucketEntry::Metaentry(m) => { - snapshot.protocol_version = m.ledger_version; + if m.ledger_version > snapshot.protocol_version { + snapshot.protocol_version = m.ledger_version; + print.infoln(format!( + "Protocol version: {}", + snapshot.protocol_version + )); + } continue; } }; From 8aefbf5cff5c6f62c96acbc4f8474fafc166928f Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Thu, 12 Dec 2024 15:04:14 -0500 Subject: [PATCH 60/77] feat(ts-bindings): allow generating from wasm hash (#1780) Refactor spec-fetching logic from `contract::info::shared` so that it can be used for `contract::bindings::typescript` as well. This means that `contract::info` commands now have more logging than they did before, and support global args for quieting these print statements. Co-authored-by: Willem Wyndham --- FULL_HELP_DOCS.md | 35 +++---- .../ts-tests/initialize.sh | 2 +- .../src/commands/contract/bindings.rs | 2 +- .../commands/contract/bindings/typescript.rs | 97 ++++--------------- cmd/soroban-cli/src/commands/contract/info.rs | 12 ++- .../src/commands/contract/info/env_meta.rs | 15 ++- .../src/commands/contract/info/interface.rs | 7 +- .../src/commands/contract/info/meta.rs | 7 +- .../src/commands/contract/info/shared.rs | 70 +++++++++---- cmd/soroban-cli/src/commands/contract/mod.rs | 2 +- 10 files changed, 119 insertions(+), 130 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index fc2a84335..04b144315 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -290,20 +290,21 @@ Generate Rust bindings Generate a TypeScript / JavaScript package -**Usage:** `stellar contract bindings typescript [OPTIONS] --output-dir ` +**Usage:** `stellar contract bindings typescript [OPTIONS] --output-dir <--wasm |--wasm-hash |--contract-id >` ###### **Options:** -* `--wasm ` — Path to wasm file on local filesystem. You must either include this OR `--contract-id` -* `--contract-id ` — A contract ID/address on a network (if no network settings provided, Testnet will be assumed). You must either include this OR `--wasm` -* `--output-dir ` — Where to place generated project -* `--overwrite` — Whether to overwrite output directory if it already exists +* `--wasm ` — Wasm file path on local filesystem. Provide this OR `--wasm-hash` OR `--contract-id` +* `--wasm-hash ` — Hash of Wasm blob on a network. Provide this OR `--wasm` OR `--contract-id` +* `--contract-id ` — Contract ID/alias on a network. Provide this OR `--wasm-hash` OR `--wasm` * `--rpc-url ` — RPC server endpoint * `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." +* `--output-dir ` — Where to place generated project +* `--overwrite` — Whether to overwrite output directory if it already exists @@ -525,13 +526,13 @@ The data outputted by this command is a stream of `SCSpecEntry` XDR values. See Outputs no data when no data is present in the contract. -**Usage:** `stellar contract info interface [OPTIONS] <--wasm |--wasm-hash |--id >` +**Usage:** `stellar contract info interface [OPTIONS] <--wasm |--wasm-hash |--contract-id >` ###### **Options:** -* `--wasm ` — Wasm file to extract the data from -* `--wasm-hash ` — Wasm hash to get the data for -* `--id ` — Contract id or contract alias to get the data for +* `--wasm ` — Wasm file path on local filesystem. Provide this OR `--wasm-hash` OR `--contract-id` +* `--wasm-hash ` — Hash of Wasm blob on a network. Provide this OR `--wasm` OR `--contract-id` +* `--contract-id ` — Contract ID/alias on a network. Provide this OR `--wasm-hash` OR `--wasm` * `--rpc-url ` — RPC server endpoint * `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server @@ -565,13 +566,13 @@ The data outputted by this command is a stream of `SCMetaEntry` XDR values. See Outputs no data when no data is present in the contract. -**Usage:** `stellar contract info meta [OPTIONS] <--wasm |--wasm-hash |--id >` +**Usage:** `stellar contract info meta [OPTIONS] <--wasm |--wasm-hash |--contract-id >` ###### **Options:** -* `--wasm ` — Wasm file to extract the data from -* `--wasm-hash ` — Wasm hash to get the data for -* `--id ` — Contract id or contract alias to get the data for +* `--wasm ` — Wasm file path on local filesystem. Provide this OR `--wasm-hash` OR `--contract-id` +* `--wasm-hash ` — Hash of Wasm blob on a network. Provide this OR `--wasm` OR `--contract-id` +* `--contract-id ` — Contract ID/alias on a network. Provide this OR `--wasm-hash` OR `--wasm` * `--rpc-url ` — RPC server endpoint * `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server @@ -605,13 +606,13 @@ The data outputted by this command is a stream of `SCEnvMetaEntry` XDR values. S Outputs no data when no data is present in the contract. -**Usage:** `stellar contract info env-meta [OPTIONS] <--wasm |--wasm-hash |--id >` +**Usage:** `stellar contract info env-meta [OPTIONS] <--wasm |--wasm-hash |--contract-id >` ###### **Options:** -* `--wasm ` — Wasm file to extract the data from -* `--wasm-hash ` — Wasm hash to get the data for -* `--id ` — Contract id or contract alias to get the data for +* `--wasm ` — Wasm file path on local filesystem. Provide this OR `--wasm-hash` OR `--contract-id` +* `--wasm-hash ` — Hash of Wasm blob on a network. Provide this OR `--wasm` OR `--contract-id` +* `--contract-id ` — Contract ID/alias on a network. Provide this OR `--wasm-hash` OR `--wasm` * `--rpc-url ` — RPC server endpoint * `--rpc-header ` — RPC Header(s) to include in requests to the RPC provider * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh index e872923c6..804820abb 100755 --- a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh +++ b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh @@ -43,7 +43,7 @@ function bind() { } function bind_all() { bind --contract-id $(cat contract-id-custom-types.txt) test-custom-types - bind --wasm ../../../../target/wasm32-unknown-unknown/test-wasms/test_constructor.wasm test-constructor + bind --wasm-hash $(cat contract-wasm-hash-constructor.txt) test-constructor } fund_all diff --git a/cmd/soroban-cli/src/commands/contract/bindings.rs b/cmd/soroban-cli/src/commands/contract/bindings.rs index a91c966aa..c0e1f288a 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings.rs @@ -12,7 +12,7 @@ pub enum Cmd { Rust(rust::Cmd), /// Generate a TypeScript / JavaScript package - Typescript(typescript::Cmd), + Typescript(Box), /// Generate Python bindings Python(python::Cmd), diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index ea1f63eed..abe26dd37 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -2,43 +2,30 @@ use std::{ffi::OsString, fmt::Debug, path::PathBuf}; use clap::{command, Parser}; use soroban_spec_tools::contract as contract_spec; -use soroban_spec_typescript::{self as typescript, boilerplate::Project}; -use stellar_strkey::DecodeError; +use soroban_spec_typescript::boilerplate::Project; use crate::print::Print; -use crate::wasm; use crate::{ - commands::{contract::fetch, global, NetworkRunnable}, - config::{self, locator, network}, - get_spec::{self, get_remote_contract_spec}, - xdr::{Hash, ScAddress}, + commands::{contract::info::shared as wasm_or_contract, global, NetworkRunnable}, + config, }; +use soroban_spec_tools::contract::Spec; #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { - /// Path to wasm file on local filesystem. You must either include this OR `--contract-id`. - #[arg(long)] - pub wasm: Option, - /// A contract ID/address on a network (if no network settings provided, Testnet will be assumed). You must either include this OR `--wasm`. - #[arg(long, visible_alias = "id")] - pub contract_id: Option, + #[command(flatten)] + pub wasm_or_hash_or_contract_id: wasm_or_contract::Args, /// Where to place generated project #[arg(long)] pub output_dir: PathBuf, /// Whether to overwrite output directory if it already exists #[arg(long)] pub overwrite: bool, - #[command(flatten)] - pub network: network::Args, - #[command(flatten)] - pub locator: locator::Args, } #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("failed generate TS from file: {0}")] - GenerateTSFromFile(typescript::GenerateFromFileError), #[error(transparent)] Io(#[from] std::io::Error), @@ -51,28 +38,12 @@ pub enum Error { #[error("--output-dir filepath not representable as utf-8: {0:?}")] NotUtf8(OsString), - #[error("must include either --wasm or --contract-id")] - MissingWasmOrContractId, - - #[error(transparent)] - Network(#[from] network::Error), - - #[error(transparent)] - Locator(#[from] locator::Error), - #[error(transparent)] - Fetch(#[from] fetch::Error), #[error(transparent)] Spec(#[from] contract_spec::Error), - #[error(transparent)] - Wasm(#[from] wasm::Error), #[error("Failed to get file name from path: {0:?}")] FailedToGetFileName(PathBuf), - #[error("cannot parse contract ID {0}: {1}")] - CannotParseContractId(String, DecodeError), - #[error(transparent)] - UtilsError(#[from] get_spec::Error), #[error(transparent)] - Config(#[from] config::Error), + WasmOrContract(#[from] wasm_or_contract::Error), } #[async_trait::async_trait] @@ -83,51 +54,19 @@ impl NetworkRunnable for Cmd { async fn run_against_rpc_server( &self, global_args: Option<&global::Args>, - config: Option<&config::Args>, + _config: Option<&config::Args>, ) -> Result<(), Error> { let print = Print::new(global_args.is_some_and(|a| a.quiet)); - let (spec, contract_address, rpc_url, network_passphrase) = if let Some(wasm) = &self.wasm { - print.infoln("Loading contract spec from file..."); - let wasm: wasm::Args = wasm.into(); - (wasm.parse()?.spec, None, None, None) - } else { - let contract_id = self - .contract_id - .as_ref() - .ok_or(Error::MissingWasmOrContractId)?; - - let network = self.network.get(&self.locator).ok().unwrap_or_else(|| { - network::DEFAULTS - .get("testnet") - .expect("no network specified and testnet network not found") - .into() - }); - print.infoln(format!("Network: {}", network.network_passphrase)); + let (spec, contract_address, network) = + wasm_or_contract::fetch_wasm(&self.wasm_or_hash_or_contract_id, &print).await?; - let contract_id = self - .locator - .resolve_contract_id(contract_id, &network.network_passphrase)? - .0; - - let contract_address = ScAddress::Contract(Hash(contract_id)).to_string(); - print.globeln(format!("Downloading contract spec: {contract_address}")); - - ( - get_remote_contract_spec( - &contract_id, - &self.locator, - &self.network, - global_args, - config, - ) - .await - .map_err(Error::from)?, - Some(contract_address), - Some(network.rpc_url), - Some(network.network_passphrase), - ) + let spec = if let Some(spec) = spec { + Spec::new(&spec)? + } else { + Spec::new(&soroban_sdk::token::StellarAssetSpec::spec_xdr())? }; + if self.output_dir.is_file() { return Err(Error::IsFile(self.output_dir.clone())); } @@ -153,9 +92,9 @@ impl NetworkRunnable for Cmd { p.init( contract_name, contract_address.as_deref(), - rpc_url.as_deref(), - network_passphrase.as_deref(), - &spec, + network.as_ref().map(|n| n.rpc_url.as_ref()), + network.as_ref().map(|n| n.network_passphrase.as_ref()), + &spec.spec, )?; print.checkln("Generated!"); print.infoln(format!( diff --git a/cmd/soroban-cli/src/commands/contract/info.rs b/cmd/soroban-cli/src/commands/contract/info.rs index 5ca03ab2c..6192c1c61 100644 --- a/cmd/soroban-cli/src/commands/contract/info.rs +++ b/cmd/soroban-cli/src/commands/contract/info.rs @@ -1,9 +1,11 @@ use std::fmt::Debug; +use crate::commands::global; + pub mod env_meta; pub mod interface; pub mod meta; -mod shared; +pub mod shared; #[derive(Debug, clap::Subcommand)] pub enum Cmd { @@ -60,11 +62,11 @@ pub enum Error { } impl Cmd { - pub async fn run(&self) -> Result<(), Error> { + pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { let result = match &self { - Cmd::Interface(interface) => interface.run().await?, - Cmd::Meta(meta) => meta.run().await?, - Cmd::EnvMeta(env_meta) => env_meta.run().await?, + Cmd::Interface(interface) => interface.run(global_args).await?, + Cmd::Meta(meta) => meta.run(global_args).await?, + Cmd::EnvMeta(env_meta) => env_meta.run(global_args).await?, }; println!("{result}"); Ok(()) diff --git a/cmd/soroban-cli/src/commands/contract/info/env_meta.rs b/cmd/soroban-cli/src/commands/contract/info/env_meta.rs index bc2d03bc6..f882d2737 100644 --- a/cmd/soroban-cli/src/commands/contract/info/env_meta.rs +++ b/cmd/soroban-cli/src/commands/contract/info/env_meta.rs @@ -6,10 +6,14 @@ use soroban_spec_tools::contract; use soroban_spec_tools::contract::Spec; use crate::{ - commands::contract::info::{ - env_meta::Error::{NoEnvMetaPresent, NoSACEnvMeta}, - shared::{self, fetch_wasm, MetasInfoOutput}, + commands::{ + contract::info::{ + env_meta::Error::{NoEnvMetaPresent, NoSACEnvMeta}, + shared::{self, fetch_wasm, MetasInfoOutput}, + }, + global, }, + print::Print, xdr::{ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion}, }; @@ -37,8 +41,9 @@ pub enum Error { } impl Cmd { - pub async fn run(&self) -> Result { - let bytes = fetch_wasm(&self.common).await?; + pub async fn run(&self, global_args: &global::Args) -> Result { + let print = Print::new(global_args.quiet); + let (bytes, ..) = fetch_wasm(&self.common, &print).await?; let Some(bytes) = bytes else { return Err(NoSACEnvMeta()); diff --git a/cmd/soroban-cli/src/commands/contract/info/interface.rs b/cmd/soroban-cli/src/commands/contract/info/interface.rs index cf96fd700..dd71150fa 100644 --- a/cmd/soroban-cli/src/commands/contract/info/interface.rs +++ b/cmd/soroban-cli/src/commands/contract/info/interface.rs @@ -3,6 +3,8 @@ use std::fmt::Debug; use crate::commands::contract::info::interface::Error::NoInterfacePresent; use crate::commands::contract::info::shared; use crate::commands::contract::info::shared::fetch_wasm; +use crate::commands::global; +use crate::print::Print; use clap::{command, Parser}; use soroban_spec_rust::ToFormattedString; use soroban_spec_tools::contract; @@ -43,8 +45,9 @@ pub enum Error { } impl Cmd { - pub async fn run(&self) -> Result { - let bytes = fetch_wasm(&self.common).await?; + pub async fn run(&self, global_args: &global::Args) -> Result { + let print = Print::new(global_args.quiet); + let (bytes, ..) = fetch_wasm(&self.common, &print).await?; let (base64, spec) = if bytes.is_none() { Spec::spec_to_base64(&soroban_sdk::token::StellarAssetSpec::spec_xdr())? diff --git a/cmd/soroban-cli/src/commands/contract/info/meta.rs b/cmd/soroban-cli/src/commands/contract/info/meta.rs index e3e2122c8..4b6fdee3e 100644 --- a/cmd/soroban-cli/src/commands/contract/info/meta.rs +++ b/cmd/soroban-cli/src/commands/contract/info/meta.rs @@ -3,6 +3,8 @@ use std::fmt::Debug; use crate::commands::contract::info::meta::Error::{NoMetaPresent, NoSACMeta}; use crate::commands::contract::info::shared; use crate::commands::contract::info::shared::{fetch_wasm, MetasInfoOutput}; +use crate::commands::global; +use crate::print::Print; use clap::{command, Parser}; use soroban_spec_tools::contract; use soroban_spec_tools::contract::Spec; @@ -32,8 +34,9 @@ pub enum Error { } impl Cmd { - pub async fn run(&self) -> Result { - let bytes = fetch_wasm(&self.common).await?; + pub async fn run(&self, global_args: &global::Args) -> Result { + let print = Print::new(global_args.quiet); + let (bytes, ..) = fetch_wasm(&self.common, &print).await?; let Some(bytes) = bytes else { return Err(NoSACMeta()); diff --git a/cmd/soroban-cli/src/commands/contract/info/shared.rs b/cmd/soroban-cli/src/commands/contract/info/shared.rs index 33a95b607..2ee5d018d 100644 --- a/cmd/soroban-cli/src/commands/contract/info/shared.rs +++ b/cmd/soroban-cli/src/commands/contract/info/shared.rs @@ -4,7 +4,11 @@ use clap::arg; use crate::{ commands::contract::info::shared::Error::InvalidWasmHash, - config::{self, locator, network}, + config::{ + self, locator, + network::{self, Network}, + }, + print::Print, utils::rpc::get_remote_wasm_from_hash, wasm::{self, Error::ContractIsStellarAsset}, xdr, @@ -18,14 +22,31 @@ use crate::{ ))] #[group(skip)] pub struct Args { - /// Wasm file to extract the data from - #[arg(long, group = "Source")] + /// Wasm file path on local filesystem. Provide this OR `--wasm-hash` OR `--contract-id`. + #[arg( + long, + group = "Source", + conflicts_with = "contract_id", + conflicts_with = "wasm_hash" + )] pub wasm: Option, - /// Wasm hash to get the data for - #[arg(long = "wasm-hash", group = "Source")] + /// Hash of Wasm blob on a network. Provide this OR `--wasm` OR `--contract-id`. + #[arg( + long = "wasm-hash", + group = "Source", + conflicts_with = "contract_id", + conflicts_with = "wasm" + )] pub wasm_hash: Option, - /// Contract id or contract alias to get the data for - #[arg(long = "id", env = "STELLAR_CONTRACT_ID", group = "Source")] + /// Contract ID/alias on a network. Provide this OR `--wasm-hash` OR `--wasm`. + #[arg( + long, + env = "STELLAR_CONTRACT_ID", + group = "Source", + visible_alias = "id", + conflicts_with = "wasm", + conflicts_with = "wasm_hash" + )] pub contract_id: Option, #[command(flatten)] pub network: network::Args, @@ -54,23 +75,31 @@ pub enum Error { Wasm(#[from] wasm::Error), #[error("provided wasm hash is invalid {0:?}")] InvalidWasmHash(String), + #[error("must provide one of --wasm, --wasm-hash, or --contract-id")] + MalformedWasmOrWasmHashOrContractId, #[error(transparent)] Rpc(#[from] soroban_rpc::Error), #[error(transparent)] Locator(#[from] locator::Error), } -pub async fn fetch_wasm(args: &Args) -> Result>, Error> { +pub async fn fetch_wasm( + args: &Args, + print: &Print, +) -> Result<(Option>, Option, Option), Error> { // Check if a local WASM file path is provided if let Some(path) = &args.wasm { // Read the WASM file and return its contents + print.infoln("Loading contract spec from file..."); let wasm_bytes = wasm::Args { wasm: path.clone() }.read()?; - return Ok(Some(wasm_bytes)); + return Ok((Some(wasm_bytes), None, None)); } // If no local wasm, then check for wasm_hash and fetch from the network let network = &args.network.get(&args.locator)?; - let wasm = if let Some(wasm_hash) = &args.wasm_hash { + print.infoln(format!("Network: {}", network.network_passphrase)); + + if let Some(wasm_hash) = &args.wasm_hash { let hash = hex::decode(wasm_hash) .map_err(|_| InvalidWasmHash(wasm_hash.clone()))? .try_into() @@ -84,18 +113,25 @@ pub async fn fetch_wasm(args: &Args) -> Result>, Error> { .verify_network_passphrase(Some(&network.network_passphrase)) .await?; - get_remote_wasm_from_hash(&client, &hash).await? + print.globeln(format!( + "Downloading contract spec for wasm hash: {wasm_hash}" + )); + Ok(( + Some(get_remote_wasm_from_hash(&client, &hash).await?), + None, + Some(network.clone()), + )) } else if let Some(contract_id) = &args.contract_id { let contract_id = contract_id.resolve_contract_id(&args.locator, &network.network_passphrase)?; + let contract_address = xdr::ScAddress::Contract(xdr::Hash(contract_id.0)).to_string(); + print.globeln(format!("Downloading contract spec: {contract_address}")); let res = wasm::fetch_from_contract(&contract_id, network).await; if let Some(ContractIsStellarAsset) = res.as_ref().err() { - return Ok(None); + return Ok((None, Some(contract_address), Some(network.clone()))); } - res? + Ok((Some(res?), Some(contract_address), Some(network.clone()))) } else { - unreachable!("One of contract location arguments must be passed"); - }; - - Ok(Some(wasm)) + return Err(Error::MalformedWasmOrWasmHashOrContractId); + } } diff --git a/cmd/soroban-cli/src/commands/contract/mod.rs b/cmd/soroban-cli/src/commands/contract/mod.rs index d72ce62b6..42792a70d 100644 --- a/cmd/soroban-cli/src/commands/contract/mod.rs +++ b/cmd/soroban-cli/src/commands/contract/mod.rs @@ -151,7 +151,7 @@ impl Cmd { Cmd::Alias(alias) => alias.run(global_args)?, Cmd::Deploy(deploy) => deploy.run(global_args).await?, Cmd::Id(id) => id.run()?, - Cmd::Info(info) => info.run().await?, + Cmd::Info(info) => info.run(global_args).await?, Cmd::Init(init) => init.run(global_args)?, Cmd::Inspect(inspect) => inspect.run(global_args)?, Cmd::Install(install) => install.run(global_args).await?, From faf0d01f7835192ff3554f2c954bbe6313243699 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Sat, 14 Dec 2024 03:09:26 +1000 Subject: [PATCH 61/77] Shorten the long env help (#1791) --- FULL_HELP_DOCS.md | 8 ++++++-- cmd/soroban-cli/src/commands/mod.rs | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 04b144315..fd1281cf1 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -45,7 +45,7 @@ Anything after the `--` double dash (the "slop") is parsed as arguments to the c * `contract` — Tools for smart contract developers * `events` — Watch the network for contract events -* `env` — Prints the current environment variables or defaults to the stdout, in a format that can be used as .env file. Environment variables have precedency over defaults +* `env` — Prints the environment variables * `keys` — Create and manage identities including keys and addresses * `network` — Configure connection to networks * `container` — Start local networks in containers @@ -915,7 +915,11 @@ Watch the network for contract events ## `stellar env` -Prints the current environment variables or defaults to the stdout, in a format that can be used as .env file. Environment variables have precedency over defaults +Prints the environment variables + +Prints to stdout in a format that can be used as .env file. Environment variables have precedence over defaults. + +If there are no environment variables in use, prints the defaults. **Usage:** `stellar env [OPTIONS]` diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index 25d61364d..a12347126 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -143,9 +143,12 @@ pub enum Cmd { /// Watch the network for contract events Events(events::Cmd), - /// Prints the current environment variables or defaults to the stdout, in - /// a format that can be used as .env file. Environment variables have - /// precedency over defaults. + /// Prints the environment variables + /// + /// Prints to stdout in a format that can be used as .env file. Environment + /// variables have precedence over defaults. + /// + /// If there are no environment variables in use, prints the defaults. Env(env::Cmd), /// Create and manage identities including keys and addresses From b195d5c324d6344c48032a219b4b5c5e591fe6c1 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 17 Dec 2024 00:05:38 +1000 Subject: [PATCH 62/77] Fix the version of SDK generated with contract init (#1798) --- .../contract-workspace-template/Cargo.toml.removeextension | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension b/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension index c0d6366e0..1c9265386 100644 --- a/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension +++ b/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension @@ -5,7 +5,7 @@ members = [ ] [workspace.dependencies] -soroban-sdk = "21.0.0" +soroban-sdk = "22" [profile.release] opt-level = "z" From e5454e6cc0c3c8997a26eb15ba83338c0506340f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 22:48:12 -0800 Subject: [PATCH 63/77] Bump version to 22.1.0 (#1801) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 32 +++++++++---------- Cargo.toml | 10 +++--- .../tests/fixtures/bye/Cargo.toml | 2 +- .../tests/fixtures/hello/Cargo.toml | 2 +- .../test-wasms/constructor/Cargo.toml | 2 +- .../test-wasms/custom_account/Cargo.toml | 2 +- .../test-wasms/custom_type/Cargo.toml | 2 +- .../test-wasms/hello_world/Cargo.toml | 2 +- .../tests/fixtures/test-wasms/swap/Cargo.toml | 2 +- .../fixtures/test-wasms/token/Cargo.toml | 2 +- 10 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6789ea504..cbe1678d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4288,7 +4288,7 @@ dependencies = [ [[package]] name = "soroban-cli" -version = "22.0.1" +version = "22.1.0" dependencies = [ "assert_cmd", "assert_fs", @@ -4454,7 +4454,7 @@ dependencies = [ [[package]] name = "soroban-hello" -version = "22.0.1" +version = "22.1.0" [[package]] name = "soroban-ledger-snapshot" @@ -4525,7 +4525,7 @@ dependencies = [ [[package]] name = "soroban-spec-json" -version = "22.0.1" +version = "22.1.0" dependencies = [ "pretty_assertions", "serde", @@ -4555,7 +4555,7 @@ dependencies = [ [[package]] name = "soroban-spec-tools" -version = "22.0.1" +version = "22.1.0" dependencies = [ "base64 0.21.7", "ethnum", @@ -4573,7 +4573,7 @@ dependencies = [ [[package]] name = "soroban-spec-typescript" -version = "22.0.1" +version = "22.1.0" dependencies = [ "base64 0.21.7", "heck 0.4.1", @@ -4594,7 +4594,7 @@ dependencies = [ [[package]] name = "soroban-test" -version = "22.0.1" +version = "22.1.0" dependencies = [ "assert_cmd", "assert_fs", @@ -4665,18 +4665,18 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-bye" -version = "22.0.1" +version = "22.1.0" [[package]] name = "stellar-cli" -version = "22.0.1" +version = "22.1.0" dependencies = [ "soroban-cli", ] [[package]] name = "stellar-ledger" -version = "22.0.1" +version = "22.1.0" dependencies = [ "async-trait", "bollard", @@ -5023,42 +5023,42 @@ dependencies = [ [[package]] name = "test_constructor" -version = "22.0.1" +version = "22.1.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_account" -version = "22.0.1" +version = "22.1.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_types" -version = "22.0.1" +version = "22.1.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_hello_world" -version = "22.0.1" +version = "22.1.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_swap" -version = "22.0.1" +version = "22.1.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_token" -version = "22.0.1" +version = "22.1.0" dependencies = [ "soroban-sdk", "soroban-token-sdk", @@ -5066,7 +5066,7 @@ dependencies = [ [[package]] name = "test_udt" -version = "22.0.1" +version = "22.1.0" dependencies = [ "soroban-sdk", ] diff --git a/Cargo.toml b/Cargo.toml index cbfe6dd3c..839ca9cd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,24 +19,24 @@ exclude = [ ] [workspace.package] -version = "22.0.1" +version = "22.1.0" rust-version = "1.81.0" # Dependencies located in this repo: [workspace.dependencies.soroban-cli] -version = "=22.0.1" +version = "=22.1.0" path = "cmd/soroban-cli" [workspace.dependencies.soroban-spec-json] -version = "=22.0.1" +version = "=22.1.0" path = "./cmd/crates/soroban-spec-json" [workspace.dependencies.soroban-spec-typescript] -version = "22.0.1" +version = "22.1.0" path = "./cmd/crates/soroban-spec-typescript" [workspace.dependencies.soroban-spec-tools] -version = "22.0.1" +version = "22.1.0" path = "./cmd/crates/soroban-spec-tools" # Dependencies from the rs-stellar-xdr repo: diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml index 4756225d2..5ca022099 100644 --- a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stellar-bye" -version = "22.0.1" +version = "22.1.0" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml index a2fb7b15c..73d7c781e 100644 --- a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "soroban-hello" -version = "22.0.1" +version = "22.1.0" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml index 9ccbb23d0..f7f9abac0 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_constructor" -version = "22.0.1" +version = "22.1.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml index e69dd96c9..081312a81 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_account" -version = "22.0.1" +version = "22.1.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index 50b6d8a72..ebe2191e1 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_types" -version = "22.0.1" +version = "22.1.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index a91a6ca62..14b386d2b 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_hello_world" -version = "22.0.1" +version = "22.1.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml index 15c45c98e..70387d652 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_swap" -version = "22.0.1" +version = "22.1.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml index d4e7e7436..681bb9b40 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_token" -version = "22.0.1" +version = "22.1.0" description = "Soroban standard token contract" authors = ["Stellar Development Foundation "] license = "Apache-2.0" From 01220f64cd9e0c3ef435cbdd9c36e93a8d47323d Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 20 Dec 2024 01:47:28 +1000 Subject: [PATCH 64/77] keys: generate 24-word keys (#1808) Close #1803 --- cmd/soroban-cli/src/config/secret.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index a7fd86fda..d6de1b6ea 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -144,7 +144,7 @@ impl Secret { let seed_phrase = if let Some(seed) = seed.map(str::as_bytes) { sep5::SeedPhrase::from_entropy(seed) } else { - sep5::SeedPhrase::random(sep5::MnemonicType::Words12) + sep5::SeedPhrase::random(sep5::MnemonicType::Words24) }? .seed_phrase .into_phrase(); From 7a50b86f1e453d2d18bd4474c80e58fddce3a87a Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Thu, 19 Dec 2024 13:52:51 -0300 Subject: [PATCH 65/77] Read correct path when uploading asset to release. (#1813) --- .github/workflows/binaries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index d913cf23d..45d74a243 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -157,6 +157,6 @@ jobs: repo: context.repo.repo, release_id: ${{ github.event.release.id }}, name: '${{ env.STELLAR_CLI_INSTALLER }}', - data: fs.readFileSync('Output/stellar-installer.exe'), + data: fs.readFileSync('${{ env.STELLAR_CLI_INSTALLER }}'), }); From 1efc4c5e41d0bf67d720a16454eb2e1f61ab7ac4 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 19 Dec 2024 14:10:46 -0500 Subject: [PATCH 66/77] fix: handle SAC spec (#1795) While creating the TS Bindings, we were creating a higher level Spec (not just `Vec`), from the raw bytes of the XDR. This higher-level Spec uses metadata from Wasm files, rather than just the raw `Vec` stuff, but TS Bindings don't even use that extra metadata. This implementation detail resulted in a bug when generating TS Bindings for Stellar Asset Contracts, which do not have the (unused) extra metadata. This adds a test of generating TS Bindings for SAC, and fixes the bug. We've also cleaned up `ts-tests` logic while here, updating "soroban" references with "stellar". --- .github/workflows/bindings-ts.yml | 2 +- .../soroban-spec-typescript/ts-tests/.env | 6 +++--- .../ts-tests/initialize.sh | 18 +++++++++--------- .../ts-tests/src/test-xlm-lib-from-sac.ts | 15 +++++++++++++++ .../ts-tests/src/util.ts | 6 +++--- .../ts-tests/{soroban => stellar} | 0 .../commands/contract/bindings/typescript.rs | 8 +++++--- 7 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts rename cmd/crates/soroban-spec-typescript/ts-tests/{soroban => stellar} (100%) diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index 9b5f767ac..f6aaae499 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -19,7 +19,7 @@ jobs: NETWORK: local ENABLE_SOROBAN_RPC: true options: >- - --health-cmd "curl --no-progress-meter --fail-with-body -X POST \"http://localhost:8000/soroban/rpc\" -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":8675309,\"method\":\"getNetwork\"}' && curl --no-progress-meter \"http://localhost:8000/friendbot\" | grep '\"invalid_field\": \"addr\"'" + --health-cmd "curl --no-progress-meter --fail-with-body -X POST \"http://localhost:8000/rpc\" -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":8675309,\"method\":\"getNetwork\"}' && curl --no-progress-meter \"http://localhost:8000/friendbot\" | grep '\"invalid_field\": \"addr\"'" --health-interval 10s --health-timeout 5s --health-retries 50 diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/.env b/cmd/crates/soroban-spec-typescript/ts-tests/.env index 93bb4be67..0ea150c3f 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/.env +++ b/cmd/crates/soroban-spec-typescript/ts-tests/.env @@ -1,3 +1,3 @@ -SOROBAN_NETWORK_PASSPHRASE="Standalone Network ; February 2017" -SOROBAN_RPC_URL="http://localhost:8000/soroban/rpc" -SOROBAN_FRIENDBOT_URL="http://localhost:8000/friendbot" +STELLAR_NETWORK_PASSPHRASE="Standalone Network ; February 2017" +STELLAR_RPC_URL="http://localhost:8000/rpc" +STELLAR_FRIENDBOT_URL="http://localhost:8000/friendbot" diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh index 804820abb..1fb84f081 100755 --- a/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh +++ b/cmd/crates/soroban-spec-typescript/ts-tests/initialize.sh @@ -10,10 +10,10 @@ done unset IFS echo Network -echo " RPC: $SOROBAN_RPC_URL" -echo " Passphrase: \"$SOROBAN_NETWORK_PASSPHRASE\"" +echo " RPC: $STELLAR_RPC_URL" +echo " Passphrase: \"$STELLAR_NETWORK_PASSPHRASE\"" -NETWORK_STATUS=$(curl -s -X POST "http://localhost:8000/soroban/rpc" -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", "id": 8675309, "method": "getHealth" }' | sed 's/.*"status":"\([^"]*\)".*/\1/') || { echo "Make sure you're running local RPC network on localhost:8000" && exit 1; } +NETWORK_STATUS=$(curl -s -X POST "http://localhost:8000/rpc" -H "Content-Type: application/json" -d '{ "jsonrpc": "2.0", "id": 8675309, "method": "getHealth" }' | sed 's/.*"status":"\([^"]*\)".*/\1/') || { echo "Make sure you're running local RPC network on localhost:8000" && exit 1; } echo " Status: $NETWORK_STATUS" if [[ "$NETWORK_STATUS" != "healthy" ]]; then @@ -22,28 +22,28 @@ if [[ "$NETWORK_STATUS" != "healthy" ]]; then fi # Print command before executing, from https://stackoverflow.com/a/23342259/249801 -# Discussion: https://github.com/stellar/soroban-tools/pull/1034#pullrequestreview-1690667116 +# Discussion: https://github.com/stellar/stellar-tools/pull/1034#pullrequestreview-1690667116 exe() { echo"${@/eval/}" ; "$@" ; } function fund_all() { - exe eval "./soroban keys generate root" - exe eval "./soroban keys fund root" + exe eval "./stellar keys generate --fund root" } function upload() { - exe eval "(./soroban contract $1 --quiet --source root --wasm $2 --ignore-checks) > $3" + exe eval "(./stellar contract $1 --quiet --source root --wasm $2 --ignore-checks) > $3" } function deploy_all() { upload deploy ../../../../target/wasm32-unknown-unknown/test-wasms/test_custom_types.wasm contract-id-custom-types.txt - # TODO: support `--wasm-hash` with `contract bindings` upload install ../../../../target/wasm32-unknown-unknown/test-wasms/test_constructor.wasm contract-wasm-hash-constructor.txt + exe eval "./stellar contract asset deploy --asset native --source root" } function bind() { - exe eval "./soroban contract bindings typescript $1 $2 --output-dir ./node_modules/$3 --overwrite" + exe eval "./stellar contract bindings typescript $1 $2 --output-dir ./node_modules/$3 --overwrite" exe eval "sh -c \"cd ./node_modules/$3 && npm install && npm run build\"" } function bind_all() { bind --contract-id $(cat contract-id-custom-types.txt) test-custom-types bind --wasm-hash $(cat contract-wasm-hash-constructor.txt) test-constructor + bind --contract-id $(./stellar contract id asset --asset native) xlm } fund_all diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts new file mode 100644 index 000000000..e39fb8b7d --- /dev/null +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/test-xlm-lib-from-sac.ts @@ -0,0 +1,15 @@ +import test from "ava" +import { rpcUrl, root, signer } from "./util.js" +import { Client, networks } from "xlm" + +const contract = new Client({ + ...networks.standalone, + rpcUrl, + allowHttp: true, + publicKey: root.keypair.publicKey(), + ...signer, +}) + +test("can generate a lib from a Stellar Asset Contract", async (t) => { + t.is((await contract.symbol()).result, "native"); +}); diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts index a5315a643..15649b63e 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts @@ -3,7 +3,7 @@ import { Address, Keypair } from "@stellar/stellar-sdk"; import { basicNodeSigner } from "@stellar/stellar-sdk/contract"; const rootKeypair = Keypair.fromSecret( - spawnSync("./soroban", ["keys", "show", "root"], { + spawnSync("./stellar", ["keys", "show", "root"], { shell: true, encoding: "utf8", }).stdout.trim(), @@ -14,9 +14,9 @@ export const root = { address: Address.fromString(rootKeypair.publicKey()), }; -export const rpcUrl = process.env.SOROBAN_RPC_URL ?? "http://localhost:8000/"; +export const rpcUrl = process.env.STELLAR_RPC_URL ?? "http://localhost:8000/"; export const networkPassphrase = - process.env.SOROBAN_NETWORK_PASSPHRASE ?? + process.env.STELLAR_NETWORK_PASSPHRASE ?? "Standalone Network ; February 2017"; export const signer = basicNodeSigner(root.keypair, networkPassphrase); diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/soroban b/cmd/crates/soroban-spec-typescript/ts-tests/stellar similarity index 100% rename from cmd/crates/soroban-spec-typescript/ts-tests/soroban rename to cmd/crates/soroban-spec-typescript/ts-tests/stellar diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index abe26dd37..5317c81f3 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -44,6 +44,8 @@ pub enum Error { FailedToGetFileName(PathBuf), #[error(transparent)] WasmOrContract(#[from] wasm_or_contract::Error), + #[error(transparent)] + Xdr(#[from] crate::xdr::Error), } #[async_trait::async_trait] @@ -62,9 +64,9 @@ impl NetworkRunnable for Cmd { wasm_or_contract::fetch_wasm(&self.wasm_or_hash_or_contract_id, &print).await?; let spec = if let Some(spec) = spec { - Spec::new(&spec)? + Spec::new(&spec)?.spec } else { - Spec::new(&soroban_sdk::token::StellarAssetSpec::spec_xdr())? + soroban_spec::read::parse_raw(&soroban_sdk::token::StellarAssetSpec::spec_xdr())? }; if self.output_dir.is_file() { @@ -94,7 +96,7 @@ impl NetworkRunnable for Cmd { contract_address.as_deref(), network.as_ref().map(|n| n.rpc_url.as_ref()), network.as_ref().map(|n| n.network_passphrase.as_ref()), - &spec.spec, + &spec, )?; print.checkln("Generated!"); print.infoln(format!( From 7b6c5cdd1da813fceb1a2b05dd9b0f5874c3c6e6 Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Thu, 19 Dec 2024 16:32:54 -0500 Subject: [PATCH 67/77] chore: clean up interface for info::shared::fetch (#1802) Follow-up to https://github.com/stellar/stellar-cli/pull/1780, implementing @leighmcculloch's [suggestions]. [suggestions]: https://github.com/stellar/stellar-cli/pull/1780#pullrequestreview-2499059771 --- .../commands/contract/bindings/typescript.rs | 39 +++++---- .../src/commands/contract/info/env_meta.rs | 10 +-- .../src/commands/contract/info/interface.rs | 24 +++--- .../src/commands/contract/info/meta.rs | 11 ++- .../src/commands/contract/info/shared.rs | 82 +++++++++++++++---- 5 files changed, 113 insertions(+), 53 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs index 5317c81f3..1da64eaa5 100644 --- a/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs +++ b/cmd/soroban-cli/src/commands/contract/bindings/typescript.rs @@ -1,12 +1,12 @@ use std::{ffi::OsString, fmt::Debug, path::PathBuf}; use clap::{command, Parser}; -use soroban_spec_tools::contract as contract_spec; +use soroban_spec_tools::contract as spec_tools; use soroban_spec_typescript::boilerplate::Project; use crate::print::Print; use crate::{ - commands::{contract::info::shared as wasm_or_contract, global, NetworkRunnable}, + commands::{contract::info::shared as contract_spec, global, NetworkRunnable}, config, }; use soroban_spec_tools::contract::Spec; @@ -15,7 +15,7 @@ use soroban_spec_tools::contract::Spec; #[group(skip)] pub struct Cmd { #[command(flatten)] - pub wasm_or_hash_or_contract_id: wasm_or_contract::Args, + pub wasm_or_hash_or_contract_id: contract_spec::Args, /// Where to place generated project #[arg(long)] pub output_dir: PathBuf, @@ -39,11 +39,11 @@ pub enum Error { NotUtf8(OsString), #[error(transparent)] - Spec(#[from] contract_spec::Error), + Spec(#[from] spec_tools::Error), #[error("Failed to get file name from path: {0:?}")] FailedToGetFileName(PathBuf), #[error(transparent)] - WasmOrContract(#[from] wasm_or_contract::Error), + WasmOrContract(#[from] contract_spec::Error), #[error(transparent)] Xdr(#[from] crate::xdr::Error), } @@ -60,13 +60,14 @@ impl NetworkRunnable for Cmd { ) -> Result<(), Error> { let print = Print::new(global_args.is_some_and(|a| a.quiet)); - let (spec, contract_address, network) = - wasm_or_contract::fetch_wasm(&self.wasm_or_hash_or_contract_id, &print).await?; + let contract_spec::Fetched { contract, source } = + contract_spec::fetch(&self.wasm_or_hash_or_contract_id, &print).await?; - let spec = if let Some(spec) = spec { - Spec::new(&spec)?.spec - } else { - soroban_spec::read::parse_raw(&soroban_sdk::token::StellarAssetSpec::spec_xdr())? + let spec = match contract { + contract_spec::Contract::Wasm { wasm_bytes } => Spec::new(&wasm_bytes)?.spec, + contract_spec::Contract::StellarAssetContract => { + soroban_spec::read::parse_raw(&soroban_sdk::token::StellarAssetSpec::spec_xdr())? + } }; if self.output_dir.is_file() { @@ -88,12 +89,20 @@ impl NetworkRunnable for Cmd { let contract_name = &file_name .to_str() .ok_or_else(|| Error::NotUtf8(file_name.to_os_string()))?; - if let Some(contract_address) = contract_address.clone() { - print.infoln(format!("Embedding contract address: {contract_address}")); - } + let (resolved_address, network) = match source { + contract_spec::Source::Contract { + resolved_address, + network, + } => { + print.infoln(format!("Embedding contract address: {resolved_address}")); + (Some(resolved_address), Some(network)) + } + contract_spec::Source::Wasm { network, .. } => (None, Some(network)), + contract_spec::Source::File { .. } => (None, None), + }; p.init( contract_name, - contract_address.as_deref(), + resolved_address.as_deref(), network.as_ref().map(|n| n.rpc_url.as_ref()), network.as_ref().map(|n| n.network_passphrase.as_ref()), &spec, diff --git a/cmd/soroban-cli/src/commands/contract/info/env_meta.rs b/cmd/soroban-cli/src/commands/contract/info/env_meta.rs index f882d2737..02da6f439 100644 --- a/cmd/soroban-cli/src/commands/contract/info/env_meta.rs +++ b/cmd/soroban-cli/src/commands/contract/info/env_meta.rs @@ -9,7 +9,7 @@ use crate::{ commands::{ contract::info::{ env_meta::Error::{NoEnvMetaPresent, NoSACEnvMeta}, - shared::{self, fetch_wasm, MetasInfoOutput}, + shared::{self, fetch, Fetched, MetasInfoOutput}, }, global, }, @@ -43,12 +43,12 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result { let print = Print::new(global_args.quiet); - let (bytes, ..) = fetch_wasm(&self.common, &print).await?; + let Fetched { contract, .. } = fetch(&self.common, &print).await?; - let Some(bytes) = bytes else { - return Err(NoSACEnvMeta()); + let spec = match contract { + shared::Contract::Wasm { wasm_bytes } => Spec::new(&wasm_bytes)?, + shared::Contract::StellarAssetContract => return Err(NoSACEnvMeta()), }; - let spec = Spec::new(&bytes)?; let Some(env_meta_base64) = spec.env_meta_base64 else { return Err(NoEnvMetaPresent()); diff --git a/cmd/soroban-cli/src/commands/contract/info/interface.rs b/cmd/soroban-cli/src/commands/contract/info/interface.rs index dd71150fa..0c896bc3d 100644 --- a/cmd/soroban-cli/src/commands/contract/info/interface.rs +++ b/cmd/soroban-cli/src/commands/contract/info/interface.rs @@ -1,8 +1,7 @@ use std::fmt::Debug; use crate::commands::contract::info::interface::Error::NoInterfacePresent; -use crate::commands::contract::info::shared; -use crate::commands::contract::info::shared::fetch_wasm; +use crate::commands::contract::info::shared::{self, fetch, Fetched}; use crate::commands::global; use crate::print::Print; use clap::{command, Parser}; @@ -47,18 +46,21 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result { let print = Print::new(global_args.quiet); - let (bytes, ..) = fetch_wasm(&self.common, &print).await?; + let Fetched { contract, .. } = fetch(&self.common, &print).await?; - let (base64, spec) = if bytes.is_none() { - Spec::spec_to_base64(&soroban_sdk::token::StellarAssetSpec::spec_xdr())? - } else { - let spec = Spec::new(&bytes.unwrap())?; + let (base64, spec) = match contract { + shared::Contract::Wasm { wasm_bytes } => { + let spec = Spec::new(&wasm_bytes)?; - if spec.env_meta_base64.is_none() { - return Err(NoInterfacePresent()); - } + if spec.env_meta_base64.is_none() { + return Err(NoInterfacePresent()); + } - (spec.spec_base64.unwrap(), spec.spec) + (spec.spec_base64.unwrap(), spec.spec) + } + shared::Contract::StellarAssetContract => { + Spec::spec_to_base64(&soroban_sdk::token::StellarAssetSpec::spec_xdr())? + } }; let res = match self.output { diff --git a/cmd/soroban-cli/src/commands/contract/info/meta.rs b/cmd/soroban-cli/src/commands/contract/info/meta.rs index 4b6fdee3e..736e8f432 100644 --- a/cmd/soroban-cli/src/commands/contract/info/meta.rs +++ b/cmd/soroban-cli/src/commands/contract/info/meta.rs @@ -1,8 +1,7 @@ use std::fmt::Debug; use crate::commands::contract::info::meta::Error::{NoMetaPresent, NoSACMeta}; -use crate::commands::contract::info::shared; -use crate::commands::contract::info::shared::{fetch_wasm, MetasInfoOutput}; +use crate::commands::contract::info::shared::{self, fetch, Fetched, MetasInfoOutput}; use crate::commands::global; use crate::print::Print; use clap::{command, Parser}; @@ -36,12 +35,12 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result { let print = Print::new(global_args.quiet); - let (bytes, ..) = fetch_wasm(&self.common, &print).await?; + let Fetched { contract, .. } = fetch(&self.common, &print).await?; - let Some(bytes) = bytes else { - return Err(NoSACMeta()); + let spec = match contract { + shared::Contract::Wasm { wasm_bytes } => Spec::new(&wasm_bytes)?, + shared::Contract::StellarAssetContract => return Err(NoSACMeta()), }; - let spec = Spec::new(&bytes)?; let Some(meta_base64) = spec.meta_base64 else { return Err(NoMetaPresent()); diff --git a/cmd/soroban-cli/src/commands/contract/info/shared.rs b/cmd/soroban-cli/src/commands/contract/info/shared.rs index 2ee5d018d..6023b03cf 100644 --- a/cmd/soroban-cli/src/commands/contract/info/shared.rs +++ b/cmd/soroban-cli/src/commands/contract/info/shared.rs @@ -76,23 +76,58 @@ pub enum Error { #[error("provided wasm hash is invalid {0:?}")] InvalidWasmHash(String), #[error("must provide one of --wasm, --wasm-hash, or --contract-id")] - MalformedWasmOrWasmHashOrContractId, + MissingArg, #[error(transparent)] Rpc(#[from] soroban_rpc::Error), #[error(transparent)] Locator(#[from] locator::Error), } -pub async fn fetch_wasm( - args: &Args, - print: &Print, -) -> Result<(Option>, Option, Option), Error> { +pub struct Fetched { + pub contract: Contract, + pub source: Source, +} + +pub enum Contract { + Wasm { wasm_bytes: Vec }, + StellarAssetContract, +} + +pub enum Source { + File { + path: PathBuf, + }, + Wasm { + hash: String, + network: Network, + }, + Contract { + resolved_address: String, + network: Network, + }, +} + +impl Source { + pub fn network(&self) -> Option<&Network> { + match self { + Source::File { .. } => None, + Source::Wasm { ref network, .. } | Source::Contract { ref network, .. } => { + Some(network) + } + } + } +} + +pub async fn fetch(args: &Args, print: &Print) -> Result { // Check if a local WASM file path is provided if let Some(path) = &args.wasm { // Read the WASM file and return its contents print.infoln("Loading contract spec from file..."); let wasm_bytes = wasm::Args { wasm: path.clone() }.read()?; - return Ok((Some(wasm_bytes), None, None)); + return Ok(Fetched { + contract: Contract::Wasm { wasm_bytes }, + source: Source::File { path: path.clone() }, + }); } // If no local wasm, then check for wasm_hash and fetch from the network @@ -116,22 +151,37 @@ pub async fn fetch_wasm( print.globeln(format!( "Downloading contract spec for wasm hash: {wasm_hash}" )); - Ok(( - Some(get_remote_wasm_from_hash(&client, &hash).await?), - None, - Some(network.clone()), - )) + let wasm_bytes = get_remote_wasm_from_hash(&client, &hash).await?; + Ok(Fetched { + contract: Contract::Wasm { wasm_bytes }, + source: Source::Wasm { + hash: wasm_hash.clone(), + network: network.clone(), + }, + }) } else if let Some(contract_id) = &args.contract_id { let contract_id = contract_id.resolve_contract_id(&args.locator, &network.network_passphrase)?; - let contract_address = xdr::ScAddress::Contract(xdr::Hash(contract_id.0)).to_string(); - print.globeln(format!("Downloading contract spec: {contract_address}")); + let derived_address = xdr::ScAddress::Contract(xdr::Hash(contract_id.0)).to_string(); + print.globeln(format!("Downloading contract spec: {derived_address}")); let res = wasm::fetch_from_contract(&contract_id, network).await; if let Some(ContractIsStellarAsset) = res.as_ref().err() { - return Ok((None, Some(contract_address), Some(network.clone()))); + return Ok(Fetched { + contract: Contract::StellarAssetContract, + source: Source::Contract { + resolved_address: derived_address, + network: network.clone(), + }, + }); } - Ok((Some(res?), Some(contract_address), Some(network.clone()))) + Ok(Fetched { + contract: Contract::Wasm { wasm_bytes: res? }, + source: Source::Contract { + resolved_address: derived_address, + network: network.clone(), + }, + }) } else { - return Err(Error::MalformedWasmOrWasmHashOrContractId); + return Err(Error::MissingArg); } } From 41050c5281220bfd75da0cbef109e9c549928ce1 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 20 Dec 2024 08:28:03 +1000 Subject: [PATCH 68/77] keys: tell the user where a key is saved (#1811) --- cmd/soroban-cli/src/commands/keys/add.rs | 16 +++++++++++----- cmd/soroban-cli/src/commands/keys/fund.rs | 15 +++++++++------ cmd/soroban-cli/src/commands/keys/generate.rs | 7 ++++++- cmd/soroban-cli/src/commands/keys/mod.rs | 4 ++-- cmd/soroban-cli/src/commands/network/add.rs | 6 +++--- cmd/soroban-cli/src/config/locator.rs | 12 ++++++++---- 6 files changed, 39 insertions(+), 21 deletions(-) diff --git a/cmd/soroban-cli/src/commands/keys/add.rs b/cmd/soroban-cli/src/commands/keys/add.rs index d8f528bae..af829fe6f 100644 --- a/cmd/soroban-cli/src/commands/keys/add.rs +++ b/cmd/soroban-cli/src/commands/keys/add.rs @@ -1,6 +1,10 @@ use clap::command; -use crate::config::{locator, secret}; +use crate::{ + commands::global, + config::{locator, secret}, + print::Print, +}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -25,9 +29,11 @@ pub struct Cmd { } impl Cmd { - pub fn run(&self) -> Result<(), Error> { - Ok(self - .config_locator - .write_identity(&self.name, &self.secrets.read_secret()?)?) + pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let print = Print::new(global_args.quiet); + let secret = self.secrets.read_secret()?; + let path = self.config_locator.write_identity(&self.name, &secret)?; + print.checkln(format!("Key saved with alias {:?} in {path:?}", self.name)); + Ok(()) } } diff --git a/cmd/soroban-cli/src/commands/keys/fund.rs b/cmd/soroban-cli/src/commands/keys/fund.rs index d7100c6cb..2419c4be2 100644 --- a/cmd/soroban-cli/src/commands/keys/fund.rs +++ b/cmd/soroban-cli/src/commands/keys/fund.rs @@ -1,6 +1,6 @@ use clap::command; -use crate::config::network; +use crate::{commands::global, config::network, print::Print}; use super::address; @@ -23,12 +23,15 @@ pub struct Cmd { } impl Cmd { - pub async fn run(&self) -> Result<(), Error> { + pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let print = Print::new(global_args.quiet); let addr = self.address.public_key()?; - self.network - .get(&self.address.locator)? - .fund_address(&addr) - .await?; + let network = self.network.get(&self.address.locator)?; + network.fund_address(&addr).await?; + print.checkln(format!( + "Account {:?} funded on {:?}", + self.address.name, network.network_passphrase + )); Ok(()) } } diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index c6623386c..fda6a3d98 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -96,7 +96,8 @@ impl Cmd { seed_phrase }; - self.config_locator.write_identity(&self.name, &secret)?; + let path = self.config_locator.write_identity(&self.name, &secret)?; + print.checkln(format!("Key saved with alias {:?} in {path:?}", self.name)); if !self.no_fund { let addr = secret.public_key(self.hd_path)?; @@ -108,6 +109,10 @@ impl Cmd { tracing::warn!("fund_address failed: {e}"); }) .unwrap_or_default(); + print.checkln(format!( + "Account {:?} funded on {:?}", + self.name, network.network_passphrase + )); } Ok(()) diff --git a/cmd/soroban-cli/src/commands/keys/mod.rs b/cmd/soroban-cli/src/commands/keys/mod.rs index 8729ee9af..e5409ce37 100644 --- a/cmd/soroban-cli/src/commands/keys/mod.rs +++ b/cmd/soroban-cli/src/commands/keys/mod.rs @@ -70,9 +70,9 @@ pub enum Error { impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match self { - Cmd::Add(cmd) => cmd.run()?, + Cmd::Add(cmd) => cmd.run(global_args)?, Cmd::Address(cmd) => cmd.run()?, - Cmd::Fund(cmd) => cmd.run().await?, + Cmd::Fund(cmd) => cmd.run(global_args).await?, Cmd::Generate(cmd) => cmd.run(global_args).await?, Cmd::Ls(cmd) => cmd.run()?, Cmd::Rm(cmd) => cmd.run()?, diff --git a/cmd/soroban-cli/src/commands/network/add.rs b/cmd/soroban-cli/src/commands/network/add.rs index 20b1afa7b..feeea9030 100644 --- a/cmd/soroban-cli/src/commands/network/add.rs +++ b/cmd/soroban-cli/src/commands/network/add.rs @@ -25,8 +25,8 @@ pub struct Cmd { impl Cmd { pub fn run(&self) -> Result<(), Error> { - Ok(self - .config_locator - .write_network(&self.name, &self.network)?) + self.config_locator + .write_network(&self.name, &self.network)?; + Ok(()) } } diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index b6f5c75c1..7e97f6796 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -162,11 +162,11 @@ impl Args { ) } - pub fn write_identity(&self, name: &str, secret: &Secret) -> Result<(), Error> { + pub fn write_identity(&self, name: &str, secret: &Secret) -> Result { KeyType::Identity.write(name, secret, &self.config_dir()?) } - pub fn write_network(&self, name: &str, network: &Network) -> Result<(), Error> { + pub fn write_network(&self, name: &str, network: &Network) -> Result { KeyType::Network.write(name, network, &self.config_dir()?) } @@ -441,10 +441,14 @@ impl KeyType { key: &str, value: &T, pwd: &Path, - ) -> Result<(), Error> { + ) -> Result { let filepath = ensure_directory(self.path(pwd, key))?; let data = toml::to_string(value).map_err(|_| Error::ConfigSerialization)?; - std::fs::write(&filepath, data).map_err(|error| Error::IdCreationFailed { filepath, error }) + std::fs::write(&filepath, data).map_err(|error| Error::IdCreationFailed { + filepath: filepath.clone(), + error, + })?; + Ok(filepath) } fn root(&self, pwd: &Path) -> PathBuf { From 2790dc15191743699eabd7b0c9288381bf579eee Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 20 Dec 2024 10:15:48 +1000 Subject: [PATCH 69/77] keys: rename `show` to `secret` (#1807) --- FULL_HELP_DOCS.md | 8 ++++---- .../soroban-spec-typescript/ts-tests/src/util.ts | 2 +- cmd/crates/soroban-test/src/lib.rs | 2 +- cmd/crates/soroban-test/tests/it/config.rs | 4 ++-- .../soroban-test/tests/it/integration/hello_world.rs | 6 +++--- cmd/soroban-cli/src/commands/keys/mod.rs | 10 +++++----- .../src/commands/keys/{show.rs => secret.rs} | 1 + 7 files changed, 17 insertions(+), 16 deletions(-) rename cmd/soroban-cli/src/commands/keys/{show.rs => secret.rs} (95%) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index fd1281cf1..208ec1e84 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -944,7 +944,7 @@ Create and manage identities including keys and addresses * `generate` — Generate a new identity with a seed phrase, currently 12 words * `ls` — List identities * `rm` — Remove an identity -* `show` — Given an identity return its private key +* `secret` — Output an identity's secret key * `use` — Set the default identity that will be used on all commands. This allows you to skip `--source-account` or setting a environment variable, while reusing this value in all commands that require it @@ -1069,11 +1069,11 @@ Remove an identity -## `stellar keys show` +## `stellar keys secret` -Given an identity return its private key +Output an identity's secret key -**Usage:** `stellar keys show [OPTIONS] ` +**Usage:** `stellar keys secret [OPTIONS] ` ###### **Arguments:** diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts index 15649b63e..eacedbaec 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts @@ -3,7 +3,7 @@ import { Address, Keypair } from "@stellar/stellar-sdk"; import { basicNodeSigner } from "@stellar/stellar-sdk/contract"; const rootKeypair = Keypair.fromSecret( - spawnSync("./stellar", ["keys", "show", "root"], { + spawnSync("./soroban", ["keys", "secret", "root"], { shell: true, encoding: "utf8", }).stdout.trim(), diff --git a/cmd/crates/soroban-test/src/lib.rs b/cmd/crates/soroban-test/src/lib.rs index 2c62578ef..492d3bb97 100644 --- a/cmd/crates/soroban-test/src/lib.rs +++ b/cmd/crates/soroban-test/src/lib.rs @@ -285,7 +285,7 @@ impl TestEnv { /// Returns the private key corresponding to the test keys's `hd_path` pub fn test_show(&self, hd_path: usize) -> String { - self.cmd::(&format!("--hd-path={hd_path}")) + self.cmd::(&format!("--hd-path={hd_path}")) .private_key() .unwrap() .to_string() diff --git a/cmd/crates/soroban-test/tests/it/config.rs b/cmd/crates/soroban-test/tests/it/config.rs index b796910a8..e81233b6e 100644 --- a/cmd/crates/soroban-test/tests/it/config.rs +++ b/cmd/crates/soroban-test/tests/it/config.rs @@ -283,7 +283,7 @@ fn use_env() { sandbox .new_assert_cmd("keys") - .arg("show") + .arg("secret") .arg("bob") .assert() .success() @@ -330,7 +330,7 @@ fn config_dirs_precedence() { sandbox .new_assert_cmd("keys") - .arg("show") + .arg("secret") .arg("alice") .arg("--verbose") .assert() diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index b9ed0196f..4464e532f 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -53,7 +53,7 @@ async fn invoke() { let secret_key = sandbox .new_assert_cmd("keys") - .arg("show") + .arg("secret") .arg("test") .assert() .stdout_as_str(); @@ -65,7 +65,7 @@ async fn invoke() { .stdout_as_str(); let secret_key_1 = sandbox .new_assert_cmd("keys") - .arg("show") + .arg("secret") .arg("test") .arg("--hd-path=1") .assert() @@ -115,7 +115,7 @@ async fn invoke() { assert_eq!(sk_from_file, format!("secret_key = \"{secret_key_1}\"\n")); let secret_key_1_readin = sandbox .new_assert_cmd("keys") - .arg("show") + .arg("secret") .arg("testone") .assert() .stdout_as_str(); diff --git a/cmd/soroban-cli/src/commands/keys/mod.rs b/cmd/soroban-cli/src/commands/keys/mod.rs index e5409ce37..b5520abf6 100644 --- a/cmd/soroban-cli/src/commands/keys/mod.rs +++ b/cmd/soroban-cli/src/commands/keys/mod.rs @@ -8,7 +8,7 @@ pub mod fund; pub mod generate; pub mod ls; pub mod rm; -pub mod show; +pub mod secret; #[derive(Debug, Parser)] pub enum Cmd { @@ -30,8 +30,8 @@ pub enum Cmd { /// Remove an identity Rm(rm::Cmd), - /// Given an identity return its private key - Show(show::Cmd), + /// Output an identity's secret key + Secret(secret::Cmd), /// Set the default identity that will be used on all commands. /// This allows you to skip `--source-account` or setting a environment @@ -61,7 +61,7 @@ pub enum Error { Ls(#[from] ls::Error), #[error(transparent)] - Show(#[from] show::Error), + Show(#[from] secret::Error), #[error(transparent)] Default(#[from] default::Error), @@ -76,7 +76,7 @@ impl Cmd { Cmd::Generate(cmd) => cmd.run(global_args).await?, Cmd::Ls(cmd) => cmd.run()?, Cmd::Rm(cmd) => cmd.run()?, - Cmd::Show(cmd) => cmd.run()?, + Cmd::Secret(cmd) => cmd.run()?, Cmd::Default(cmd) => cmd.run(global_args)?, }; Ok(()) diff --git a/cmd/soroban-cli/src/commands/keys/show.rs b/cmd/soroban-cli/src/commands/keys/secret.rs similarity index 95% rename from cmd/soroban-cli/src/commands/keys/show.rs rename to cmd/soroban-cli/src/commands/keys/secret.rs index 58c47740c..d28445247 100644 --- a/cmd/soroban-cli/src/commands/keys/show.rs +++ b/cmd/soroban-cli/src/commands/keys/secret.rs @@ -16,6 +16,7 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] #[group(skip)] +#[command(name = "secret", alias = "show")] pub struct Cmd { /// Name of identity to lookup, default is test identity pub name: String, From a5f02595a434e168c443fbb7147264a6e180821b Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Fri, 20 Dec 2024 18:39:35 +1000 Subject: [PATCH 70/77] keys: valid keys when added (#1812) Co-authored-by: Willem Wyndham Co-authored-by: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> --- FULL_HELP_DOCS.md | 4 +-- cmd/soroban-cli/src/config/secret.rs | 45 ++++++++-------------------- 2 files changed, 14 insertions(+), 35 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 208ec1e84..6b67e32a0 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -961,8 +961,8 @@ Add a new identity (keypair, ledger, macOS keychain) ###### **Options:** -* `--secret-key` — Add using `secret_key` Can provide with `SOROBAN_SECRET_KEY` -* `--seed-phrase` — Add using 12 word seed phrase to generate `secret_key` +* `--secret-key` — (deprecated) Enter secret (S) key when prompted +* `--seed-phrase` — (deprecated) Enter key using 12-24 word seed phrase * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index d6de1b6ea..00cec12f6 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -11,8 +11,6 @@ use crate::{ #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("invalid secret key")] - InvalidSecretKey, // #[error("seed_phrase must be 12 words long, found {len}")] // InvalidSeedPhrase { len: usize }, #[error("secret input error")] @@ -23,8 +21,8 @@ pub enum Error { SeedPhrase(#[from] sep5::error::Error), #[error(transparent)] Ed25519(#[from] ed25519_dalek::SignatureError), - #[error("Invalid address {0}")] - InvalidAddress(String), + #[error("cannot parse secret (S) or seed phrase (12 or 24 word)")] + InvalidSecretOrSeedPhrase, #[error(transparent)] Signer(#[from] signer::Error), } @@ -32,12 +30,11 @@ pub enum Error { #[derive(Debug, clap::Args, Clone)] #[group(skip)] pub struct Args { - /// Add using `secret_key` - /// Can provide with `SOROBAN_SECRET_KEY` - #[arg(long, conflicts_with = "seed_phrase")] + /// (deprecated) Enter secret (S) key when prompted + #[arg(long)] pub secret_key: bool, - /// Add using 12 word seed phrase to generate `secret_key` - #[arg(long, conflicts_with = "secret_key")] + /// (deprecated) Enter key using 12-24 word seed phrase + #[arg(long)] pub seed_phrase: bool, } @@ -45,30 +42,12 @@ impl Args { pub fn read_secret(&self) -> Result { if let Ok(secret_key) = std::env::var("SOROBAN_SECRET_KEY") { Ok(Secret::SecretKey { secret_key }) - } else if self.secret_key { - println!("Type a secret key: "); - let secret_key = read_password()?; - let secret_key = PrivateKey::from_string(&secret_key) - .map_err(|_| Error::InvalidSecretKey)? - .to_string(); - Ok(Secret::SecretKey { secret_key }) - } else if self.seed_phrase { - println!("Type a 12 word seed phrase: "); - let seed_phrase = read_password()?; - let seed_phrase: Vec<&str> = seed_phrase.split_whitespace().collect(); - // if seed_phrase.len() != 12 { - // let len = seed_phrase.len(); - // return Err(Error::InvalidSeedPhrase { len }); - // } - Ok(Secret::SeedPhrase { - seed_phrase: seed_phrase - .into_iter() - .map(ToString::to_string) - .collect::>() - .join(" "), - }) } else { - Err(Error::PasswordRead {}) + println!("Type a secret key or 12/24 word seed phrase:"); + let secret_key = read_password()?; + secret_key + .parse() + .map_err(|_| Error::InvalidSecretOrSeedPhrase) } } } @@ -93,7 +72,7 @@ impl FromStr for Secret { seed_phrase: s.to_string(), }) } else { - Err(Error::InvalidAddress(s.to_string())) + Err(Error::InvalidSecretOrSeedPhrase) } } } From 1c0d4e6e528452d7a7d020ef12ce39e475434f4a Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Fri, 20 Dec 2024 13:00:39 -0500 Subject: [PATCH 71/77] Fix/rpc header (#1799) * Use network.rpc_client() to get a contract's spec this will make sure that we're adding the necessary rpc provider headers, if they are required for the given provider * Use self.rpc_client() in network for creating a new rpc client * Refactor TestEnv to have a network field * Test that rpc_headers are being passed on rpc provider requests * Fix operations int test * Clippy * Add CC-1.0 to allowed licenses in deny.toml https://stellarfoundation.slack.com/archives/C92PPVBPT/p1734657921992129 * fix * Use workspace httpmock dep also - move soroban-test httpmock dep to dev-dependencies - use workspace dep for stellar-ledger test --------- Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- Cargo.lock | 1 + Cargo.toml | 1 + cmd/crates/soroban-test/Cargo.toml | 2 +- cmd/crates/soroban-test/src/lib.rs | 45 ++++++--- .../tests/it/integration/bindings.rs | 4 +- .../tests/it/integration/hello_world.rs | 4 +- .../tests/it/integration/tx/operations.rs | 24 ++--- cmd/crates/soroban-test/tests/it/main.rs | 1 + .../soroban-test/tests/it/rpc_provider.rs | 97 +++++++++++++++++++ cmd/crates/stellar-ledger/Cargo.toml | 2 +- cmd/soroban-cli/src/config/network.rs | 2 +- cmd/soroban-cli/src/get_spec.rs | 2 +- deny.toml | 1 + 13 files changed, 155 insertions(+), 31 deletions(-) create mode 100644 cmd/crates/soroban-test/tests/it/rpc_provider.rs diff --git a/Cargo.lock b/Cargo.lock index cbe1678d6..d69fbaa51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4601,6 +4601,7 @@ dependencies = [ "ed25519-dalek", "fs_extra", "hex", + "httpmock", "predicates", "sep5", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index 839ca9cd0..702de93c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -105,6 +105,7 @@ toml_edit = "0.22.20" toml = "0.8.19" reqwest = "0.12.7" predicates = "3.1.2" +httpmock = "0.7.0" [profile.test-wasms] inherits = "release" diff --git a/cmd/crates/soroban-test/Cargo.toml b/cmd/crates/soroban-test/Cargo.toml index d035652d1..ddb10d5f7 100644 --- a/cmd/crates/soroban-test/Cargo.toml +++ b/cmd/crates/soroban-test/Cargo.toml @@ -33,7 +33,6 @@ predicates = { workspace = true } fs_extra = "1.3.0" toml = { workspace = true } - [dev-dependencies] serde_json = "1.0.93" which = { workspace = true } @@ -42,6 +41,7 @@ walkdir = "2.4.0" ulid.workspace = true ed25519-dalek = { workspace = true } hex = { workspace = true } +httpmock = { workspace = true } [features] it = [] diff --git a/cmd/crates/soroban-test/src/lib.rs b/cmd/crates/soroban-test/src/lib.rs index 492d3bb97..4f36a0b33 100644 --- a/cmd/crates/soroban-test/src/lib.rs +++ b/cmd/crates/soroban-test/src/lib.rs @@ -58,8 +58,7 @@ pub enum Error { /// its own `TempDir` where it will save test-specific configuration. pub struct TestEnv { pub temp_dir: TempDir, - pub rpc_url: String, - pub network_passphrase: String, + pub network: network::Network, } impl Default for TestEnv { @@ -67,8 +66,11 @@ impl Default for TestEnv { let temp_dir = TempDir::new().unwrap(); Self { temp_dir, - rpc_url: "http://localhost:8889/soroban/rpc".to_string(), - network_passphrase: LOCAL_NETWORK_PASSPHRASE.to_string(), + network: network::Network { + rpc_url: "http://localhost:8889/soroban/rpc".to_string(), + network_passphrase: LOCAL_NETWORK_PASSPHRASE.to_string(), + rpc_headers: [].to_vec(), + }, } } } @@ -102,12 +104,21 @@ impl TestEnv { } pub fn with_rpc_url(rpc_url: &str) -> TestEnv { - let mut env = TestEnv { - rpc_url: rpc_url.to_string(), - ..Default::default() + let mut env = TestEnv::default(); + env.network.rpc_url = rpc_url.to_string(); + if let Ok(network_passphrase) = std::env::var("STELLAR_NETWORK_PASSPHRASE") { + env.network.network_passphrase = network_passphrase; }; + env.generate_account("test", None).assert().success(); + env + } + + pub fn with_rpc_provider(rpc_url: &str, rpc_headers: Vec<(String, String)>) -> TestEnv { + let mut env = TestEnv::default(); + env.network.rpc_url = rpc_url.to_string(); + env.network.rpc_headers = rpc_headers; if let Ok(network_passphrase) = std::env::var("STELLAR_NETWORK_PASSPHRASE") { - env.network_passphrase = network_passphrase; + env.network.network_passphrase = network_passphrase; }; env.generate_account("test", None).assert().success(); env @@ -131,13 +142,25 @@ impl TestEnv { /// to be the internal `temp_dir`. pub fn new_assert_cmd(&self, subcommand: &str) -> Command { let mut cmd: Command = self.bin(); + cmd.arg(subcommand) .env("SOROBAN_ACCOUNT", TEST_ACCOUNT) - .env("SOROBAN_RPC_URL", &self.rpc_url) + .env("SOROBAN_RPC_URL", &self.network.rpc_url) .env("SOROBAN_NETWORK_PASSPHRASE", LOCAL_NETWORK_PASSPHRASE) .env("XDG_CONFIG_HOME", self.temp_dir.join("config").as_os_str()) .env("XDG_DATA_HOME", self.temp_dir.join("data").as_os_str()) .current_dir(&self.temp_dir); + + if !self.network.rpc_headers.is_empty() { + cmd.env( + "STELLAR_RPC_HEADERS", + format!( + "{}:{}", + &self.network.rpc_headers[0].0, &self.network.rpc_headers[0].1 + ), + ); + } + cmd } @@ -234,7 +257,7 @@ impl TestEnv { let config_dir = Some(self.dir().to_path_buf()); config::Args { network: network::Args { - rpc_url: Some(self.rpc_url.clone()), + rpc_url: Some(self.network.rpc_url.clone()), rpc_headers: [].to_vec(), network_passphrase: Some(LOCAL_NETWORK_PASSPHRASE.to_string()), network: None, @@ -305,7 +328,7 @@ impl TestEnv { } pub fn client(&self) -> soroban_rpc::Client { - soroban_rpc::Client::new(&self.rpc_url).unwrap() + self.network.rpc_client().unwrap() } } diff --git a/cmd/crates/soroban-test/tests/it/integration/bindings.rs b/cmd/crates/soroban-test/tests/it/integration/bindings.rs index feb7f2ef8..4080cc110 100644 --- a/cmd/crates/soroban-test/tests/it/integration/bindings.rs +++ b/cmd/crates/soroban-test/tests/it/integration/bindings.rs @@ -13,7 +13,7 @@ async fn invoke_test_generate_typescript_bindings() { "--network-passphrase", LOCAL_NETWORK_PASSPHRASE, "--rpc-url", - &sandbox.rpc_url, + &sandbox.network.rpc_url, "--output-dir", &outdir.display().to_string(), "--overwrite", @@ -43,7 +43,7 @@ async fn invoke_test_bindings_context_failure() { "--network-passphrase", LOCAL_NETWORK_PASSPHRASE, "--rpc-url", - &sandbox.rpc_url, + &sandbox.network.rpc_url, "--output-dir", &outdir.display().to_string(), "--overwrite", diff --git a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs index 4464e532f..e63fdd4b4 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -27,7 +27,7 @@ async fn invoke_view_with_non_existent_source_account() { #[allow(clippy::too_many_lines)] async fn invoke() { let sandbox = &TestEnv::new(); - let c = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let c = sandbox.network.rpc_client().unwrap(); let GetLatestLedgerResponse { sequence, .. } = c.get_latest_ledger().await.unwrap(); sandbox .new_assert_cmd("keys") @@ -365,7 +365,7 @@ async fn fetch(sandbox: &TestEnv, id: &str) { let f = sandbox.dir().join("contract.wasm"); let cmd = sandbox.cmd_arr::(&[ "--rpc-url", - &sandbox.rpc_url, + &sandbox.network.rpc_url, "--network-passphrase", LOCAL_NETWORK_PASSPHRASE, "--id", diff --git a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs index 1ce1f06c9..d9bc2ac63 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -66,7 +66,7 @@ async fn create_account() { .success() .stdout_as_str(); let test = test_address(sandbox); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let test_account = client.get_account(&test).await.unwrap(); println!("test account has a balance of {}", test_account.balance); let starting_balance = ONE_XLM * 100; @@ -92,7 +92,7 @@ async fn create_account() { #[tokio::test] async fn payment() { let sandbox = &TestEnv::new(); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let (test, test1) = setup_accounts(sandbox); let test_account = client.get_account(&test).await.unwrap(); println!("test account has a balance of {}", test_account.balance); @@ -125,7 +125,7 @@ async fn payment() { #[tokio::test] async fn bump_sequence() { let sandbox = &TestEnv::new(); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let test = test_address(sandbox); let before = client.get_account(&test).await.unwrap(); let amount = 50; @@ -148,7 +148,7 @@ async fn bump_sequence() { #[tokio::test] async fn account_merge() { let sandbox = &TestEnv::new(); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let (test, test1) = setup_accounts(sandbox); let before = client.get_account(&test).await.unwrap(); let before1 = client.get_account(&test1).await.unwrap(); @@ -188,7 +188,7 @@ async fn set_trustline_flags() { .success(); let id = contract_id_hash_from_asset( asset.parse::().unwrap(), - &sandbox.network_passphrase, + &sandbox.network.network_passphrase, ); // sandbox // .new_assert_cmd("contract") @@ -224,7 +224,7 @@ async fn set_trustline_flags() { #[tokio::test] async fn set_options_add_signer() { let sandbox = &TestEnv::new(); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let (test, test1) = setup_accounts(sandbox); let before = client.get_account(&test).await.unwrap(); sandbox @@ -286,7 +286,7 @@ fn build_and_run(sandbox: &TestEnv, cmd: &str, args: &[&str]) -> String { #[tokio::test] async fn set_options() { let sandbox = &TestEnv::new(); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let (test, alice) = setup_accounts(sandbox); let before = client.get_account(&test).await.unwrap(); assert!(before.inflation_dest.is_none()); @@ -356,7 +356,7 @@ async fn set_options() { #[tokio::test] async fn set_some_options() { let sandbox = &TestEnv::new(); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let test = test_address(sandbox); let before = client.get_account(&test).await.unwrap(); assert!(before.inflation_dest.is_none()); @@ -451,7 +451,7 @@ async fn change_trust() { // wrap_cmd(&asset).run().await.unwrap(); let id = contract_id_hash_from_asset( asset.parse::().unwrap(), - &sandbox.network_passphrase, + &sandbox.network.network_passphrase, ); sandbox .new_assert_cmd("contract") @@ -529,7 +529,7 @@ async fn change_trust() { async fn manage_data() { let sandbox = &TestEnv::new(); let (test, _) = setup_accounts(sandbox); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let key = "test"; let value = "beefface"; sandbox @@ -573,7 +573,7 @@ async fn manage_data() { } async fn issue_asset(sandbox: &TestEnv, test: &str, asset: &str, limit: u64, initial_balance: u64) { - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let test_before = client.get_account(test).await.unwrap(); sandbox .new_assert_cmd("tx") @@ -633,7 +633,7 @@ async fn issue_asset(sandbox: &TestEnv, test: &str, asset: &str, limit: u64, ini #[tokio::test] async fn multi_create_accounts() { let sandbox = &TestEnv::new(); - let client = soroban_rpc::Client::new(&sandbox.rpc_url).unwrap(); + let client = sandbox.network.rpc_client().unwrap(); let nums: Vec = (1..=3).collect(); let mut accounts: Vec<(String, String)> = nums .iter() diff --git a/cmd/crates/soroban-test/tests/it/main.rs b/cmd/crates/soroban-test/tests/it/main.rs index e06c1a47d..4dc54a194 100644 --- a/cmd/crates/soroban-test/tests/it/main.rs +++ b/cmd/crates/soroban-test/tests/it/main.rs @@ -6,5 +6,6 @@ mod init; // #[cfg(feature = "it")] mod integration; mod plugin; +mod rpc_provider; mod util; mod version; diff --git a/cmd/crates/soroban-test/tests/it/rpc_provider.rs b/cmd/crates/soroban-test/tests/it/rpc_provider.rs new file mode 100644 index 000000000..04c4c1bdc --- /dev/null +++ b/cmd/crates/soroban-test/tests/it/rpc_provider.rs @@ -0,0 +1,97 @@ +use httpmock::{prelude::*, Mock}; +use serde_json::json; +use soroban_rpc::{GetEventsResponse, GetNetworkResponse}; +use soroban_test::{TestEnv, LOCAL_NETWORK_PASSPHRASE}; + +#[tokio::test] +async fn test_use_rpc_provider_with_auth_header() { + // mock out http request to rpc provider + let server = MockServer::start(); + let generate_account_mock = mock_generate_account(&server); + let get_network_mock = mock_get_network(&server); + let get_events_mock = mock_get_events(&server); + + // create a new test environment with the mock server + let rpc_url = server.url(""); + let rpc_headers = vec![("Authorization".to_string(), "Bearer test-token".to_string())]; + let sandbox = &TestEnv::with_rpc_provider(&rpc_url, rpc_headers); + + sandbox + .new_assert_cmd("events") + .arg("--start-ledger") + .arg("1000") + .assert() + .success(); + + // generate account is being called in `with_rpc_provider` + generate_account_mock.assert(); + // get_network and get_events are being called in the `stellar events` command + get_network_mock.assert(); + get_events_mock.assert(); +} + +fn mock_generate_account(server: &MockServer) -> Mock { + server.mock(|when, then| { + when.method(GET) + .path("/friendbot") + .header("accept", "*/*") + .header("user-agent", "soroban-cli/22.0.1"); //update this to be future proof + then.status(200); + }) +} + +fn mock_get_network(server: &MockServer) -> Mock { + server.mock(|when, then| { + when.method(POST) + .path("/") + .header("authorization", "Bearer test-token") + .json_body(json!({ + "jsonrpc": "2.0", + "id": 0, + "method": "getNetwork" + })); + + then.status(200).json_body(json!({ + "jsonrpc": "2.0", + "id": 0, + "result": GetNetworkResponse { + friendbot_url: None, + passphrase: LOCAL_NETWORK_PASSPHRASE.to_string(), + protocol_version: 22} + })); + }) +} + +fn mock_get_events(server: &MockServer) -> Mock { + server.mock(|when, then| { + when.method(POST) + .path("/") + .header("authorization", "Bearer test-token") + .json_body(json!({ + "jsonrpc": "2.0", + "id": 1, + "method": "getEvents", + "params": { + "startLedger": 1000, + "filters": [ + { + "contractIds": [], + "topics": [] + } + ], + "pagination": { + "limit": 10 + } + } + })); + + then.status(200).json_body(json!({ + "jsonrpc": "2.0", + "id": 1, + "result": GetEventsResponse { + events: vec![], + latest_ledger: 1000 + } + })); + }) +} diff --git a/cmd/crates/stellar-ledger/Cargo.toml b/cmd/crates/stellar-ledger/Cargo.toml index b3d6318a4..f06d17a2b 100644 --- a/cmd/crates/stellar-ledger/Cargo.toml +++ b/cmd/crates/stellar-ledger/Cargo.toml @@ -51,7 +51,7 @@ log = "0.4.21" once_cell = "1.19.0" pretty_assertions = "1.2.1" serial_test = "3.0.0" -httpmock = "0.7.0-rc.1" +httpmock = { workspace = true } test-case = "3.3.1" testcontainers = "0.20.1" diff --git a/cmd/soroban-cli/src/config/network.rs b/cmd/soroban-cli/src/config/network.rs index 829716753..e64a0ee77 100644 --- a/cmd/soroban-cli/src/config/network.rs +++ b/cmd/soroban-cli/src/config/network.rs @@ -170,7 +170,7 @@ impl Network { local_url.set_query(Some(&format!("addr={addr}"))); Ok(local_url) } else { - let client = Client::new(&self.rpc_url)?; + let client = self.rpc_client()?; let network = client.get_network().await?; tracing::debug!("network {network:?}"); let url = client.friendbot_url().await?; diff --git a/cmd/soroban-cli/src/get_spec.rs b/cmd/soroban-cli/src/get_spec.rs index 26e609543..f2da15863 100644 --- a/cmd/soroban-cli/src/get_spec.rs +++ b/cmd/soroban-cli/src/get_spec.rs @@ -44,7 +44,7 @@ pub async fn get_remote_contract_spec( |c| c.get_network().map_err(Error::from), )?; tracing::trace!(?network); - let client = rpc::Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; // Get contract data let r = client.get_contract_data(contract_id).await?; tracing::trace!("{r:?}"); diff --git a/deny.toml b/deny.toml index 9817c3e79..600bfec02 100644 --- a/deny.toml +++ b/deny.toml @@ -110,6 +110,7 @@ allow = [ "Unicode-DFS-2016", "ISC", "BSD-2-Clause", + "CC0-1.0", ] # List of explicitly disallowed licenses # See https://spdx.org/licenses/ for list of possible licenses From 497efe8d9b7dc9be3d8feb1bb90b5098938e9294 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Fri, 20 Dec 2024 14:58:10 -0500 Subject: [PATCH 72/77] feat(contract invoke): support contract aliases when parsing address (#1765) * feat(contract invoke): support contract aliases when parsing address fixes: 1764 * fix: only parse with address typedefs * fix: fmt * split two logics combined into one fn * feat: rename to unresolvedX to make it names clearer * fix: fmt and add tests * feat: ban overlapping names * fix: tests * fix: tests --------- Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- cmd/crates/soroban-test/tests/it/config.rs | 44 ++++++++++++ .../tests/it/integration/custom_types.rs | 26 ++++++- .../soroban-test/tests/it/integration/tx.rs | 2 +- .../tests/it/integration/tx/operations.rs | 2 +- .../soroban-test/tests/it/integration/util.rs | 11 +-- .../src/commands/contract/arg_parsing.rs | 60 ++++++++++++----- .../src/commands/contract/fetch.rs | 2 +- .../src/commands/contract/info/shared.rs | 2 +- .../src/commands/contract/invoke.rs | 2 +- cmd/soroban-cli/src/commands/events.rs | 2 +- .../src/commands/snapshot/create.rs | 4 +- .../src/commands/tx/op/add/args.rs | 2 +- cmd/soroban-cli/src/config/address.rs | 44 +++++++----- cmd/soroban-cli/src/config/alias.rs | 34 ++++++---- cmd/soroban-cli/src/config/locator.rs | 10 +++ cmd/soroban-cli/src/config/mod.rs | 8 ++- cmd/soroban-cli/src/config/sc_address.rs | 67 +++++++++++++++++++ cmd/soroban-cli/src/key.rs | 2 +- 18 files changed, 263 insertions(+), 61 deletions(-) create mode 100644 cmd/soroban-cli/src/config/sc_address.rs diff --git a/cmd/crates/soroban-test/tests/it/config.rs b/cmd/crates/soroban-test/tests/it/config.rs index e81233b6e..2e5bc21c1 100644 --- a/cmd/crates/soroban-test/tests/it/config.rs +++ b/cmd/crates/soroban-test/tests/it/config.rs @@ -393,3 +393,47 @@ fn set_default_network() { .stdout(predicate::str::contains("STELLAR_NETWORK=testnet")) .success(); } + +#[test] +fn cannot_create_contract_with_test_name() { + let sandbox = TestEnv::default(); + sandbox + .new_assert_cmd("keys") + .arg("generate") + .arg("--no-fund") + .arg("d") + .assert() + .success(); + sandbox + .new_assert_cmd("contract") + .arg("alias") + .arg("add") + .arg("d") + .arg("--id=CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE") + .assert() + .stderr(predicate::str::contains("cannot overlap with key")) + .failure(); +} + +#[test] +fn cannot_create_key_with_alias() { + let sandbox = TestEnv::default(); + sandbox + .new_assert_cmd("contract") + .arg("alias") + .arg("add") + .arg("t") + .arg("--id=CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE") + .assert() + .success(); + sandbox + .new_assert_cmd("keys") + .arg("generate") + .arg("--no-fund") + .arg("t") + .assert() + .stderr(predicate::str::contains( + "cannot overlap with contract alias", + )) + .failure(); +} diff --git a/cmd/crates/soroban-test/tests/it/integration/custom_types.rs b/cmd/crates/soroban-test/tests/it/integration/custom_types.rs index 6cdb61192..f4c2be61b 100644 --- a/cmd/crates/soroban-test/tests/it/integration/custom_types.rs +++ b/cmd/crates/soroban-test/tests/it/integration/custom_types.rs @@ -5,7 +5,7 @@ use soroban_test::TestEnv; use crate::integration::util::{deploy_custom, extend_contract}; -use super::util::invoke_with_roundtrip; +use super::util::{invoke, invoke_with_roundtrip}; fn invoke_custom(e: &TestEnv, id: &str, func: &str) -> assert_cmd::Command { let mut s = e.new_assert_cmd("contract"); @@ -40,7 +40,9 @@ async fn parse() { negative_i32(sandbox, id).await; negative_i64(sandbox, id).await; account_address(sandbox, id).await; + account_address_with_alias(sandbox, id).await; contract_address(sandbox, id).await; + contract_address_with_alias(sandbox, id).await; bytes(sandbox, id).await; const_enum(sandbox, id).await; number_arg_return_ok(sandbox, id); @@ -237,6 +239,12 @@ async fn account_address(sandbox: &TestEnv, id: &str) { .await; } +async fn account_address_with_alias(sandbox: &TestEnv, id: &str) { + let res = invoke(sandbox, id, "addresse", &json!("test").to_string()).await; + let test = format!("\"{}\"", super::tx::operations::test_address(sandbox)); + assert_eq!(test, res); +} + async fn contract_address(sandbox: &TestEnv, id: &str) { invoke_with_roundtrip( sandbox, @@ -247,6 +255,22 @@ async fn contract_address(sandbox: &TestEnv, id: &str) { .await; } +async fn contract_address_with_alias(sandbox: &TestEnv, id: &str) { + sandbox + .new_assert_cmd("contract") + .arg("alias") + .arg("add") + .arg("test_contract") + .arg("--id=CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE") + .assert() + .success(); + let res = invoke(sandbox, id, "addresse", &json!("test_contract").to_string()).await; + assert_eq!( + res, + "\"CA3D5KRYM6CB7OWQ6TWYRR3Z4T7GNZLKERYNZGGA5SOAOPIFY6YQGAXE\"" + ); +} + async fn bytes(sandbox: &TestEnv, id: &str) { invoke_with_roundtrip(sandbox, id, "bytes", json!("7374656c6c6172")).await; } diff --git a/cmd/crates/soroban-test/tests/it/integration/tx.rs b/cmd/crates/soroban-test/tests/it/integration/tx.rs index c3cd2693b..3fa85bc09 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx.rs @@ -4,7 +4,7 @@ use soroban_test::{AssertExt, TestEnv}; use crate::integration::util::{deploy_contract, DeployKind, HELLO_WORLD}; -mod operations; +pub mod operations; #[tokio::test] async fn simulate() { diff --git a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs index d9bc2ac63..8c894e5dc 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -11,7 +11,7 @@ use crate::integration::{ util::{deploy_contract, DeployKind, HELLO_WORLD}, }; -fn test_address(sandbox: &TestEnv) -> String { +pub fn test_address(sandbox: &TestEnv) -> String { sandbox .new_assert_cmd("keys") .arg("address") diff --git a/cmd/crates/soroban-test/tests/it/integration/util.rs b/cmd/crates/soroban-test/tests/it/integration/util.rs index 486b00a1b..fc7f824b6 100644 --- a/cmd/crates/soroban-test/tests/it/integration/util.rs +++ b/cmd/crates/soroban-test/tests/it/integration/util.rs @@ -11,16 +11,19 @@ pub const CUSTOM_TYPES: &Wasm = &Wasm::Custom("test-wasms", "test_custom_types") pub const CUSTOM_ACCOUNT: &Wasm = &Wasm::Custom("test-wasms", "test_custom_account"); pub const SWAP: &Wasm = &Wasm::Custom("test-wasms", "test_swap"); +pub async fn invoke(sandbox: &TestEnv, id: &str, func: &str, data: &str) -> String { + sandbox + .invoke_with_test(&["--id", id, "--", func, &format!("--{func}"), data]) + .await + .unwrap() +} pub async fn invoke_with_roundtrip(e: &TestEnv, id: &str, func: &str, data: D) where D: Display, { let data = data.to_string(); println!("{data}"); - let res = e - .invoke_with_test(&["--id", id, "--", func, &format!("--{func}"), &data]) - .await - .unwrap(); + let res = invoke(e, id, func, &data).await; assert_eq!(res, data); } diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index 21fa2f383..a223851ca 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -9,12 +9,14 @@ use ed25519_dalek::SigningKey; use heck::ToKebabCase; use crate::xdr::{ - self, Hash, InvokeContractArgs, ScAddress, ScSpecEntry, ScSpecFunctionV0, ScSpecTypeDef, ScVal, - ScVec, + self, Hash, InvokeContractArgs, ScSpecEntry, ScSpecFunctionV0, ScSpecTypeDef, ScVal, ScVec, }; use crate::commands::txn_result::TxnResult; -use crate::config::{self}; +use crate::config::{ + self, + sc_address::{self, UnresolvedScAddress}, +}; use soroban_spec_tools::Spec; #[derive(thiserror::Error, Debug)] @@ -43,6 +45,10 @@ pub enum Error { MissingArgument(String), #[error("")] MissingFileArg(PathBuf), + #[error(transparent)] + ScAddress(#[from] sc_address::Error), + #[error(transparent)] + Config(#[from] config::Error), } pub fn build_host_function_parameters( @@ -80,18 +86,18 @@ pub fn build_host_function_parameters( .map(|i| { let name = i.name.to_utf8_string()?; if let Some(mut val) = matches_.get_raw(&name) { - let mut s = val.next().unwrap().to_string_lossy().to_string(); + let mut s = val + .next() + .unwrap() + .to_string_lossy() + .trim_matches('"') + .to_string(); if matches!(i.type_, ScSpecTypeDef::Address) { - let cmd = crate::commands::keys::address::Cmd { - name: s.clone(), - hd_path: Some(0), - locator: config.locator.clone(), - }; - if let Ok(address) = cmd.public_key() { - s = address.to_string(); - } - if let Ok(key) = cmd.private_key() { - signers.push(key); + let addr = resolve_address(&s, config)?; + let signer = resolve_signer(&s, config); + s = addr; + if let Some(signer) = signer { + signers.push(signer); } } spec.from_string(&s, &i.type_) @@ -125,7 +131,7 @@ pub fn build_host_function_parameters( }) .collect::, Error>>()?; - let contract_address_arg = ScAddress::Contract(Hash(contract_id.0)); + let contract_address_arg = xdr::ScAddress::Contract(Hash(contract_id.0)); let function_symbol_arg = function .try_into() .map_err(|()| Error::FunctionNameTooLong(function.clone()))?; @@ -246,3 +252,27 @@ pub fn output_to_string( } Ok(TxnResult::Res(res_str)) } + +fn resolve_address(addr_or_alias: &str, config: &config::Args) -> Result { + let sc_address: UnresolvedScAddress = addr_or_alias.parse().unwrap(); + let account = match sc_address { + UnresolvedScAddress::Resolved(addr) => addr.to_string(), + addr @ UnresolvedScAddress::Alias(_) => { + let addr = addr.resolve(&config.locator, &config.get_network()?.network_passphrase)?; + match addr { + xdr::ScAddress::Account(account) => account.to_string(), + contract @ xdr::ScAddress::Contract(_) => contract.to_string(), + } + } + }; + Ok(account) +} + +fn resolve_signer(addr_or_alias: &str, config: &config::Args) -> Option { + let cmd = crate::commands::keys::address::Cmd { + name: addr_or_alias.to_string(), + hd_path: Some(0), + locator: config.locator.clone(), + }; + cmd.private_key().ok() +} diff --git a/cmd/soroban-cli/src/commands/contract/fetch.rs b/cmd/soroban-cli/src/commands/contract/fetch.rs index 31ed191ff..d73aac3b7 100644 --- a/cmd/soroban-cli/src/commands/contract/fetch.rs +++ b/cmd/soroban-cli/src/commands/contract/fetch.rs @@ -22,7 +22,7 @@ use crate::{ pub struct Cmd { /// Contract ID to fetch #[arg(long = "id", env = "STELLAR_CONTRACT_ID")] - pub contract_id: config::ContractAddress, + pub contract_id: config::UnresolvedContract, /// Where to write output otherwise stdout is used #[arg(long, short = 'o')] pub out_file: Option, diff --git a/cmd/soroban-cli/src/commands/contract/info/shared.rs b/cmd/soroban-cli/src/commands/contract/info/shared.rs index 6023b03cf..13355268f 100644 --- a/cmd/soroban-cli/src/commands/contract/info/shared.rs +++ b/cmd/soroban-cli/src/commands/contract/info/shared.rs @@ -47,7 +47,7 @@ pub struct Args { conflicts_with = "wasm", conflicts_with = "wasm_hash" )] - pub contract_id: Option, + pub contract_id: Option, #[command(flatten)] pub network: network::Args, #[command(flatten)] diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index c7b631343..bd069698d 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -40,7 +40,7 @@ use soroban_spec_tools::contract; pub struct Cmd { /// Contract ID to invoke #[arg(long = "id", env = "STELLAR_CONTRACT_ID")] - pub contract_id: config::ContractAddress, + pub contract_id: config::UnresolvedContract, // For testing only #[arg(skip)] pub wasm: Option, diff --git a/cmd/soroban-cli/src/commands/events.rs b/cmd/soroban-cli/src/commands/events.rs index 48d79c1b7..16ef410bd 100644 --- a/cmd/soroban-cli/src/commands/events.rs +++ b/cmd/soroban-cli/src/commands/events.rs @@ -42,7 +42,7 @@ pub struct Cmd { num_args = 1..=6, help_heading = "FILTERS" )] - contract_ids: Vec, + contract_ids: Vec, /// 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. diff --git a/cmd/soroban-cli/src/commands/snapshot/create.rs b/cmd/soroban-cli/src/commands/snapshot/create.rs index a3ba865fa..9ad39953f 100644 --- a/cmd/soroban-cli/src/commands/snapshot/create.rs +++ b/cmd/soroban-cli/src/commands/snapshot/create.rs @@ -34,7 +34,7 @@ use crate::{ tx::builder, utils::get_name_from_stellar_asset_contract_storage, }; -use crate::{config::address::Address, utils::http}; +use crate::{config::address::UnresolvedMuxedAccount, utils::http}; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, ValueEnum)] pub enum Output { @@ -413,7 +413,7 @@ impl Cmd { // Resolve an account address to an account id. The address can be a // G-address or a key name (as in `stellar keys address NAME`). fn resolve_account(&self, address: &str) -> Option { - let address: Address = address.parse().ok()?; + let address: UnresolvedMuxedAccount = address.parse().ok()?; Some(AccountId(xdr::PublicKey::PublicKeyTypeEd25519( match address.resolve_muxed_account(&self.locator, None).ok()? { diff --git a/cmd/soroban-cli/src/commands/tx/op/add/args.rs b/cmd/soroban-cli/src/commands/tx/op/add/args.rs index f1858e0b0..51ee4d476 100644 --- a/cmd/soroban-cli/src/commands/tx/op/add/args.rs +++ b/cmd/soroban-cli/src/commands/tx/op/add/args.rs @@ -23,7 +23,7 @@ pub struct Args { visible_alias = "op-source", env = "STELLAR_OPERATION_SOURCE_ACCOUNT" )] - pub operation_source_account: Option, + pub operation_source_account: Option, } impl Args { diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 066bc8d91..356c7a991 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -6,14 +6,14 @@ use super::{locator, secret}; /// Address can be either a public key or eventually an alias of a address. #[derive(Clone, Debug)] -pub enum Address { - MuxedAccount(xdr::MuxedAccount), +pub enum UnresolvedMuxedAccount { + Resolved(xdr::MuxedAccount), AliasOrSecret(String), } -impl Default for Address { +impl Default for UnresolvedMuxedAccount { fn default() -> Self { - Address::AliasOrSecret(String::default()) + UnresolvedMuxedAccount::AliasOrSecret(String::default()) } } @@ -27,37 +27,49 @@ pub enum Error { CannotSign(xdr::MuxedAccount), } -impl FromStr for Address { +impl FromStr for UnresolvedMuxedAccount { type Err = Error; fn from_str(value: &str) -> Result { Ok(xdr::MuxedAccount::from_str(value).map_or_else( - |_| Address::AliasOrSecret(value.to_string()), - Address::MuxedAccount, + |_| UnresolvedMuxedAccount::AliasOrSecret(value.to_string()), + UnresolvedMuxedAccount::Resolved, )) } } -impl Address { +impl UnresolvedMuxedAccount { pub fn resolve_muxed_account( &self, locator: &locator::Args, hd_path: Option, ) -> Result { match self { - Address::MuxedAccount(muxed_account) => Ok(muxed_account.clone()), - Address::AliasOrSecret(alias) => alias.parse().or_else(|_| { - Ok(xdr::MuxedAccount::Ed25519( - locator.read_identity(alias)?.public_key(hd_path)?.0.into(), - )) - }), + UnresolvedMuxedAccount::Resolved(muxed_account) => Ok(muxed_account.clone()), + UnresolvedMuxedAccount::AliasOrSecret(alias) => { + Self::resolve_muxed_account_with_alias(alias, locator, hd_path) + } } } + pub fn resolve_muxed_account_with_alias( + alias: &str, + locator: &locator::Args, + hd_path: Option, + ) -> Result { + alias.parse().or_else(|_| { + Ok(xdr::MuxedAccount::Ed25519( + locator.read_identity(alias)?.public_key(hd_path)?.0.into(), + )) + }) + } + pub fn resolve_secret(&self, locator: &locator::Args) -> Result { match &self { - Address::MuxedAccount(muxed_account) => Err(Error::CannotSign(muxed_account.clone())), - Address::AliasOrSecret(alias) => Ok(locator.read_identity(alias)?), + UnresolvedMuxedAccount::Resolved(muxed_account) => { + Err(Error::CannotSign(muxed_account.clone())) + } + UnresolvedMuxedAccount::AliasOrSecret(alias) => Ok(locator.read_identity(alias)?), } } } diff --git a/cmd/soroban-cli/src/config/alias.rs b/cmd/soroban-cli/src/config/alias.rs index 9d1d8c11b..734925c4e 100644 --- a/cmd/soroban-cli/src/config/alias.rs +++ b/cmd/soroban-cli/src/config/alias.rs @@ -11,39 +11,49 @@ pub struct Data { /// 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), +pub enum UnresolvedContract { + Resolved(stellar_strkey::Contract), Alias(String), } -impl Default for ContractAddress { +impl Default for UnresolvedContract { fn default() -> Self { - ContractAddress::Alias(String::default()) + UnresolvedContract::Alias(String::default()) } } -impl FromStr for ContractAddress { +impl FromStr for UnresolvedContract { type Err = Infallible; fn from_str(value: &str) -> Result { Ok(stellar_strkey::Contract::from_str(value).map_or_else( - |_| ContractAddress::Alias(value.to_string()), - ContractAddress::ContractId, + |_| UnresolvedContract::Alias(value.to_string()), + UnresolvedContract::Resolved, )) } } -impl ContractAddress { +impl UnresolvedContract { pub fn resolve_contract_id( &self, locator: &locator::Args, network_passphrase: &str, ) -> Result { 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())), + UnresolvedContract::Resolved(contract) => Ok(*contract), + UnresolvedContract::Alias(alias) => { + Self::resolve_alias(alias, locator, network_passphrase) + } } } + + pub fn resolve_alias( + alias: &str, + locator: &locator::Args, + network_passphrase: &str, + ) -> Result { + locator + .get_contract_id(alias, network_passphrase)? + .ok_or_else(|| locator::Error::ContractNotFound(alias.to_owned())) + } } diff --git a/cmd/soroban-cli/src/config/locator.rs b/cmd/soroban-cli/src/config/locator.rs index 7e97f6796..1e26bbf7f 100644 --- a/cmd/soroban-cli/src/config/locator.rs +++ b/cmd/soroban-cli/src/config/locator.rs @@ -83,6 +83,10 @@ pub enum Error { UpgradeCheckReadFailed { path: PathBuf, error: io::Error }, #[error("Failed to write upgrade check file: {path}: {error}")] UpgradeCheckWriteFailed { path: PathBuf, error: io::Error }, + #[error("Contract alias {0}, cannot overlap with key")] + ContractAliasCannotOverlapWithKey(String), + #[error("Key cannot {0} cannot overlap with contract alias")] + KeyCannotOverlapWithContractAlias(String), } #[derive(Debug, clap::Args, Default, Clone)] @@ -163,6 +167,9 @@ impl Args { } pub fn write_identity(&self, name: &str, secret: &Secret) -> Result { + if let Ok(Some(_)) = self.load_contract_from_alias(name) { + return Err(Error::KeyCannotOverlapWithContractAlias(name.to_owned())); + } KeyType::Identity.write(name, secret, &self.config_dir()?) } @@ -286,6 +293,9 @@ impl Args { contract_id: &stellar_strkey::Contract, alias: &str, ) -> Result<(), Error> { + if self.read_identity(alias).is_ok() { + return Err(Error::ContractAliasCannotOverlapWithKey(alias.to_owned())); + } let path = self.alias_path(alias)?; let dir = path.parent().ok_or(Error::CannotAccessConfigDir)?; diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index a429ff434..1188d3bfa 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -1,4 +1,3 @@ -use address::Address; use clap::{arg, command}; use serde::{Deserialize, Serialize}; use std::{ @@ -19,11 +18,14 @@ pub mod alias; pub mod data; pub mod locator; pub mod network; +pub mod sc_address; pub mod secret; pub mod sign_with; pub mod upgrade_check; -pub use alias::ContractAddress; +pub use address::UnresolvedMuxedAccount; +pub use alias::UnresolvedContract; +pub use sc_address::UnresolvedScAddress; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -56,7 +58,7 @@ pub struct Args { /// or a seed phrase (--source "kite urban…"). /// If `--build-only` or `--sim-only` flags were NOT provided, this key will also be used to /// sign the final transaction. In that case, trying to sign with public key will fail. - pub source_account: Address, + pub source_account: UnresolvedMuxedAccount, #[arg(long)] /// If using a seed phrase, which hierarchical deterministic path to use, e.g. `m/44'/148'/{hd_path}`. Example: `--hd-path 1`. Default: `0` diff --git a/cmd/soroban-cli/src/config/sc_address.rs b/cmd/soroban-cli/src/config/sc_address.rs new file mode 100644 index 000000000..fc9c168f2 --- /dev/null +++ b/cmd/soroban-cli/src/config/sc_address.rs @@ -0,0 +1,67 @@ +use std::str::FromStr; + +use crate::xdr; + +use super::{address, locator, UnresolvedContract}; + +/// `ScAddress` can be either a resolved `xdr::ScAddress` or an alias of a `Contract` or `MuxedAccount`. +#[allow(clippy::module_name_repetitions)] +#[derive(Clone, Debug)] +pub enum UnresolvedScAddress { + Resolved(xdr::ScAddress), + Alias(String), +} + +impl Default for UnresolvedScAddress { + fn default() -> Self { + UnresolvedScAddress::Alias(String::default()) + } +} + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Locator(#[from] locator::Error), + #[error(transparent)] + Address(#[from] address::Error), + #[error("Account alias not Found{0}")] + AccountAliasNotFound(String), +} + +impl FromStr for UnresolvedScAddress { + type Err = Error; + + fn from_str(value: &str) -> Result { + Ok(xdr::ScAddress::from_str(value).map_or_else( + |_| UnresolvedScAddress::Alias(value.to_string()), + UnresolvedScAddress::Resolved, + )) + } +} + +impl UnresolvedScAddress { + pub fn resolve( + self, + locator: &locator::Args, + network_passphrase: &str, + ) -> Result { + let alias = match self { + UnresolvedScAddress::Resolved(addr) => return Ok(addr), + UnresolvedScAddress::Alias(alias) => alias, + }; + let contract = UnresolvedContract::resolve_alias(&alias, locator, network_passphrase); + let muxed_account = + super::UnresolvedMuxedAccount::resolve_muxed_account_with_alias(&alias, locator, None); + match (contract, muxed_account) { + (Ok(contract), Ok(_)) => { + eprintln!( + "Warning: ScAddress alias {alias} is ambiguous, assuming it is a contract" + ); + Ok(xdr::ScAddress::Contract(xdr::Hash(contract.0))) + } + (Ok(contract), _) => Ok(xdr::ScAddress::Contract(xdr::Hash(contract.0))), + (_, Ok(muxed_account)) => Ok(xdr::ScAddress::Account(muxed_account.account_id())), + _ => Err(Error::AccountAliasNotFound(alias)), + } + } +} diff --git a/cmd/soroban-cli/src/key.rs b/cmd/soroban-cli/src/key.rs index b704541c4..c3fd7ed89 100644 --- a/cmd/soroban-cli/src/key.rs +++ b/cmd/soroban-cli/src/key.rs @@ -34,7 +34,7 @@ pub struct Args { required_unless_present = "wasm", required_unless_present = "wasm_hash" )] - pub contract_id: Option, + pub contract_id: Option, /// Storage key (symbols only) #[arg(long = "key", conflicts_with = "key_xdr")] pub key: Option>, From ec01a79e070c8063d7726c8fb2e47c24fc4a6a9d Mon Sep 17 00:00:00 2001 From: Gleb Date: Fri, 3 Jan 2025 14:33:35 -0800 Subject: [PATCH 73/77] Fix TS tests (#1820) --- cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts b/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts index eacedbaec..47504c368 100644 --- a/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts +++ b/cmd/crates/soroban-spec-typescript/ts-tests/src/util.ts @@ -3,7 +3,7 @@ import { Address, Keypair } from "@stellar/stellar-sdk"; import { basicNodeSigner } from "@stellar/stellar-sdk/contract"; const rootKeypair = Keypair.fromSecret( - spawnSync("./soroban", ["keys", "secret", "root"], { + spawnSync("./stellar", ["keys", "secret", "root"], { shell: true, encoding: "utf8", }).stdout.trim(), From b60196ff3b286e4b7d1296e4197644f449b2ec7e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 9 Jan 2025 10:23:54 -0800 Subject: [PATCH 74/77] Bump version to 22.2.0 (#1819) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Gleb --- Cargo.lock | 32 +++++++++---------- Cargo.toml | 10 +++--- .../tests/fixtures/bye/Cargo.toml | 2 +- .../tests/fixtures/hello/Cargo.toml | 2 +- .../test-wasms/constructor/Cargo.toml | 2 +- .../test-wasms/custom_account/Cargo.toml | 2 +- .../test-wasms/custom_type/Cargo.toml | 2 +- .../test-wasms/hello_world/Cargo.toml | 2 +- .../tests/fixtures/test-wasms/swap/Cargo.toml | 2 +- .../fixtures/test-wasms/token/Cargo.toml | 2 +- 10 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d69fbaa51..ee45a0303 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4288,7 +4288,7 @@ dependencies = [ [[package]] name = "soroban-cli" -version = "22.1.0" +version = "22.2.0" dependencies = [ "assert_cmd", "assert_fs", @@ -4454,7 +4454,7 @@ dependencies = [ [[package]] name = "soroban-hello" -version = "22.1.0" +version = "22.2.0" [[package]] name = "soroban-ledger-snapshot" @@ -4525,7 +4525,7 @@ dependencies = [ [[package]] name = "soroban-spec-json" -version = "22.1.0" +version = "22.2.0" dependencies = [ "pretty_assertions", "serde", @@ -4555,7 +4555,7 @@ dependencies = [ [[package]] name = "soroban-spec-tools" -version = "22.1.0" +version = "22.2.0" dependencies = [ "base64 0.21.7", "ethnum", @@ -4573,7 +4573,7 @@ dependencies = [ [[package]] name = "soroban-spec-typescript" -version = "22.1.0" +version = "22.2.0" dependencies = [ "base64 0.21.7", "heck 0.4.1", @@ -4594,7 +4594,7 @@ dependencies = [ [[package]] name = "soroban-test" -version = "22.1.0" +version = "22.2.0" dependencies = [ "assert_cmd", "assert_fs", @@ -4666,18 +4666,18 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-bye" -version = "22.1.0" +version = "22.2.0" [[package]] name = "stellar-cli" -version = "22.1.0" +version = "22.2.0" dependencies = [ "soroban-cli", ] [[package]] name = "stellar-ledger" -version = "22.1.0" +version = "22.2.0" dependencies = [ "async-trait", "bollard", @@ -5024,42 +5024,42 @@ dependencies = [ [[package]] name = "test_constructor" -version = "22.1.0" +version = "22.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_account" -version = "22.1.0" +version = "22.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_types" -version = "22.1.0" +version = "22.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_hello_world" -version = "22.1.0" +version = "22.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_swap" -version = "22.1.0" +version = "22.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_token" -version = "22.1.0" +version = "22.2.0" dependencies = [ "soroban-sdk", "soroban-token-sdk", @@ -5067,7 +5067,7 @@ dependencies = [ [[package]] name = "test_udt" -version = "22.1.0" +version = "22.2.0" dependencies = [ "soroban-sdk", ] diff --git a/Cargo.toml b/Cargo.toml index 702de93c5..f0993d3e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,24 +19,24 @@ exclude = [ ] [workspace.package] -version = "22.1.0" +version = "22.2.0" rust-version = "1.81.0" # Dependencies located in this repo: [workspace.dependencies.soroban-cli] -version = "=22.1.0" +version = "=22.2.0" path = "cmd/soroban-cli" [workspace.dependencies.soroban-spec-json] -version = "=22.1.0" +version = "=22.2.0" path = "./cmd/crates/soroban-spec-json" [workspace.dependencies.soroban-spec-typescript] -version = "22.1.0" +version = "22.2.0" path = "./cmd/crates/soroban-spec-typescript" [workspace.dependencies.soroban-spec-tools] -version = "22.1.0" +version = "22.2.0" path = "./cmd/crates/soroban-spec-tools" # Dependencies from the rs-stellar-xdr repo: diff --git a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml index 5ca022099..bf8ce501d 100644 --- a/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/bye/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "stellar-bye" -version = "22.1.0" +version = "22.2.0" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml index 73d7c781e..1a515dfa0 100644 --- a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "soroban-hello" -version = "22.1.0" +version = "22.2.0" edition = "2021" publish = false diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml index f7f9abac0..095b49379 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/constructor/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_constructor" -version = "22.1.0" +version = "22.2.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml index 081312a81..75a8fa357 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_account" -version = "22.1.0" +version = "22.2.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index ebe2191e1..ecee573f5 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_types" -version = "22.1.0" +version = "22.2.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index 14b386d2b..f4db468eb 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_hello_world" -version = "22.1.0" +version = "22.2.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml index 70387d652..6d8900756 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_swap" -version = "22.1.0" +version = "22.2.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml index 681bb9b40..809172526 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_token" -version = "22.1.0" +version = "22.2.0" description = "Soroban standard token contract" authors = ["Stellar Development Foundation "] license = "Apache-2.0" From c9280069e3a13e8c9e7d66ab4cb6d998ddcf9120 Mon Sep 17 00:00:00 2001 From: Gleb Date: Thu, 9 Jan 2025 12:06:19 -0800 Subject: [PATCH 75/77] Bump SDK dependency (#1825) --- Cargo.lock | 57 +++++++++++++++++++++++++++--------------------------- Cargo.toml | 14 +++++++------- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee45a0303..14e44327f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1059,9 +1059,9 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb49164822f3ee45b17acd4a208cfc1251410cf0cad9a833234c9890774dd9f" +checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", "syn 2.0.77", @@ -4276,9 +4276,9 @@ dependencies = [ [[package]] name = "soroban-builtin-sdk-macros" -version = "22.0.0-rc.3" +version = "22.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c45d2492cd44f05cc79eeb857985f153f12a4423ce51b4b746b5925024c473b1" +checksum = "8ebed97f583127b391cc8137d5e475e66ba4e12f428dd6c9aed7a914bbd2353e" dependencies = [ "itertools 0.10.5", "proc-macro2", @@ -4374,9 +4374,9 @@ dependencies = [ [[package]] name = "soroban-env-common" -version = "22.0.0-rc.3" +version = "22.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39b6d2ec8955243394278e1fae88be3b367fcfed9cf74e5044799a90786a8642" +checksum = "94ce037307fcd6d775f2b567ae10d5eb9b99eacb2b1110e9b23ed92b351e47f4" dependencies = [ "arbitrary", "crate-git-revision", @@ -4393,9 +4393,9 @@ dependencies = [ [[package]] name = "soroban-env-guest" -version = "22.0.0-rc.3" +version = "22.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4002fc582cd20cc9b9fbb73959bc5d6b5b15feda11485cbfab0c28e78ecbab3e" +checksum = "b395eaf56d155529a3951c0ad54420599184a810db86d7316b97cc59b97e5b85" dependencies = [ "soroban-env-common", "static_assertions", @@ -4403,9 +4403,9 @@ dependencies = [ [[package]] name = "soroban-env-host" -version = "22.0.0-rc.3" +version = "22.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb9be0260d39a648db0d33e1c6f8f494ec0c4f5be2b8a0a4e15ed4b7c6a92b0" +checksum = "cb980b49637cc428fab2442a97800ac2ed9ced39422acf4840f77ab596858cae" dependencies = [ "ark-bls12-381", "ark-ec", @@ -4439,9 +4439,9 @@ dependencies = [ [[package]] name = "soroban-env-macros" -version = "22.0.0-rc.3" +version = "22.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a328297a568ae98999fdb06902e3362dfd8a2bfa9abea40beaeb7dc93a402fe7" +checksum = "ef84a5b3bfffc84250b22454d6ce9df6750afd5ed900faf7d02968400b9c8bd0" dependencies = [ "itertools 0.10.5", "proc-macro2", @@ -4458,9 +4458,9 @@ version = "22.2.0" [[package]] name = "soroban-ledger-snapshot" -version = "22.0.0-rc.3" +version = "22.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56375490f176006a636db0e50c2269c55626e0ff7222711bb78d77028376fe0d" +checksum = "ac26413e0aac51844bec4ec60b5b86dc854c0152694637c78d9d9ccbc3b3c4b4" dependencies = [ "serde", "serde_json", @@ -4472,13 +4472,14 @@ dependencies = [ [[package]] name = "soroban-sdk" -version = "22.0.0-rc.3" +version = "22.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d063d0df000aaec20105aab3d743660322bc0269934ea95d79fa19aa8792385" +checksum = "cca32fb960f5cdd847cdb711f2f674748cc2cadf3887712d48fc00b9b5acb2ec" dependencies = [ "arbitrary", "bytes-lit", "ctor", + "derive_arbitrary", "ed25519-dalek", "rand", "rustc_version", @@ -4493,9 +4494,9 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "22.0.0-rc.3" +version = "22.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "508c9d819a05109120664aab86c371e1b72c5bea20b1a13158b4ef7948d9f673" +checksum = "9fa7d8701b627f0e6a02a6a86a745401fb81e77a2b67aca3002332398625d7f1" dependencies = [ "crate-git-revision", "darling", @@ -4513,9 +4514,9 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "22.0.0-rc.3" +version = "22.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69001c97783ed3ce197eac2404e7beeabedd16e40e6f0aa210d1bc6a13063c33" +checksum = "413559f8b6c77af0cc97cd52cca0ecb59ad81004d3fd064711d91ea50274965a" dependencies = [ "base64 0.13.1", "stellar-xdr", @@ -4539,9 +4540,9 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "22.0.0-rc.3" +version = "22.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45dbf346f91ed23ea63b1c256c522da9e6f0e2db1887b990a8f0f1d842a3093" +checksum = "202e759a3f416b2a852c87beec1cbe8955d49d6c8b590b8386baef12e065261d" dependencies = [ "prettyplease", "proc-macro2", @@ -4622,9 +4623,9 @@ dependencies = [ [[package]] name = "soroban-token-sdk" -version = "22.0.0-rc.3" +version = "22.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bb933a3dcf41d234f6d669b077eb755663773630c6899a1c8a30dddf950f52" +checksum = "c14961339f6830772941bc28616951259bf75864558e70796a03f83e809faa07" dependencies = [ "soroban-sdk", ] @@ -4715,9 +4716,9 @@ dependencies = [ [[package]] name = "stellar-rpc-client" -version = "22.0.0-rc.1" +version = "22.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaba3219c517ceba11f99e1f9adb1e801fe8416bc9ff35c6842b5fe8cac19290" +checksum = "d7c4daeb7f113802cc4bcce8736be32bde243e8e2bf29dda76614b949ed445cf" dependencies = [ "clap", "hex", @@ -4773,9 +4774,9 @@ dependencies = [ [[package]] name = "stellar-xdr" -version = "22.0.0-rc.1.1" +version = "22.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c88dc0e928b9cb65ea43836b52560bb4ead3e32895f5019ca223dc7cd1966cbf" +checksum = "2ce69db907e64d1e70a3dce8d4824655d154749426a6132b25395c49136013e4" dependencies = [ "arbitrary", "base64 0.13.1", diff --git a/Cargo.toml b/Cargo.toml index f0993d3e5..12c5490d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,29 +41,29 @@ path = "./cmd/crates/soroban-spec-tools" # Dependencies from the rs-stellar-xdr repo: [workspace.dependencies.stellar-xdr] -version = "=22.0.0-rc.1.1" +version = "=22.1.0" default-features = true # Dependencies from the rs-soroban-sdk repo: [workspace.dependencies.soroban-spec] -version = "=22.0.0-rc.3" +version = "=22.0.4" [workspace.dependencies.soroban-spec-rust] -version = "=22.0.0-rc.3" +version = "=22.0.4" [workspace.dependencies.soroban-sdk] -version = "=22.0.0-rc.3" +version = "=22.0.4" [workspace.dependencies.soroban-token-sdk] -version = "=22.0.0-rc.3" +version = "=22.0.4" [workspace.dependencies.soroban-ledger-snapshot] -version = "=22.0.0-rc.3" +version = "=22.0.4" # Dependencies from the rs-stellar-rpc-client repo: [workspace.dependencies.soroban-rpc] package = "stellar-rpc-client" -version = "=22.0.0-rc.1" +version = "=22.0.0" # Dependencies from elsewhere shared by crates: [workspace.dependencies] From c055eac1347a00f29cefdc4eab9c6acd4b80e081 Mon Sep 17 00:00:00 2001 From: Willem Wyndham Date: Thu, 9 Jan 2025 15:57:15 -0500 Subject: [PATCH 76/77] feat: add support for OS specific keychains (#1703) * feat: initial work into system keychain * chore: clean up * Add KeyName struct in address * Add Secret::Keychain * keys generate: allow for generating keys that are stored in keychain * keys generate: Namespace keychain entry to identity name * keys generate: don't allow 'keychain:' as a key name * keys address: use keychain entry in secret to get the pub key * tx sign: allow a keychain identity sign a tx * Cleanup * Use keyring mock for generate tests * Refactor keyring: add keyring entry as StellarEntry field - previously we were creating a new keyring entry for each interaction with the keyring - this change will allow us use a mock keyring entry for testing * Add tests for keyring * Update config/secret tests * Cleanup * Rename keychain arg to secure_store in generate * Rename Secret::Keychain to Secret::SecureStore * Rename SignerKind::Keychain to SignerKind::SecureStore * Use print for new fns in generate * Return error when trying to get Secure Store secret * Cleanup tests * Install libdbus for rpc-tests and bindings-ts workflows required for keyring crate * Update generated docs * Install libdbus for binaries workflow when target aarch64-unknown-linux-gnu * Clippy * Install libdbus for rust workflow * Install libdbus-1-dev in binaries workflow for build step * Impl Display for KeyName this change was made so that we can concat the KeyName with secure story prefix and service * Use resolve_muxed_account in resolve_secret * Use resolve_muxed_account to get public key * Clippy * fix: Sign tx hash instead of tx env with keychain * Remove unused bin/secret * Fix after merging with main * Apply suggestion from code review Co-authored-by: Willem Wyndham * Limit key name length * Update public_key to work with secure storage keys * fix(address): remove private key function & use unresolved Address This simplifies the lookup of the address. * feat: store seedphrase instead of private key This will allow for exporting the phrase later * fix: clean up --------- Co-authored-by: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> --- .github/workflows/binaries.yml | 3 +- .github/workflows/bindings-ts.yml | 1 + .github/workflows/rpc-tests.yml | 1 + .github/workflows/rust.yml | 3 +- Cargo.lock | 111 ++++++++++++ FULL_HELP_DOCS.md | 5 +- cmd/soroban-cli/Cargo.toml | 7 +- .../src/commands/contract/arg_parsing.rs | 7 +- cmd/soroban-cli/src/commands/keys/add.rs | 4 +- cmd/soroban-cli/src/commands/keys/address.rs | 40 ++--- cmd/soroban-cli/src/commands/keys/generate.rs | 164 ++++++++++++++++-- cmd/soroban-cli/src/commands/keys/mod.rs | 2 +- cmd/soroban-cli/src/config/address.rs | 55 +++++- cmd/soroban-cli/src/config/secret.rs | 118 +++++++++++-- cmd/soroban-cli/src/signer.rs | 22 +++ cmd/soroban-cli/src/signer/keyring.rs | 147 ++++++++++++++++ 16 files changed, 615 insertions(+), 75 deletions(-) create mode 100644 cmd/soroban-cli/src/signer/keyring.rs diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 45d74a243..48e2e5657 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -46,7 +46,7 @@ jobs: - run: rustup target add ${{ matrix.sys.target }} - if: matrix.sys.target == 'aarch64-unknown-linux-gnu' - run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev + run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev libdbus-1-dev - name: Setup vars run: | @@ -69,6 +69,7 @@ jobs: env: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc working-directory: ${{ env.BUILD_WORKING_DIR }} + run: sudo apt-get update && sudo apt-get -y install libdbus-1-dev run: cargo build --target-dir="$GITHUB_WORKSPACE/target" --package ${{ matrix.crate.name }} --features opt --release --target ${{ matrix.sys.target }} - name: Build provenance for attestation (release only) diff --git a/.github/workflows/bindings-ts.yml b/.github/workflows/bindings-ts.yml index f6aaae499..7f87baf08 100644 --- a/.github/workflows/bindings-ts.yml +++ b/.github/workflows/bindings-ts.yml @@ -38,6 +38,7 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - run: rustup update + - run: sudo apt install -y libdbus-1-dev - run: cargo build - run: rustup target add wasm32-unknown-unknown - run: make build-test-wasms diff --git a/.github/workflows/rpc-tests.yml b/.github/workflows/rpc-tests.yml index 75b6d7760..5392d9830 100644 --- a/.github/workflows/rpc-tests.yml +++ b/.github/workflows/rpc-tests.yml @@ -39,6 +39,7 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - run: rustup update + - run: sudo apt install -y libdbus-1-dev - run: cargo build - run: rustup target add wasm32-unknown-unknown - run: make build-test-wasms diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index f3c9b1920..ff4f7d399 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -49,6 +49,7 @@ jobs: - uses: actions/checkout@v4 - uses: stellar/actions/rust-cache@main - run: rustup update + - run: sudo apt install -y libdbus-1-dev - run: make generate-full-help-doc - run: git add -N . && git diff HEAD --exit-code @@ -90,7 +91,7 @@ jobs: - run: rustup target add ${{ matrix.sys.target }} - run: rustup target add wasm32-unknown-unknown - if: runner.os == 'Linux' - run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev + run: sudo apt-get update && sudo apt-get -y install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libudev-dev libdbus-1-dev - run: cargo clippy --all-targets --target ${{ matrix.sys.target }} - run: make test env: diff --git a/Cargo.lock b/Cargo.lock index 14e44327f..ca8bc5ee1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1179,6 +1179,30 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" +[[package]] +name = "dbus" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" +dependencies = [ + "libc", + "libdbus-sys", + "winapi", +] + +[[package]] +name = "dbus-secret-service" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" +dependencies = [ + "dbus", + "futures-util", + "num", + "once_cell", + "rand", +] + [[package]] name = "der" version = "0.7.9" @@ -2581,6 +2605,18 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "keyring" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fa83d1ca02db069b5fbe94b23b584d588e989218310c9c15015bb5571ef1a94" +dependencies = [ + "byteorder 1.5.0", + "dbus-secret-service", + "security-framework", + "windows-sys 0.59.0", +] + [[package]] name = "kv-log-macro" version = "1.0.7" @@ -2682,6 +2718,15 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libdbus-sys" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" +dependencies = [ + "pkg-config", +] + [[package]] name = "libm" version = "0.2.8" @@ -2870,6 +2915,20 @@ dependencies = [ "winapi", ] +[[package]] +name = "num" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.4" @@ -2881,6 +2940,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2908,6 +2976,29 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -4320,6 +4411,7 @@ dependencies = [ "itertools 0.10.5", "jsonrpsee-core", "jsonrpsee-http-client", + "keyring", "mockito", "num-bigint", "open", @@ -4370,6 +4462,8 @@ dependencies = [ "wasm-opt", "wasmparser", "which", + "whoami", + "zeroize", ] [[package]] @@ -5589,6 +5683,12 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -5797,6 +5897,17 @@ dependencies = [ "rustix 0.38.34", ] +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", + "web-sys", +] + [[package]] name = "widestring" version = "1.1.0" diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 6b67e32a0..9347f4a68 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -938,7 +938,7 @@ Create and manage identities including keys and addresses ###### **Subcommands:** -* `add` — Add a new identity (keypair, ledger, macOS keychain) +* `add` — Add a new identity (keypair, ledger, OS specific secure store) * `address` — Given an identity return its address (public key) * `fund` — Fund an identity on a test network * `generate` — Generate a new identity with a seed phrase, currently 12 words @@ -951,7 +951,7 @@ Create and manage identities including keys and addresses ## `stellar keys add` -Add a new identity (keypair, ledger, macOS keychain) +Add a new identity (keypair, ledger, OS specific secure store) **Usage:** `stellar keys add [OPTIONS] ` @@ -1023,6 +1023,7 @@ Generate a new identity with a seed phrase, currently 12 words * `--no-fund` — Do not fund address * `--seed ` — Optional seed to use when generating seed phrase. Random otherwise * `-s`, `--as-secret` — Output the generated identity as a secret key +* `--secure-store` — Save in OS-specific secure store * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." * `--hd-path ` — When generating a secret key, which `hd_path` should be used from the original `seed_phrase` diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 2f2a26255..3d366464b 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -72,7 +72,8 @@ rand = "0.8.5" wasmparser = { workspace = true } sha2 = { workspace = true } csv = "1.1.6" -ed25519-dalek = { workspace = true } +# zeroize feature ensures that all sensitive data is zeroed out when dropped +ed25519-dalek = { workspace = true, features = ["zeroize"] } reqwest = { version = "0.12.7", default-features = false, features = [ "rustls-tls", "http2", @@ -124,6 +125,10 @@ fqdn = "0.3.12" open = "5.3.0" url = "2.5.2" wasm-gen = "0.1.4" +zeroize = "1.8.1" +keyring = { version = "3", features = ["apple-native", "windows-native", "sync-secret-service"] } +whoami = "1.5.2" + [build-dependencies] crate-git-revision = "0.0.6" diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index a223851ca..bb2d2aa76 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -269,10 +269,5 @@ fn resolve_address(addr_or_alias: &str, config: &config::Args) -> Result Option { - let cmd = crate::commands::keys::address::Cmd { - name: addr_or_alias.to_string(), - hd_path: Some(0), - locator: config.locator.clone(), - }; - cmd.private_key().ok() + config.locator.key(addr_or_alias).ok()?.key_pair(None).ok() } diff --git a/cmd/soroban-cli/src/commands/keys/add.rs b/cmd/soroban-cli/src/commands/keys/add.rs index af829fe6f..4c5ddbd9b 100644 --- a/cmd/soroban-cli/src/commands/keys/add.rs +++ b/cmd/soroban-cli/src/commands/keys/add.rs @@ -2,7 +2,7 @@ use clap::command; use crate::{ commands::global, - config::{locator, secret}, + config::{address::KeyName, locator, secret}, print::Print, }; @@ -19,7 +19,7 @@ pub enum Error { #[group(skip)] pub struct Cmd { /// Name of identity - pub name: String, + pub name: KeyName, #[command(flatten)] pub secrets: secret::Args, diff --git a/cmd/soroban-cli/src/commands/keys/address.rs b/cmd/soroban-cli/src/commands/keys/address.rs index d13381b49..51ce90ed2 100644 --- a/cmd/soroban-cli/src/commands/keys/address.rs +++ b/cmd/soroban-cli/src/commands/keys/address.rs @@ -1,25 +1,21 @@ -use crate::commands::config::secret; - -use super::super::config::locator; use clap::arg; +use crate::{ + commands::config::{address, locator}, + config::UnresolvedMuxedAccount, +}; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error(transparent)] - Config(#[from] locator::Error), - - #[error(transparent)] - Secret(#[from] secret::Error), - - #[error(transparent)] - StrKey(#[from] stellar_strkey::DecodeError), + Address(#[from] address::Error), } #[derive(Debug, clap::Parser, Clone)] #[group(skip)] pub struct Cmd { /// Name of identity to lookup, default test identity used if not provided - pub name: String, + pub name: UnresolvedMuxedAccount, /// If identity is a seed phrase use this hd path, default is 0 #[arg(long)] @@ -35,20 +31,14 @@ impl Cmd { Ok(()) } - pub fn private_key(&self) -> Result { - Ok(self - .locator - .read_identity(&self.name)? - .key_pair(self.hd_path)?) - } - pub fn public_key(&self) -> Result { - if let Ok(key) = stellar_strkey::ed25519::PublicKey::from_string(&self.name) { - Ok(key) - } else { - Ok(stellar_strkey::ed25519::PublicKey::from_payload( - self.private_key()?.verifying_key().as_bytes(), - )?) - } + let muxed = self + .name + .resolve_muxed_account(&self.locator, self.hd_path)?; + let bytes = match muxed { + soroban_sdk::xdr::MuxedAccount::Ed25519(uint256) => uint256.0, + soroban_sdk::xdr::MuxedAccount::MuxedEd25519(muxed_account) => muxed_account.ed25519.0, + }; + Ok(stellar_strkey::ed25519::PublicKey(bytes)) } } diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index fda6a3d98..8ec0158bb 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -1,10 +1,16 @@ use clap::{arg, command}; +use sep5::SeedPhrase; use super::super::config::{ locator, network, secret::{self, Secret}, }; -use crate::{commands::global, print::Print}; +use crate::{ + commands::global, + config::address::KeyName, + print::Print, + signer::keyring::{self, StellarEntry}, +}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -19,6 +25,9 @@ pub enum Error { #[error("An identity with the name '{0}' already exists")] IdentityAlreadyExists(String), + + #[error(transparent)] + Keyring(#[from] keyring::Error), } #[derive(Debug, clap::Parser, Clone)] @@ -26,10 +35,12 @@ pub enum Error { #[allow(clippy::struct_excessive_bools)] pub struct Cmd { /// Name of identity - pub name: String, + pub name: KeyName, + /// Do not fund address #[arg(long)] pub no_fund: bool, + /// Optional seed to use when generating seed phrase. /// Random otherwise. #[arg(long, conflicts_with = "default_seed")] @@ -39,6 +50,10 @@ pub struct Cmd { #[arg(long, short = 's')] pub as_secret: bool, + /// Save in OS-specific secure store + #[arg(long)] + pub secure_store: bool, + #[command(flatten)] pub config_locator: locator::Args, @@ -69,10 +84,10 @@ impl Cmd { if self.config_locator.read_identity(&self.name).is_ok() { if !self.overwrite { - return Err(Error::IdentityAlreadyExists(self.name.clone())); + return Err(Error::IdentityAlreadyExists(self.name.to_string())); } - print.exclaimln(format!("Overwriting identity '{}'", &self.name)); + print.exclaimln(format!("Overwriting identity '{}'", &self.name.to_string())); } if !self.fund { @@ -83,19 +98,7 @@ impl Cmd { warning. It can be suppressed with -q flag.", ); } - - let seed_phrase = if self.default_seed { - Secret::test_seed_phrase() - } else { - Secret::from_seed(self.seed.as_deref()) - }?; - - let secret = if self.as_secret { - seed_phrase.private_key(self.hd_path)?.into() - } else { - seed_phrase - }; - + let secret = self.secret(&print)?; let path = self.config_locator.write_identity(&self.name, &secret)?; print.checkln(format!("Key saved with alias {:?} in {path:?}", self.name)); @@ -117,4 +120,131 @@ impl Cmd { Ok(()) } + + fn secret(&self, print: &Print) -> Result { + let seed_phrase = self.seed_phrase()?; + if self.secure_store { + // secure_store:org.stellar.cli: + let entry_name_with_prefix = format!( + "{}{}-{}", + keyring::SECURE_STORE_ENTRY_PREFIX, + keyring::SECURE_STORE_ENTRY_SERVICE, + self.name + ); + + //checking that the entry name is valid before writing to the secure store + let secret: Secret = entry_name_with_prefix.parse()?; + + if let Secret::SecureStore { entry_name } = &secret { + Self::write_to_secure_store(entry_name, seed_phrase, print)?; + } + + return Ok(secret); + } + let secret: Secret = seed_phrase.into(); + Ok(if self.as_secret { + secret.private_key(self.hd_path)?.into() + } else { + secret + }) + } + + fn seed_phrase(&self) -> Result { + Ok(if self.default_seed { + secret::test_seed_phrase() + } else { + secret::seed_phrase_from_seed(self.seed.as_deref()) + }?) + } + + fn write_to_secure_store( + entry_name: &String, + seed_phrase: SeedPhrase, + print: &Print, + ) -> Result<(), Error> { + print.infoln(format!("Writing to secure store: {entry_name}")); + let entry = StellarEntry::new(entry_name)?; + if let Ok(key) = entry.get_public_key(None) { + print.warnln(format!("A key for {entry_name} already exists in your operating system's secure store: {key}")); + } else { + print.infoln(format!( + "Saving a new key to your operating system's secure store: {entry_name}" + )); + entry.set_seed_phrase(seed_phrase)?; + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::config::{address::KeyName, secret::Secret}; + use keyring::{mock, set_default_credential_builder}; + + fn set_up_test() -> (super::locator::Args, super::Cmd) { + let temp_dir = tempfile::tempdir().unwrap(); + let locator = super::locator::Args { + global: false, + config_dir: Some(temp_dir.path().to_path_buf()), + }; + + let cmd = super::Cmd { + name: KeyName("test_name".to_string()), + no_fund: true, + seed: None, + as_secret: false, + secure_store: false, + config_locator: locator.clone(), + hd_path: None, + default_seed: false, + network: super::network::Args::default(), + fund: false, + overwrite: false, + }; + + (locator, cmd) + } + + fn global_args() -> super::global::Args { + super::global::Args { + quiet: true, + ..Default::default() + } + } + + #[tokio::test] + async fn test_storing_secret_as_a_seed_phrase() { + let (test_locator, cmd) = set_up_test(); + let global_args = global_args(); + + let result = cmd.run(&global_args).await; + assert!(result.is_ok()); + let identity = test_locator.read_identity("test_name").unwrap(); + assert!(matches!(identity, Secret::SeedPhrase { .. })); + } + + #[tokio::test] + async fn test_storing_secret_as_a_secret_key() { + let (test_locator, mut cmd) = set_up_test(); + cmd.as_secret = true; + let global_args = global_args(); + + let result = cmd.run(&global_args).await; + assert!(result.is_ok()); + let identity = test_locator.read_identity("test_name").unwrap(); + assert!(matches!(identity, Secret::SecretKey { .. })); + } + + #[tokio::test] + async fn test_storing_secret_in_secure_store() { + set_default_credential_builder(mock::default_credential_builder()); + let (test_locator, mut cmd) = set_up_test(); + cmd.secure_store = true; + let global_args = global_args(); + + let result = cmd.run(&global_args).await; + assert!(result.is_ok()); + let identity = test_locator.read_identity("test_name").unwrap(); + assert!(matches!(identity, Secret::SecureStore { .. })); + } } diff --git a/cmd/soroban-cli/src/commands/keys/mod.rs b/cmd/soroban-cli/src/commands/keys/mod.rs index b5520abf6..3e36df085 100644 --- a/cmd/soroban-cli/src/commands/keys/mod.rs +++ b/cmd/soroban-cli/src/commands/keys/mod.rs @@ -12,7 +12,7 @@ pub mod secret; #[derive(Debug, Parser)] pub enum Cmd { - /// Add a new identity (keypair, ledger, macOS keychain) + /// Add a new identity (keypair, ledger, OS specific secure store) Add(add::Cmd), /// Given an identity return its address (public key) diff --git a/cmd/soroban-cli/src/config/address.rs b/cmd/soroban-cli/src/config/address.rs index 356c7a991..f86f88ecb 100644 --- a/cmd/soroban-cli/src/config/address.rs +++ b/cmd/soroban-cli/src/config/address.rs @@ -1,4 +1,7 @@ -use std::str::FromStr; +use std::{ + fmt::{self, Display, Formatter}, + str::FromStr, +}; use crate::xdr; @@ -25,6 +28,12 @@ pub enum Error { Secret(#[from] secret::Error), #[error("Address cannot be used to sign {0}")] CannotSign(xdr::MuxedAccount), + #[error("Invalid key name: {0}\n only alphanumeric characters, underscores (_), and hyphens (-) are allowed.")] + InvalidKeyNameCharacters(String), + #[error("Invalid key name: {0}\n keys cannot exceed 250 characters")] + InvalidKeyNameLength(String), + #[error("Invalid key name: {0}\n keys cannot be the word \"ledger\"")] + InvalidKeyName(String), } impl FromStr for UnresolvedMuxedAccount { @@ -46,8 +55,8 @@ impl UnresolvedMuxedAccount { ) -> Result { match self { UnresolvedMuxedAccount::Resolved(muxed_account) => Ok(muxed_account.clone()), - UnresolvedMuxedAccount::AliasOrSecret(alias) => { - Self::resolve_muxed_account_with_alias(alias, locator, hd_path) + UnresolvedMuxedAccount::AliasOrSecret(alias_or_secret) => { + Self::resolve_muxed_account_with_alias(alias_or_secret, locator, hd_path) } } } @@ -69,7 +78,45 @@ impl UnresolvedMuxedAccount { UnresolvedMuxedAccount::Resolved(muxed_account) => { Err(Error::CannotSign(muxed_account.clone())) } - UnresolvedMuxedAccount::AliasOrSecret(alias) => Ok(locator.read_identity(alias)?), + UnresolvedMuxedAccount::AliasOrSecret(alias_or_secret) => { + Ok(locator.key(alias_or_secret)?) + } + } + } +} + +#[derive(Clone, Debug)] +pub struct KeyName(pub String); + +impl std::ops::Deref for KeyName { + type Target = str; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::str::FromStr for KeyName { + type Err = Error; + fn from_str(s: &str) -> Result { + if !s.chars().all(allowed_char) { + return Err(Error::InvalidKeyNameCharacters(s.to_string())); + } + if s == "ledger" { + return Err(Error::InvalidKeyName(s.to_string())); } + if s.len() > 250 { + return Err(Error::InvalidKeyNameLength(s.to_string())); + } + Ok(KeyName(s.to_string())) } } + +impl Display for KeyName { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +fn allowed_char(c: char) -> bool { + c.is_ascii_alphanumeric() || c == '_' || c == '-' +} diff --git a/cmd/soroban-cli/src/config/secret.rs b/cmd/soroban-cli/src/config/secret.rs index 00cec12f6..f32b291e8 100644 --- a/cmd/soroban-cli/src/config/secret.rs +++ b/cmd/soroban-cli/src/config/secret.rs @@ -1,11 +1,13 @@ use clap::arg; use serde::{Deserialize, Serialize}; use std::{io::Write, str::FromStr}; + +use sep5::SeedPhrase; use stellar_strkey::ed25519::{PrivateKey, PublicKey}; use crate::{ print::Print, - signer::{self, LocalKey, Signer, SignerKind}, + signer::{self, keyring, LocalKey, SecureStoreEntry, Signer, SignerKind}, utils, }; @@ -25,6 +27,10 @@ pub enum Error { InvalidSecretOrSeedPhrase, #[error(transparent)] Signer(#[from] signer::Error), + #[error(transparent)] + Keyring(#[from] keyring::Error), + #[error("Secure Store does not reveal secret key")] + SecureStoreDoesNotRevealSecretKey, } #[derive(Debug, clap::Args, Clone)] @@ -57,6 +63,7 @@ impl Args { pub enum Secret { SecretKey { secret_key: String }, SeedPhrase { seed_phrase: String }, + SecureStore { entry_name: String }, } impl FromStr for Secret { @@ -71,6 +78,10 @@ impl FromStr for Secret { Ok(Secret::SeedPhrase { seed_phrase: s.to_string(), }) + } else if s.starts_with(keyring::SECURE_STORE_ENTRY_PREFIX) { + Ok(Secret::SecureStore { + entry_name: s.to_string(), + }) } else { Err(Error::InvalidSecretOrSeedPhrase) } @@ -85,6 +96,14 @@ impl From for Secret { } } +impl From for Secret { + fn from(value: SeedPhrase) -> Self { + Secret::SeedPhrase { + seed_phrase: value.seed_phrase.into_phrase(), + } + } +} + impl Secret { pub fn private_key(&self, index: Option) -> Result { Ok(match self { @@ -95,22 +114,34 @@ impl Secret { .private() .0, )?, + Secret::SecureStore { .. } => { + return Err(Error::SecureStoreDoesNotRevealSecretKey); + } }) } pub fn public_key(&self, index: Option) -> Result { - let key = self.key_pair(index)?; - Ok(stellar_strkey::ed25519::PublicKey::from_payload( - key.verifying_key().as_bytes(), - )?) + if let Secret::SecureStore { entry_name } = self { + let entry = keyring::StellarEntry::new(entry_name)?; + Ok(entry.get_public_key(index)?) + } else { + let key = self.key_pair(index)?; + Ok(stellar_strkey::ed25519::PublicKey::from_payload( + key.verifying_key().as_bytes(), + )?) + } } - pub fn signer(&self, index: Option, print: Print) -> Result { + pub fn signer(&self, hd_path: Option, print: Print) -> Result { let kind = match self { Secret::SecretKey { .. } | Secret::SeedPhrase { .. } => { - let key = self.key_pair(index)?; + let key = self.key_pair(hd_path)?; SignerKind::Local(LocalKey { key }) } + Secret::SecureStore { entry_name } => SignerKind::SecureStore(SecureStoreEntry { + name: entry_name.to_string(), + hd_path, + }), }; Ok(Signer { kind, print }) } @@ -120,14 +151,7 @@ impl Secret { } pub fn from_seed(seed: Option<&str>) -> Result { - let seed_phrase = if let Some(seed) = seed.map(str::as_bytes) { - sep5::SeedPhrase::from_entropy(seed) - } else { - sep5::SeedPhrase::random(sep5::MnemonicType::Words24) - }? - .seed_phrase - .into_phrase(); - Ok(Secret::SeedPhrase { seed_phrase }) + Ok(seed_phrase_from_seed(seed)?.into()) } pub fn test_seed_phrase() -> Result { @@ -135,7 +159,71 @@ impl Secret { } } +pub fn seed_phrase_from_seed(seed: Option<&str>) -> Result { + Ok(if let Some(seed) = seed.map(str::as_bytes) { + sep5::SeedPhrase::from_entropy(seed)? + } else { + sep5::SeedPhrase::random(sep5::MnemonicType::Words24)? + }) +} + +pub fn test_seed_phrase() -> Result { + Ok("0000000000000000".parse()?) +} + fn read_password() -> Result { std::io::stdout().flush().map_err(|_| Error::PasswordRead)?; rpassword::read_password().map_err(|_| Error::PasswordRead) } + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_PUBLIC_KEY: &str = "GAREAZZQWHOCBJS236KIE3AWYBVFLSBK7E5UW3ICI3TCRWQKT5LNLCEZ"; + const TEST_SECRET_KEY: &str = "SBF5HLRREHMS36XZNTUSKZ6FTXDZGNXOHF4EXKUL5UCWZLPBX3NGJ4BH"; + const TEST_SEED_PHRASE: &str = + "depth decade power loud smile spatial sign movie judge february rate broccoli"; + + #[test] + fn test_from_str_for_secret_key() { + let secret = Secret::from_str(TEST_SECRET_KEY).unwrap(); + let public_key = secret.public_key(None).unwrap(); + let private_key = secret.private_key(None).unwrap(); + + assert!(matches!(secret, Secret::SecretKey { .. })); + assert_eq!(public_key.to_string(), TEST_PUBLIC_KEY); + assert_eq!(private_key.to_string(), TEST_SECRET_KEY); + } + + #[test] + fn test_secret_from_seed_phrase() { + let secret = Secret::from_str(TEST_SEED_PHRASE).unwrap(); + let public_key = secret.public_key(None).unwrap(); + let private_key = secret.private_key(None).unwrap(); + + assert!(matches!(secret, Secret::SeedPhrase { .. })); + assert_eq!(public_key.to_string(), TEST_PUBLIC_KEY); + assert_eq!(private_key.to_string(), TEST_SECRET_KEY); + } + + #[test] + fn test_secret_from_secure_store() { + //todo: add assertion for getting public key - will need to mock the keychain and add the keypair to the keychain + let secret = Secret::from_str("secure_store:org.stellar.cli-alice").unwrap(); + assert!(matches!(secret, Secret::SecureStore { .. })); + + let private_key_result = secret.private_key(None); + assert!(private_key_result.is_err()); + assert!(matches!( + private_key_result.unwrap_err(), + Error::SecureStoreDoesNotRevealSecretKey + )); + } + + #[test] + fn test_secret_from_invalid_string() { + let secret = Secret::from_str("invalid"); + assert!(secret.is_err()); + } +} diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index 5bf22499c..ebd650d40 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -1,4 +1,5 @@ use ed25519_dalek::ed25519::signature::Signer as _; +use keyring::StellarEntry; use sha2::{Digest, Sha256}; use crate::xdr::{ @@ -11,6 +12,8 @@ use crate::xdr::{ use crate::{config::network::Network, print::Print, utils::transaction_hash}; +pub mod keyring; + #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Contract addresses are not supported to sign auth entries {address}")] @@ -33,6 +36,8 @@ pub enum Error { Open(#[from] std::io::Error), #[error("Returning a signature from Lab is not yet supported; Transaction can be found and submitted in lab")] ReturningSignatureFromLab, + #[error(transparent)] + Keyring(#[from] keyring::Error), } fn requires_auth(txn: &Transaction) -> Option { @@ -207,6 +212,7 @@ pub struct Signer { pub enum SignerKind { Local(LocalKey), Lab, + SecureStore(SecureStoreEntry), } impl Signer { @@ -235,6 +241,7 @@ impl Signer { let decorated_signature = match &self.kind { SignerKind::Local(key) => key.sign_tx_hash(tx_hash)?, SignerKind::Lab => Lab::sign_tx_env(tx_env, network, &self.print)?, + SignerKind::SecureStore(entry) => entry.sign_tx_hash(tx_hash)?, }; let mut sigs = signatures.clone().into_vec(); sigs.push(decorated_signature); @@ -284,3 +291,18 @@ impl Lab { Err(Error::ReturningSignatureFromLab) } } + +pub struct SecureStoreEntry { + pub name: String, + pub hd_path: Option, +} + +impl SecureStoreEntry { + pub fn sign_tx_hash(&self, tx_hash: [u8; 32]) -> Result { + let entry = StellarEntry::new(&self.name)?; + let hint = SignatureHint(entry.get_public_key(self.hd_path)?.0[28..].try_into()?); + let signed_tx_hash = entry.sign_data(&tx_hash, self.hd_path)?; + let signature = Signature(signed_tx_hash.clone().try_into()?); + Ok(DecoratedSignature { hint, signature }) + } +} diff --git a/cmd/soroban-cli/src/signer/keyring.rs b/cmd/soroban-cli/src/signer/keyring.rs new file mode 100644 index 000000000..0e6c49137 --- /dev/null +++ b/cmd/soroban-cli/src/signer/keyring.rs @@ -0,0 +1,147 @@ +use ed25519_dalek::Signer; +use keyring::Entry; +use sep5::seed_phrase::SeedPhrase; +use zeroize::Zeroize; + +pub(crate) const SECURE_STORE_ENTRY_PREFIX: &str = "secure_store:"; +pub(crate) const SECURE_STORE_ENTRY_SERVICE: &str = "org.stellar.cli"; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + Keyring(#[from] keyring::Error), + #[error(transparent)] + Sep5(#[from] sep5::error::Error), +} + +pub struct StellarEntry { + keyring: Entry, +} + +impl StellarEntry { + pub fn new(name: &str) -> Result { + Ok(StellarEntry { + keyring: Entry::new(name, &whoami::username())?, + }) + } + + pub fn set_seed_phrase(&self, seed_phrase: SeedPhrase) -> Result<(), Error> { + let mut data = seed_phrase.seed_phrase.into_phrase(); + self.keyring.set_password(&data)?; + data.zeroize(); + Ok(()) + } + + fn get_seed_phrase(&self) -> Result { + Ok(self.keyring.get_password()?.parse()?) + } + + fn use_key( + &self, + f: impl FnOnce(ed25519_dalek::SigningKey) -> Result, + hd_path: Option, + ) -> Result { + // The underlying Mnemonic type is zeroized when dropped + let mut key_bytes: [u8; 32] = { + self.get_seed_phrase()? + .from_path_index(hd_path.unwrap_or_default(), None)? + .private() + .0 + }; + let result = { + // Use this scope to ensure the keypair is zeroized when dropped + let keypair = ed25519_dalek::SigningKey::from_bytes(&key_bytes); + f(keypair)? + }; + key_bytes.zeroize(); + Ok(result) + } + + pub fn get_public_key( + &self, + hd_path: Option, + ) -> Result { + self.use_key( + |keypair| { + Ok(stellar_strkey::ed25519::PublicKey( + *keypair.verifying_key().as_bytes(), + )) + }, + hd_path, + ) + } + + pub fn sign_data(&self, data: &[u8], hd_path: Option) -> Result, Error> { + self.use_key( + |keypair| { + let signature = keypair.sign(data); + Ok(signature.to_bytes().to_vec()) + }, + hd_path, + ) + } +} + +#[cfg(test)] +mod test { + use super::*; + use keyring::{mock, set_default_credential_builder}; + + #[test] + fn test_get_password() { + set_default_credential_builder(mock::default_credential_builder()); + + let seed_phrase = crate::config::secret::seed_phrase_from_seed(None).unwrap(); + let seed_phrase_clone = seed_phrase.clone(); + + let entry = StellarEntry::new("test").unwrap(); + + // set the seed phrase + let set_seed_phrase_result = entry.set_seed_phrase(seed_phrase); + assert!(set_seed_phrase_result.is_ok()); + + // get_seed_phrase should return the same seed phrase we set + let get_seed_phrase_result = entry.get_seed_phrase(); + assert!(get_seed_phrase_result.is_ok()); + assert_eq!( + seed_phrase_clone.phrase(), + get_seed_phrase_result.unwrap().phrase() + ); + } + + #[test] + fn test_get_public_key() { + set_default_credential_builder(mock::default_credential_builder()); + + let seed_phrase = crate::config::secret::seed_phrase_from_seed(None).unwrap(); + let public_key = seed_phrase.from_path_index(0, None).unwrap().public().0; + + let entry = StellarEntry::new("test").unwrap(); + + // set the seed_phrase + let set_seed_phrase_result = entry.set_seed_phrase(seed_phrase); + assert!(set_seed_phrase_result.is_ok()); + + // confirm that we can get the public key from the entry and that it matches the one we set + let get_public_key_result = entry.get_public_key(None); + assert!(get_public_key_result.is_ok()); + assert_eq!(public_key, get_public_key_result.unwrap().0); + } + + #[test] + fn test_sign_data() { + set_default_credential_builder(mock::default_credential_builder()); + + //create a seed phrase + let seed_phrase = crate::config::secret::seed_phrase_from_seed(None).unwrap(); + + // create a keyring entry and set the seed_phrase + let entry = StellarEntry::new("test").unwrap(); + entry.set_seed_phrase(seed_phrase).unwrap(); + + let tx_xdr = r"AAAAAgAAAADh6eOnZEq1xQgKioffuH7/8D8x8+OdGFEkiYC6QKMWzQAAAGQAAACuAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAYAAAAAQAAAAAAAAAAAAAAAOHp46dkSrXFCAqKh9+4fv/wPzHz450YUSSJgLpAoxbNoFT1s8jZPCv9IJ2DsqGTA8pOtavv58JF53aDycpRPcEAAAAA+N2m5zc3EfWUmLvigYPOHKXhSy8OrWfVibc6y6PrQoYAAAAAAAAAAAAAAAA"; + + let sign_tx_env_result = entry.sign_data(tx_xdr.as_bytes(), None); + assert!(sign_tx_env_result.is_ok()); + } +} From b6bd2553b7b5f2a13195c2704cd605ce56998625 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:13:29 -0500 Subject: [PATCH 77/77] Install libdbus-1-dev for dry run for ubuntu (#1826) --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ff4f7d399..22a27a939 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -107,7 +107,7 @@ jobs: - os: ubuntu-latest-16-cores target: x86_64-unknown-linux-gnu cargo-hack-feature-options: --feature-powerset - additional-deb-packages: libudev-dev + additional-deb-packages: libudev-dev libdbus-1-dev # TODO: add back ARM support #- os: ubuntu-latest-16-cores # target: aarch64-unknown-linux-gnu