From ba23e00b9a0be2262f2bfe2fbe38ae0e67cbcf06 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Mon, 7 Oct 2024 17:04:36 -0700 Subject: [PATCH 01/30] Do not require source account when reading contract. (#1658) --- FULL_HELP_DOCS.md | 4 +--- .../soroban-test/tests/it/integration/cookbook.rs | 2 -- cmd/soroban-cli/src/commands/contract/read.rs | 15 +++++++++------ cookbook/contract-lifecycle.mdx | 2 +- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 5128ce396..e393818ce 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -747,7 +747,7 @@ Optimize a WASM file Print the current value of a contract-data ledger entry -**Usage:** `stellar contract read [OPTIONS] --source-account ` +**Usage:** `stellar contract read [OPTIONS]` ###### **Options:** @@ -781,8 +781,6 @@ Print the current value of a contract-data ledger entry * `--rpc-url ` — RPC server endpoint * `--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 "." diff --git a/cmd/crates/soroban-test/tests/it/integration/cookbook.rs b/cmd/crates/soroban-test/tests/it/integration/cookbook.rs index 82b9c5f43..5e9a30eb2 100644 --- a/cmd/crates/soroban-test/tests/it/integration/cookbook.rs +++ b/cmd/crates/soroban-test/tests/it/integration/cookbook.rs @@ -252,8 +252,6 @@ mod tests { .arg("xdr") .arg("--key") .arg("COUNTER") - .arg("--source-account") - .arg(source) .assert() .stdout_as_str(); let key_xdr = read_xdr.split(',').next().unwrap_or("").trim(); diff --git a/cmd/soroban-cli/src/commands/contract/read.rs b/cmd/soroban-cli/src/commands/contract/read.rs index 3cb253bb1..dae5f3cdf 100644 --- a/cmd/soroban-cli/src/commands/contract/read.rs +++ b/cmd/soroban-cli/src/commands/contract/read.rs @@ -28,7 +28,7 @@ pub struct Cmd { #[command(flatten)] pub key: key::Args, #[command(flatten)] - config: config::Args, + config: config::ArgsLocatorAndNetwork, } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, ValueEnum)] @@ -89,6 +89,8 @@ pub enum Error { OnlyDataAllowed, #[error(transparent)] Locator(#[from] locator::Error), + #[error(transparent)] + Network(#[from] config::network::Error), } impl Cmd { @@ -179,14 +181,15 @@ impl NetworkRunnable for Cmd { async fn run_against_rpc_server( &self, - _: Option<&global::Args>, - config: Option<&config::Args>, + _global_args: Option<&global::Args>, + _config: Option<&config::Args>, ) -> Result { - let config = config.unwrap_or(&self.config); - let network = config.get_network()?; + let locator = self.config.locator.clone(); + let network = self.config.network.get(&locator)?; + tracing::trace!(?network); let client = Client::new(&network.rpc_url)?; - let keys = self.key.parse_keys(&config.locator, &network)?; + let keys = self.key.parse_keys(&locator, &network)?; Ok(client.get_full_ledger_entries(&keys).await?) } } diff --git a/cookbook/contract-lifecycle.mdx b/cookbook/contract-lifecycle.mdx index b64262b34..e38a233de 100644 --- a/cookbook/contract-lifecycle.mdx +++ b/cookbook/contract-lifecycle.mdx @@ -47,7 +47,7 @@ stellar contract invoke --id --source alice --network testnet -- f 6. View the contract's state: ```bash -stellar contract read --id --network testnet --source alice --durability --key +stellar contract read --id --network testnet --durability --key ``` Note: `` is either `persistent` or `temporary`. `KEY` provides the key of the storage entry being read. From 8ebf6eaf370311a8218eeacad7a3da35b13b56e7 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Thu, 10 Oct 2024 00:47:41 +1000 Subject: [PATCH 02/30] Update xdr, env, sdk, strkey deps to compat with 22.0.0-rc.1 stream (#1646) --- .github/workflows/dependency-check.yml | 6 - Cargo.lock | 547 +++++++++++++++--- Cargo.toml | 50 +- FULL_HELP_DOCS.md | 26 + cmd/crates/soroban-spec-tools/Cargo.toml | 7 +- cmd/crates/soroban-spec-tools/src/contract.rs | 22 +- cmd/crates/soroban-test/Cargo.toml | 2 - cmd/crates/soroban-test/src/wasm.rs | 2 +- .../test-wasms/custom_account/Cargo.toml | 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/token/Cargo.toml | 4 +- .../tests/fixtures/test-wasms/udt/Cargo.toml | 4 +- .../contracts/add/Cargo.toml | 4 +- .../contracts/call/Cargo.toml | 4 +- .../workspace/contracts/add/Cargo.toml | 4 +- .../workspace/contracts/add/add2/Cargo.toml | 4 +- .../workspace/contracts/call/Cargo.toml | 4 +- .../soroban-test/tests/it/arg_parsing.rs | 2 +- .../soroban-test/tests/it/integration/tx.rs | 2 +- .../soroban-test/tests/it/integration/util.rs | 6 +- cmd/crates/stellar-ledger/Cargo.toml | 1 - cmd/crates/stellar-ledger/src/lib.rs | 8 +- .../tests/test/emulator_tests.rs | 6 +- cmd/soroban-cli/Cargo.toml | 1 - .../src/commands/contract/arg_parsing.rs | 2 +- .../src/commands/contract/deploy/asset.rs | 19 +- .../src/commands/contract/deploy/wasm.rs | 17 +- .../src/commands/contract/extend.rs | 4 +- .../src/commands/contract/id/asset.rs | 2 +- .../src/commands/contract/id/wasm.rs | 6 +- .../src/commands/contract/info/env_meta.rs | 25 +- .../src/commands/contract/info/shared.rs | 2 +- .../src/commands/contract/inspect.rs | 2 +- .../src/commands/contract/install.rs | 4 +- .../src/commands/contract/invoke.rs | 19 +- cmd/soroban-cli/src/commands/contract/mod.rs | 6 +- cmd/soroban-cli/src/commands/contract/read.rs | 15 +- .../src/commands/contract/restore.rs | 4 +- cmd/soroban-cli/src/commands/events.rs | 2 +- cmd/soroban-cli/src/commands/tx/hash.rs | 2 +- .../commands/tx/new/set_trustline_flags.rs | 4 +- cmd/soroban-cli/src/commands/tx/xdr.rs | 3 +- cmd/soroban-cli/src/commands/txn_result.rs | 2 +- cmd/soroban-cli/src/commands/version.rs | 6 +- cmd/soroban-cli/src/fee.rs | 2 +- cmd/soroban-cli/src/get_spec.rs | 6 +- cmd/soroban-cli/src/key.rs | 8 +- cmd/soroban-cli/src/lib.rs | 2 +- cmd/soroban-cli/src/log.rs | 5 +- cmd/soroban-cli/src/log/auth.rs | 2 +- cmd/soroban-cli/src/log/budget.rs | 5 - cmd/soroban-cli/src/log/cost.rs | 2 +- cmd/soroban-cli/src/log/footprint.rs | 2 +- cmd/soroban-cli/src/log/host_event.rs | 7 - cmd/soroban-cli/src/print.rs | 2 +- cmd/soroban-cli/src/signer.rs | 2 +- cmd/soroban-cli/src/tx/builder/transaction.rs | 2 +- cmd/soroban-cli/src/utils.rs | 4 +- cmd/soroban-cli/src/wasm.rs | 2 +- scripts/check-dependencies.bash | 61 -- 63 files changed, 656 insertions(+), 338 deletions(-) delete mode 100644 cmd/soroban-cli/src/log/budget.rs delete mode 100644 cmd/soroban-cli/src/log/host_event.rs delete mode 100755 scripts/check-dependencies.bash diff --git a/.github/workflows/dependency-check.yml b/.github/workflows/dependency-check.yml index cef838a7c..fe8c0e8bc 100644 --- a/.github/workflows/dependency-check.yml +++ b/.github/workflows/dependency-check.yml @@ -14,12 +14,6 @@ defaults: shell: bash jobs: - dependency-sanity-checker: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: rustup update - - run: scripts/check-dependencies.bash validate-rust-git-rev-deps: runs-on: ubuntu-latest steps: diff --git a/Cargo.lock b/Cargo.lock index 7ce514d54..33f0962d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,18 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -111,12 +123,136 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "ark-bls12-381" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c775f0d12169cba7aae4caeb547bb6a50781c7449a8aa53793827c9ec4abf488" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand", +] + [[package]] name = "arrayref" 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" @@ -1108,6 +1244,17 @@ dependencies = [ "serde", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_arbitrary" version = "1.3.2" @@ -1266,9 +1413,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "ecdsa" -version = "0.16.7" +version = "0.16.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der", "digest 0.10.7", @@ -2580,11 +2727,23 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", +] [[package]] name = "heck" @@ -3277,9 +3436,9 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.1" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -3563,6 +3722,12 @@ 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" @@ -5128,6 +5293,18 @@ dependencies = [ "syn 2.0.77", ] +[[package]] +name = "soroban-builtin-sdk-macros" +version = "22.0.0-rc.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4c8668199d95e3061cd42e1b96a91451c656a238a607fa53f96f0a3fdcf5f3" +dependencies = [ + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "soroban-cli" version = "21.5.0" @@ -5182,17 +5359,16 @@ dependencies = [ "serde_json", "sha2 0.10.8", "shlex", - "soroban-env-host", - "soroban-ledger-snapshot", - "soroban-sdk", - "soroban-spec", + "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-spec-json", - "soroban-spec-rust", + "soroban-spec-rust 22.0.0-rc.1.1", "soroban-spec-tools", "soroban-spec-typescript", "stellar-rpc-client", "stellar-strkey 0.0.11", - "stellar-xdr", + "stellar-xdr 22.0.0-rc.1.1", "strsim 0.10.0", "strum 0.17.1", "strum_macros 0.17.1", @@ -5227,10 +5403,28 @@ dependencies = [ "num-derive", "num-traits", "serde", - "soroban-env-macros", - "soroban-wasmi", + "soroban-env-macros 21.2.1", + "soroban-wasmi 0.31.1-soroban.20.0.1", + "static_assertions", + "stellar-xdr 21.2.0", + "wasmparser 0.116.1", +] + +[[package]] +name = "soroban-env-common" +version = "22.0.0-rc.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdf1d66133d6b29e2834acea79decb57c47c71aa01885cae2b9ad621d67525c" +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", "static_assertions", - "stellar-xdr", + "stellar-xdr 22.0.0-rc.1.1", "wasmparser 0.116.1", ] @@ -5240,7 +5434,17 @@ version = "21.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bfb2536811045d5cd0c656a324cbe9ce4467eb734c7946b74410d90dea5d0ce" dependencies = [ - "soroban-env-common", + "soroban-env-common 21.2.1", + "static_assertions", +] + +[[package]] +name = "soroban-env-guest" +version = "22.0.0-rc.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa9610ac8a4a900e6f35b2ed171bc325c7e9883929f5e9da758e85f1226dd284" +dependencies = [ + "soroban-env-common 22.0.0-rc.1.1", "static_assertions", ] @@ -5269,14 +5473,50 @@ dependencies = [ "sec1", "sha2 0.10.8", "sha3", - "soroban-builtin-sdk-macros", - "soroban-env-common", - "soroban-wasmi", + "soroban-builtin-sdk-macros 21.2.1", + "soroban-env-common 21.2.1", + "soroban-wasmi 0.31.1-soroban.20.0.1", "static_assertions", "stellar-strkey 0.0.8", "wasmparser 0.116.1", ] +[[package]] +name = "soroban-env-host" +version = "22.0.0-rc.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c695d22888ede1f98c016a4a690be307817d133be0e0f32a25fd6e53bb6c929" +dependencies = [ + "ark-bls12-381", + "ark-ec", + "ark-ff", + "ark-serialize", + "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 22.0.0-rc.1.1", + "soroban-env-common 22.0.0-rc.1.1", + "soroban-wasmi 0.36.1-soroban.22.0.0", + "static_assertions", + "stellar-strkey 0.0.9", + "wasmparser 0.116.1", +] + [[package]] name = "soroban-env-macros" version = "21.2.1" @@ -5288,7 +5528,22 @@ dependencies = [ "quote", "serde", "serde_json", - "stellar-xdr", + "stellar-xdr 21.2.0", + "syn 2.0.77", +] + +[[package]] +name = "soroban-env-macros" +version = "22.0.0-rc.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d926d0daa3ba798cd70ce962ea10012e630d75088352369a6d248b2644dd7a2c" +dependencies = [ + "itertools 0.10.5", + "proc-macro2", + "quote", + "serde", + "serde_json", + "stellar-xdr 22.0.0-rc.1.1", "syn 2.0.77", ] @@ -5298,15 +5553,29 @@ 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 = "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.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf596b2083946a95914a55d7d29cee6a8095b515fd06211851f45bf6af5a496" +checksum = "c07ca63290730b803f0637e00994f803d2f24cc6383ac8680724050d07690a89" dependencies = [ "serde", "serde_json", "serde_with", - "soroban-env-common", - "soroban-env-host", + "soroban-env-common 22.0.0-rc.1.1", + "soroban-env-host 22.0.0-rc.1.1", "thiserror", ] @@ -5323,18 +5592,35 @@ dependencies = [ "rand", "serde", "serde_json", - "soroban-env-guest", - "soroban-env-host", - "soroban-ledger-snapshot", - "soroban-sdk-macros", + "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.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b715e15357dbdda2fe0626005b75c2253bb3786deec3001d4077462a9dadd3" +dependencies = [ + "bytes-lit", + "rand", + "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", + "stellar-strkey 0.0.9", +] + [[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", @@ -5343,21 +5629,53 @@ dependencies = [ "quote", "rustc_version", "sha2 0.10.8", - "soroban-env-common", - "soroban-spec", - "soroban-spec-rust", - "stellar-xdr", + "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.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00d1b8d96ccf53ea9c30d86352756cace630ca5c7e1200fff32ffc793bedd593" +dependencies = [ + "crate-git-revision 0.0.6", + "darling", + "itertools 0.10.5", + "proc-macro2", + "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", + "stellar-xdr 22.0.0-rc.1.1", "syn 2.0.77", ] [[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", + "stellar-xdr 21.2.0", + "thiserror", + "wasmparser 0.116.1", +] + +[[package]] +name = "soroban-spec" +version = "22.0.0-rc.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4603430fd36848da7189e758d7f3fe1d7bbfef024e8aad2230a8be8252a583c1" +dependencies = [ + "base64 0.13.1", + "stellar-xdr 22.0.0-rc.1.1", "thiserror", "wasmparser 0.116.1", ] @@ -5371,23 +5689,39 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.9.9", - "soroban-spec", - "stellar-xdr", + "soroban-spec 22.0.0-rc.1.1", + "stellar-xdr 22.0.0-rc.1.1", "thiserror", ] [[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", - "stellar-xdr", + "soroban-spec 21.7.3", + "stellar-xdr 21.2.0", + "syn 2.0.77", + "thiserror", +] + +[[package]] +name = "soroban-spec-rust" +version = "22.0.0-rc.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d5f3fe5b27e0b1c1d9ecdff04c4e31f5cd4d12cdc052d54f0e4995cf637b9c" +dependencies = [ + "prettyplease", + "proc-macro2", + "quote", + "sha2 0.10.8", + "soroban-spec 22.0.0-rc.1.1", + "stellar-xdr 22.0.0-rc.1.1", "syn 2.0.77", "thiserror", ] @@ -5401,10 +5735,9 @@ dependencies = [ "hex", "itertools 0.10.5", "serde_json", - "soroban-env-host", - "soroban-spec", + "soroban-spec 22.0.0-rc.1.1", "stellar-strkey 0.0.11", - "stellar-xdr", + "stellar-xdr 22.0.0-rc.1.1", "thiserror", "tokio", "wasmparser 0.90.0", @@ -5425,8 +5758,8 @@ dependencies = [ "serde_derive", "serde_json", "sha2 0.9.9", - "soroban-spec", - "stellar-xdr", + "soroban-spec 22.0.0-rc.1.1", + "stellar-xdr 22.0.0-rc.1.1", "temp-dir", "thiserror", "walkdir", @@ -5446,10 +5779,8 @@ dependencies = [ "serde_json", "sha2 0.10.8", "soroban-cli", - "soroban-env-host", - "soroban-ledger-snapshot", - "soroban-sdk", - "soroban-spec", + "soroban-ledger-snapshot 22.0.0-rc.1.1", + "soroban-spec 22.0.0-rc.1.1", "soroban-spec-tools", "stellar-rpc-client", "stellar-strkey 0.0.11", @@ -5463,11 +5794,11 @@ dependencies = [ [[package]] name = "soroban-token-sdk" -version = "21.7.2" +version = "22.0.0-rc.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6ede0da76646037f3ea5db9ccd37830865444bb24f137cb8f0af8282c784f5" +checksum = "7baa9e15d0838973cfa0aa0eee6e0fa062bec2e4a115c82396f452fa6148d731" dependencies = [ - "soroban-sdk", + "soroban-sdk 22.0.0-rc.1.1", ] [[package]] @@ -5479,7 +5810,24 @@ dependencies = [ "smallvec", "spin", "wasmi_arena", - "wasmi_core", + "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.3", "wasmparser-nostd", ] @@ -5539,11 +5887,10 @@ dependencies = [ "serial_test", "sha2 0.9.9", "slip10", - "soroban-env-host", - "soroban-spec", + "soroban-spec 22.0.0-rc.1.1", "stellar-rpc-client", "stellar-strkey 0.0.11", - "stellar-xdr", + "stellar-xdr 22.0.0-rc.1.1", "test-case", "testcontainers", "thiserror", @@ -5554,8 +5901,7 @@ dependencies = [ [[package]] name = "stellar-rpc-client" version = "21.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c735c8e456fa7c37f72dd2a6abc022a111b3bf9b0520d50eef091eb1336ad370" +source = "git+https://github.com/stellar/rs-stellar-rpc-client?branch=main#9f748334fffb2762db01b566dee455eea3095c79" dependencies = [ "clap", "hex", @@ -5566,9 +5912,10 @@ dependencies = [ "serde", "serde-aux", "serde_json", + "serde_with", "sha2 0.10.8", - "stellar-strkey 0.0.8", - "stellar-xdr", + "stellar-strkey 0.0.9", + "stellar-xdr 22.0.0-rc.1.1", "termcolor", "termcolor_output", "thiserror", @@ -5587,6 +5934,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "stellar-strkey" +version = "0.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e3aa3ed00e70082cb43febc1c2afa5056b9bb3e348bbb43d0cd0aa88a611144" +dependencies = [ + "crate-git-revision 0.0.6", + "data-encoding", + "thiserror", +] + [[package]] name = "stellar-strkey" version = "0.0.11" @@ -5604,6 +5962,21 @@ 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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c88dc0e928b9cb65ea43836b52560bb4ead3e32895f5019ca223dc7cd1966cbf" +dependencies = [ "base64 0.13.1", "clap", "crate-git-revision 0.0.6", @@ -5613,10 +5986,21 @@ dependencies = [ "serde", "serde_json", "serde_with", - "stellar-strkey 0.0.8", + "stellar-strkey 0.0.9", "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" @@ -5864,35 +6248,35 @@ dependencies = [ name = "test_custom_account" version = "21.5.0" dependencies = [ - "soroban-sdk", + "soroban-sdk 21.7.2", ] [[package]] name = "test_custom_types" version = "21.5.0" dependencies = [ - "soroban-sdk", + "soroban-sdk 21.7.2", ] [[package]] name = "test_hello_world" version = "21.5.0" dependencies = [ - "soroban-sdk", + "soroban-sdk 21.7.2", ] [[package]] name = "test_swap" version = "21.5.0" dependencies = [ - "soroban-sdk", + "soroban-sdk 21.7.2", ] [[package]] name = "test_token" version = "21.5.0" dependencies = [ - "soroban-sdk", + "soroban-sdk 21.7.2", "soroban-token-sdk", ] @@ -5900,7 +6284,7 @@ dependencies = [ name = "test_udt" version = "21.5.0" dependencies = [ - "soroban-sdk", + "soroban-sdk 21.7.2", ] [[package]] @@ -6555,9 +6939,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", @@ -6572,6 +6956,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "104a7f73be44570cac297b3035d76b169d6599637631cf37a1703326a0727073" +[[package]] +name = "wasmi_collections" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ee1cf2328e7fbb8654fda8449395c64c36ef5a30511e79fae0265a96e1a446" +dependencies = [ + "ahash", + "hashbrown 0.14.5", + "string-interner", +] + [[package]] name = "wasmi_core" version = "0.13.0" @@ -6584,6 +6979,18 @@ dependencies = [ "paste", ] +[[package]] +name = "wasmi_core" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e77c1e701d21edfd263e5c6c940861202c6b840c715040cfdca6211bf8857aa" +dependencies = [ + "downcast-rs", + "libm", + "num-traits", + "paste", +] + [[package]] name = "wasmparser" version = "0.90.0" diff --git a/Cargo.toml b/Cargo.toml index 7282ff497..ef052c569 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,17 +14,10 @@ exclude = ["cmd/crates/soroban-test/tests/fixtures/hello"] version = "21.5.0" rust-version = "1.81.0" -[workspace.dependencies.soroban-env-host] -version = "=21.2.1" - -[workspace.dependencies.soroban-simulation] -version = "=21.2.1" - -[workspace.dependencies.soroban-spec] -version = "=21.7.2" - -[workspace.dependencies.soroban-spec-rust] -version = "=21.7.2" +# Dependencies located in this repo: +[workspace.dependencies.soroban-cli] +version = "=21.5.0" +path = "cmd/soroban-cli" [workspace.dependencies.soroban-spec-json] version = "=21.5.0" @@ -38,27 +31,35 @@ path = "./cmd/crates/soroban-spec-typescript" version = "21.5.0" path = "./cmd/crates/soroban-spec-tools" +# Dependencies from the rs-stellar-xdr repo: +[workspace.dependencies.stellar-xdr] +version = "=22.0.0-rc.1.1" +default-features = true + +# Dependencies from the rs-soroban-sdk repo: +[workspace.dependencies.soroban-spec] +version = "=22.0.0-rc.1.1" + +[workspace.dependencies.soroban-spec-rust] +version = "=22.0.0-rc.1.1" + [workspace.dependencies.soroban-sdk] -version = "=21.7.2" +version = "=22.0.0-rc.1.1" [workspace.dependencies.soroban-token-sdk] -version = "=21.7.2" +version = "=22.0.0-rc.1.1" [workspace.dependencies.soroban-ledger-snapshot] -version = "=21.7.2" - -[workspace.dependencies.soroban-cli] -version = "=21.5.0" -path = "cmd/soroban-cli" +version = "=22.0.0-rc.1.1" +# 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" -[workspace.dependencies.stellar-xdr] -version = "21.2.0" -default-features = true - +# Dependencies from elsewhere shared by crates: [workspace.dependencies] stellar-strkey = "0.0.11" sep5 = "0.0.4" @@ -70,11 +71,9 @@ hex = "0.4.3" itertools = "0.10.0" async-trait = "0.1.76" bollard = "0.16.0" - serde-aux = "4.1.2" serde_json = "1.0.82" serde = "1.0.82" - clap = { version = "4.1.8", features = [ "derive", "env", @@ -92,8 +91,7 @@ ulid = "1.1" termcolor = "1.1.3" termcolor_output = "1.0.1" ed25519-dalek = ">= 2.1.1" - -# networking +http = "1.0.0" jsonrpsee-http-client = "0.20.1" jsonrpsee-core = "0.20.1" tokio = "1.28.1" diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index e393818ce..2fd02cafb 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1630,6 +1630,7 @@ Decode and encode XDR * `guess` — Guess the XDR type * `decode` — Decode XDR * `encode` — Encode XDR +* `compare` — Compare two XDR values with each other * `version` — Print version information ###### **Arguments:** @@ -1768,6 +1769,31 @@ Encode XDR Default value: `single-base64` + Possible values: `single`, `single-base64`, `stream` + + + + +## `stellar xdr compare` + +Compare two XDR values with each other + +Outputs: `-1` when the left XDR value is less than the right XDR value, `0` when the left XDR value is equal to the right XDR value, `1` when the left XDR value is greater than the right XDR value + +**Usage:** `stellar xdr compare [OPTIONS] --type ` + +###### **Arguments:** + +* `` — XDR file to decode and compare with the right value +* `` — XDR file to decode and compare with the left value + +###### **Options:** + +* `--type ` — XDR type of both inputs +* `--input ` + + Default value: `single-base64` + Possible values: `single`, `single-base64` diff --git a/cmd/crates/soroban-spec-tools/Cargo.toml b/cmd/crates/soroban-spec-tools/Cargo.toml index 514b82924..a17a5d31f 100644 --- a/cmd/crates/soroban-spec-tools/Cargo.toml +++ b/cmd/crates/soroban-spec-tools/Cargo.toml @@ -19,9 +19,7 @@ crate-type = ["rlib"] [dependencies] soroban-spec = { workspace = true } stellar-strkey = { workspace = true } -stellar-xdr = { workspace = true, features = ["curr", "std", "serde"] } -soroban-env-host = { workspace = true } - +stellar-xdr = { workspace = true, features = ["curr", "std", "serde", "base64"] } serde_json = { workspace = true } itertools = { workspace = true } ethnum = { workspace = true } @@ -29,9 +27,6 @@ hex = { workspace = true } wasmparser = { workspace = true } base64 = { workspace = true } thiserror = "1.0.31" -# soroban-ledger-snapshot = { workspace = true } -# soroban-sdk = { workspace = true } -# sep5 = { workspace = true } [dev-dependencies] diff --git a/cmd/crates/soroban-spec-tools/src/contract.rs b/cmd/crates/soroban-spec-tools/src/contract.rs index 334b2425f..9984a19d1 100644 --- a/cmd/crates/soroban-spec-tools/src/contract.rs +++ b/cmd/crates/soroban-spec-tools/src/contract.rs @@ -4,10 +4,10 @@ use std::{ io::{self, Cursor}, }; -use soroban_env_host::xdr::{ - self, Limited, Limits, ReadXdr, ScEnvMetaEntry, ScMetaEntry, ScMetaV0, ScSpecEntry, - ScSpecFunctionV0, ScSpecUdtEnumV0, ScSpecUdtErrorEnumV0, ScSpecUdtStructV0, ScSpecUdtUnionV0, - StringM, WriteXdr, +use stellar_xdr::curr::{ + self as xdr, Limited, Limits, ReadXdr, ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion, + ScMetaEntry, ScMetaV0, ScSpecEntry, ScSpecFunctionV0, ScSpecUdtEnumV0, ScSpecUdtErrorEnumV0, + ScSpecUdtStructV0, ScSpecUdtUnionV0, StringM, WriteXdr, }; pub struct Spec { @@ -121,10 +121,16 @@ impl Display for Spec { writeln!(f, "Env Meta: {env_meta}")?; for env_meta_entry in &self.env_meta { match env_meta_entry { - ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(v) => { - let protocol = v >> 32; - let interface = v & 0xffff_ffff; - writeln!(f, " • Interface Version: {v} (protocol: {protocol}, interface: {interface})")?; + ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion( + ScEnvMetaEntryInterfaceVersion { + protocol, + pre_release, + }, + ) => { + writeln!(f, " • Protocol Version: {protocol}")?; + if pre_release != &0 { + writeln!(f, " • Pre-release Version: {pre_release})")?; + } } } } diff --git a/cmd/crates/soroban-test/Cargo.toml b/cmd/crates/soroban-test/Cargo.toml index a34b7c65c..b240494e4 100644 --- a/cmd/crates/soroban-test/Cargo.toml +++ b/cmd/crates/soroban-test/Cargo.toml @@ -17,12 +17,10 @@ crate-type = ["rlib", "cdylib"] [dependencies] -soroban-env-host = { workspace = true } soroban-spec = { workspace = true } soroban-spec-tools = { workspace = true } soroban-ledger-snapshot = { workspace = true } stellar-strkey = { workspace = true } -soroban-sdk = { workspace = true } sep5 = { workspace = true } soroban-cli = { workspace = true } soroban-rpc = { workspace = true } diff --git a/cmd/crates/soroban-test/src/wasm.rs b/cmd/crates/soroban-test/src/wasm.rs index d03114b93..3e473ed46 100644 --- a/cmd/crates/soroban-test/src/wasm.rs +++ b/cmd/crates/soroban-test/src/wasm.rs @@ -1,7 +1,7 @@ use std::{fmt::Display, fs, path::PathBuf}; use sha2::{Digest, Sha256}; -use soroban_env_host::xdr; +use soroban_cli::xdr; #[derive(thiserror::Error, Debug)] pub enum Error { 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 d4405c512..792925edb 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 = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"]} +soroban-sdk = { version = "=21.7.2", features = ["testutils"]} 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 17e618805..398520104 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 = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"]} +soroban-sdk = { version = "=21.7.2", 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 9ad83fd1c..5f8b1256f 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 = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"]} +soroban-sdk = { version = "=21.7.2", 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 f74201a31..509483408 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 = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"] } +soroban-sdk = { version = "=21.7.2", features = ["testutils"] } 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..8875b87e7 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 = { workspace = true } +soroban-sdk = { version = "=21.7.2" } soroban-token-sdk = { workspace = true } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"] } +soroban-sdk = { version = "=21.7.2", features = ["testutils"] } 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 206284802..aea356447 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 = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true , features = ["testutils"]} +soroban-sdk = { version = "=21.7.2" , features = ["testutils"]} diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace-with-default-members/contracts/add/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/workspace-with-default-members/contracts/add/Cargo.toml index 660b7eb11..ca38cca49 100644 --- a/cmd/crates/soroban-test/tests/fixtures/workspace-with-default-members/contracts/add/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/workspace-with-default-members/contracts/add/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"] } +soroban-sdk = { version = "=21.7.2", features = ["testutils"] } diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace-with-default-members/contracts/call/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/workspace-with-default-members/contracts/call/Cargo.toml index 48e32b14d..a1ba4ed43 100644 --- a/cmd/crates/soroban-test/tests/fixtures/workspace-with-default-members/contracts/call/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/workspace-with-default-members/contracts/call/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"] } +soroban-sdk = { version = "=21.7.2", features = ["testutils"] } diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/Cargo.toml index 660b7eb11..ca38cca49 100644 --- a/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"] } +soroban-sdk = { version = "=21.7.2", features = ["testutils"] } diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/add2/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/add2/Cargo.toml index bae834e02..b6b570327 100644 --- a/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/add2/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/add/add2/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"] } +soroban-sdk = { version = "=21.7.2", features = ["testutils"] } diff --git a/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/call/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/call/Cargo.toml index 48e32b14d..a1ba4ed43 100644 --- a/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/call/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/workspace/contracts/call/Cargo.toml @@ -9,7 +9,7 @@ crate-type = ["cdylib"] doctest = false [dependencies] -soroban-sdk = { workspace = true } +soroban-sdk = { version = "=21.7.2" } [dev-dependencies] -soroban-sdk = { workspace = true, features = ["testutils"] } +soroban-sdk = { version = "=21.7.2", features = ["testutils"] } diff --git a/cmd/crates/soroban-test/tests/it/arg_parsing.rs b/cmd/crates/soroban-test/tests/it/arg_parsing.rs index c245fd8c9..d25d22354 100644 --- a/cmd/crates/soroban-test/tests/it/arg_parsing.rs +++ b/cmd/crates/soroban-test/tests/it/arg_parsing.rs @@ -1,6 +1,6 @@ use crate::util::CUSTOM_TYPES; use serde_json::json; -use soroban_env_host::xdr::{ +use soroban_cli::xdr::{ ScBytes, ScSpecTypeBytesN, ScSpecTypeDef, ScSpecTypeOption, ScSpecTypeUdt, ScVal, }; use soroban_spec_tools::{from_string_primitive, Spec}; diff --git a/cmd/crates/soroban-test/tests/it/integration/tx.rs b/cmd/crates/soroban-test/tests/it/integration/tx.rs index 5cc6bdb9b..c3cd2693b 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx.rs @@ -1,5 +1,5 @@ use soroban_cli::assembled::simulate_and_assemble_transaction; -use soroban_sdk::xdr::{Limits, ReadXdr, TransactionEnvelope, WriteXdr}; +use soroban_cli::xdr::{Limits, ReadXdr, TransactionEnvelope, WriteXdr}; use soroban_test::{AssertExt, TestEnv}; use crate::integration::util::{deploy_contract, DeployKind, HELLO_WORLD}; diff --git a/cmd/crates/soroban-test/tests/it/integration/util.rs b/cmd/crates/soroban-test/tests/it/integration/util.rs index 6feae7860..438428e38 100644 --- a/cmd/crates/soroban-test/tests/it/integration/util.rs +++ b/cmd/crates/soroban-test/tests/it/integration/util.rs @@ -1,5 +1,7 @@ -use soroban_cli::commands; -use soroban_sdk::xdr::{Limits, WriteXdr}; +use soroban_cli::{ + commands, + xdr::{Limits, WriteXdr}, +}; use soroban_test::{TestEnv, Wasm}; use std::fmt::Display; diff --git a/cmd/crates/stellar-ledger/Cargo.toml b/cmd/crates/stellar-ledger/Cargo.toml index b8894b71d..abf73c375 100644 --- a/cmd/crates/stellar-ledger/Cargo.toml +++ b/cmd/crates/stellar-ledger/Cargo.toml @@ -17,7 +17,6 @@ serde = "1.0.82" serde_derive = "1.0.82" serde_json = "1.0.82" sha2 = "0.9.9" -soroban-env-host = { workspace = true } ed25519-dalek = { workspace = true } stellar-strkey = { workspace = true } ledger-transport-hid = "0.10.0" diff --git a/cmd/crates/stellar-ledger/src/lib.rs b/cmd/crates/stellar-ledger/src/lib.rs index c74365af2..e90c31bb9 100644 --- a/cmd/crates/stellar-ledger/src/lib.rs +++ b/cmd/crates/stellar-ledger/src/lib.rs @@ -5,12 +5,11 @@ use ledger_transport_hid::{ LedgerHIDError, TransportNativeHID, }; -use soroban_env_host::xdr::{Hash, Transaction}; use std::vec; use stellar_strkey::DecodeError; use stellar_xdr::curr::{ - self as xdr, Limits, TransactionSignaturePayload, TransactionSignaturePayloadTaggedTransaction, - WriteXdr, + self as xdr, Hash, Limits, Transaction, TransactionSignaturePayload, + TransactionSignaturePayloadTaggedTransaction, WriteXdr, }; pub use crate::signer::Blob; @@ -312,10 +311,9 @@ mod test { use crate::Blob; use test_helpers::test::emulator_http_transport::EmulatorHttpTransport; - use soroban_env_host::xdr::Transaction; use std::vec; - use soroban_env_host::xdr::{self, Operation, OperationBody, Uint256}; + use super::xdr::{self, Operation, OperationBody, Transaction, Uint256}; use crate::{test_network_hash, Error, LedgerSigner}; diff --git a/cmd/crates/stellar-ledger/tests/test/emulator_tests.rs b/cmd/crates/stellar-ledger/tests/test/emulator_tests.rs index d45981eef..1b0c09bab 100644 --- a/cmd/crates/stellar-ledger/tests/test/emulator_tests.rs +++ b/cmd/crates/stellar-ledger/tests/test/emulator_tests.rs @@ -1,8 +1,6 @@ use ledger_transport::Exchange; use once_cell::sync::Lazy; use serde::Deserialize; -use soroban_env_host::xdr::{self, Operation, OperationBody, Uint256}; -use soroban_env_host::xdr::{Hash, Transaction}; use std::ops::Range; use std::sync::Mutex; use std::vec; @@ -15,8 +13,10 @@ use std::sync::Arc; use std::{collections::HashMap, time::Duration}; use stellar_xdr::curr::{ - Memo, MuxedAccount, PaymentOp, Preconditions, SequenceNumber, TransactionExt, + self as xdr, Hash, Memo, MuxedAccount, Operation, OperationBody, PaymentOp, Preconditions, + SequenceNumber, Transaction, TransactionExt, Uint256, }; + use testcontainers::{core::ContainerPort, runners::AsyncRunner, ContainerAsync, ImageExt}; use tokio::time::sleep; diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 646e8a92e..da142ad57 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -40,7 +40,6 @@ opt = ["dep:wasm-opt"] [dependencies] stellar-xdr = { workspace = true, features = ["cli"] } -soroban-env-host = { workspace = true } soroban-spec = { workspace = true } soroban-spec-json = { workspace = true } soroban-spec-rust = { workspace = true } diff --git a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs index 4a8af47e2..2eb3c2696 100644 --- a/cmd/soroban-cli/src/commands/contract/arg_parsing.rs +++ b/cmd/soroban-cli/src/commands/contract/arg_parsing.rs @@ -8,7 +8,7 @@ use clap::value_parser; use ed25519_dalek::SigningKey; use heck::ToKebabCase; -use soroban_env_host::xdr::{ +use crate::xdr::{ self, Hash, InvokeContractArgs, ScAddress, ScSpecEntry, ScSpecFunctionV0, ScSpecTypeDef, ScVal, ScVec, }; diff --git a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs index 8ff8e08b3..ad0afce5e 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs @@ -1,13 +1,10 @@ -use clap::{arg, command, Parser}; -use soroban_env_host::{ - xdr::{ - Asset, ContractDataDurability, ContractExecutable, ContractIdPreimage, CreateContractArgs, - Error as XdrError, Hash, HostFunction, InvokeHostFunctionOp, LedgerKey::ContractData, - LedgerKeyContractData, Limits, Memo, MuxedAccount, Operation, OperationBody, Preconditions, - ScAddress, ScVal, SequenceNumber, Transaction, TransactionExt, VecM, WriteXdr, - }, - HostError, +use crate::xdr::{ + Asset, ContractDataDurability, ContractExecutable, ContractIdPreimage, CreateContractArgs, + Error as XdrError, Hash, HostFunction, InvokeHostFunctionOp, LedgerKey::ContractData, + LedgerKeyContractData, Limits, Memo, MuxedAccount, Operation, OperationBody, Preconditions, + ScAddress, ScVal, SequenceNumber, Transaction, TransactionExt, VecM, WriteXdr, }; +use clap::{arg, command, Parser}; use std::convert::Infallible; use std::{array::TryFromSliceError, fmt::Debug, num::ParseIntError}; @@ -26,10 +23,6 @@ use crate::{ #[derive(thiserror::Error, Debug)] pub enum Error { - #[error(transparent)] - // TODO: the Display impl of host errors is pretty user-unfriendly - // (it just calls Debug). I think we can do better than that - Host(#[from] HostError), #[error("error parsing int: {0}")] ParseIntError(#[from] ParseIntError), #[error(transparent)] diff --git a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs index 36ce2e9f7..03ed3f438 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs @@ -2,18 +2,15 @@ use std::array::TryFromSliceError; 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, +}; use clap::{arg, command, Parser}; use rand::Rng; use regex::Regex; -use soroban_env_host::{ - 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, - }, - HostError, -}; use crate::{ assembled::simulate_and_assemble_transaction, @@ -70,8 +67,6 @@ pub struct Cmd { pub enum Error { #[error(transparent)] Install(#[from] install::Error), - #[error(transparent)] - Host(#[from] HostError), #[error("error parsing int: {0}")] ParseIntError(#[from] ParseIntError), #[error("internal conversion error: {0}")] diff --git a/cmd/soroban-cli/src/commands/contract/extend.rs b/cmd/soroban-cli/src/commands/contract/extend.rs index 3f7477254..92b986a22 100644 --- a/cmd/soroban-cli/src/commands/contract/extend.rs +++ b/cmd/soroban-cli/src/commands/contract/extend.rs @@ -1,12 +1,12 @@ use std::{fmt::Debug, path::Path, str::FromStr}; -use clap::{command, Parser}; -use soroban_env_host::xdr::{ +use crate::xdr::{ Error as XdrError, ExtendFootprintTtlOp, ExtensionPoint, LedgerEntry, LedgerEntryChange, LedgerEntryData, LedgerFootprint, Limits, Memo, Operation, OperationBody, Preconditions, SequenceNumber, SorobanResources, SorobanTransactionData, Transaction, TransactionExt, TransactionMeta, TransactionMetaV3, TtlEntry, WriteXdr, }; +use clap::{command, Parser}; use crate::{ assembled::simulate_and_assemble_transaction, diff --git a/cmd/soroban-cli/src/commands/contract/id/asset.rs b/cmd/soroban-cli/src/commands/contract/id/asset.rs index cdf826015..921592cf8 100644 --- a/cmd/soroban-cli/src/commands/contract/id/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/id/asset.rs @@ -20,7 +20,7 @@ pub enum Error { #[error(transparent)] ConfigError(#[from] config::Error), #[error(transparent)] - Xdr(#[from] soroban_env_host::xdr::Error), + Xdr(#[from] crate::xdr::Error), } impl Cmd { pub fn run(&self) -> Result<(), Error> { diff --git a/cmd/soroban-cli/src/commands/contract/id/wasm.rs b/cmd/soroban-cli/src/commands/contract/id/wasm.rs index c020e94b2..349dd167b 100644 --- a/cmd/soroban-cli/src/commands/contract/id/wasm.rs +++ b/cmd/soroban-cli/src/commands/contract/id/wasm.rs @@ -1,9 +1,9 @@ -use clap::{arg, command, Parser}; -use sha2::{Digest, Sha256}; -use soroban_env_host::xdr::{ +use crate::xdr::{ self, AccountId, ContractIdPreimage, ContractIdPreimageFromAddress, Hash, HashIdPreimage, HashIdPreimageContractId, Limits, PublicKey, ScAddress, Uint256, WriteXdr, }; +use clap::{arg, command, Parser}; +use sha2::{Digest, Sha256}; use crate::config; 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 03225c328..bc2d03bc6 100644 --- a/cmd/soroban-cli/src/commands/contract/info/env_meta.rs +++ b/cmd/soroban-cli/src/commands/contract/info/env_meta.rs @@ -1,14 +1,17 @@ use std::fmt::Debug; use clap::{command, Parser}; -use stellar_xdr::curr::ScEnvMetaEntry; use soroban_spec_tools::contract; use soroban_spec_tools::contract::Spec; -use crate::commands::contract::info::env_meta::Error::{NoEnvMetaPresent, NoSACEnvMeta}; -use crate::commands::contract::info::shared; -use crate::commands::contract::info::shared::{fetch_wasm, MetasInfoOutput}; +use crate::{ + commands::contract::info::{ + env_meta::Error::{NoEnvMetaPresent, NoSACEnvMeta}, + shared::{self, fetch_wasm, MetasInfoOutput}, + }, + xdr::{ScEnvMetaEntry, ScEnvMetaEntryInterfaceVersion}, +}; #[derive(Parser, Debug, Clone)] pub struct Cmd { @@ -54,12 +57,16 @@ impl Cmd { let mut meta_str = "Contract env-meta:\n".to_string(); for env_meta_entry in &spec.env_meta { match env_meta_entry { - ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion(v) => { - let protocol = v >> 32; - let interface = v & 0xffff_ffff; + ScEnvMetaEntry::ScEnvMetaKindInterfaceVersion( + ScEnvMetaEntryInterfaceVersion { + protocol, + pre_release, + }, + ) => { meta_str.push_str(&format!(" • Protocol: v{protocol}\n")); - meta_str.push_str(&format!(" • Interface: v{interface}\n")); - meta_str.push_str(&format!(" • Interface Version: {v}\n")); + if pre_release != &0 { + meta_str.push_str(&format!(" • Pre-release: v{pre_release}\n")); + } } } } diff --git a/cmd/soroban-cli/src/commands/contract/info/shared.rs b/cmd/soroban-cli/src/commands/contract/info/shared.rs index 25cbc9258..4113f7d5b 100644 --- a/cmd/soroban-cli/src/commands/contract/info/shared.rs +++ b/cmd/soroban-cli/src/commands/contract/info/shared.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; +use crate::xdr; use clap::arg; -use soroban_env_host::xdr; use soroban_rpc::Client; use crate::commands::contract::info::shared::Error::InvalidWasmHash; diff --git a/cmd/soroban-cli/src/commands/contract/inspect.rs b/cmd/soroban-cli/src/commands/contract/inspect.rs index 46fdc33a7..86559641b 100644 --- a/cmd/soroban-cli/src/commands/contract/inspect.rs +++ b/cmd/soroban-cli/src/commands/contract/inspect.rs @@ -1,5 +1,5 @@ +use crate::xdr; use clap::{command, Parser}; -use soroban_env_host::xdr; use soroban_spec_tools::contract; use std::{fmt::Debug, path::PathBuf}; use tracing::debug; diff --git a/cmd/soroban-cli/src/commands/contract/install.rs b/cmd/soroban-cli/src/commands/contract/install.rs index b70cadb78..d51158ec3 100644 --- a/cmd/soroban-cli/src/commands/contract/install.rs +++ b/cmd/soroban-cli/src/commands/contract/install.rs @@ -2,12 +2,12 @@ use std::array::TryFromSliceError; use std::fmt::Debug; use std::num::ParseIntError; -use clap::{command, Parser}; -use soroban_env_host::xdr::{ +use crate::xdr::{ self, ContractCodeEntryExt, Error as XdrError, Hash, HostFunction, InvokeHostFunctionOp, LedgerEntryData, Limits, OperationBody, ReadXdr, ScMetaEntry, ScMetaV0, Transaction, TransactionResult, TransactionResultResult, VecM, WriteXdr, }; +use clap::{command, Parser}; use super::restore; use crate::assembled::simulate_and_assemble_transaction; diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index 55e2554bf..e32d5d5a6 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -7,15 +7,12 @@ use std::{fmt::Debug, fs, io}; use clap::{arg, command, Parser, ValueEnum}; -use soroban_env_host::{ - 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, - }, - HostError, +use crate::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, }; use soroban_rpc::{SimulateHostFunctionResult, SimulateTransactionResponse}; @@ -80,10 +77,6 @@ impl Pwd for Cmd { pub enum Error { #[error("cannot add contract to ledger entries: {0}")] CannotAddContractToLedgerEntries(xdr::Error), - #[error(transparent)] - // TODO: the Display impl of host errors is pretty user-unfriendly - // (it just calls Debug). I think we can do better than that - Host(#[from] HostError), #[error("reading file {0:?}: {1}")] CannotReadContractFile(PathBuf, io::Error), #[error("committing file {filepath}: {error}")] diff --git a/cmd/soroban-cli/src/commands/contract/mod.rs b/cmd/soroban-cli/src/commands/contract/mod.rs index 9ac6b8527..4f3c6f7f4 100644 --- a/cmd/soroban-cli/src/commands/contract/mod.rs +++ b/cmd/soroban-cli/src/commands/contract/mod.rs @@ -168,11 +168,11 @@ pub enum Durability { Temporary, } -impl From<&Durability> for soroban_env_host::xdr::ContractDataDurability { +impl From<&Durability> for crate::xdr::ContractDataDurability { fn from(d: &Durability) -> Self { match d { - Durability::Persistent => soroban_env_host::xdr::ContractDataDurability::Persistent, - Durability::Temporary => soroban_env_host::xdr::ContractDataDurability::Temporary, + Durability::Persistent => crate::xdr::ContractDataDurability::Persistent, + Durability::Temporary => crate::xdr::ContractDataDurability::Temporary, } } } diff --git a/cmd/soroban-cli/src/commands/contract/read.rs b/cmd/soroban-cli/src/commands/contract/read.rs index dae5f3cdf..4e013a1f4 100644 --- a/cmd/soroban-cli/src/commands/contract/read.rs +++ b/cmd/soroban-cli/src/commands/contract/read.rs @@ -3,14 +3,11 @@ use std::{ io::{self, stdout}, }; -use clap::{command, Parser, ValueEnum}; -use soroban_env_host::{ - xdr::{ - ContractDataEntry, Error as XdrError, LedgerEntryData, LedgerKey, LedgerKeyContractData, - Limits, ScVal, WriteXdr, - }, - HostError, +use crate::xdr::{ + ContractDataEntry, Error as XdrError, LedgerEntryData, LedgerKey, LedgerKeyContractData, + Limits, ScVal, WriteXdr, }; +use clap::{command, Parser, ValueEnum}; use crate::{ commands::{global, NetworkRunnable}, @@ -77,10 +74,6 @@ pub enum Error { Rpc(#[from] rpc::Error), #[error(transparent)] Xdr(#[from] XdrError), - #[error(transparent)] - // TODO: the Display impl of host errors is pretty user-unfriendly - // (it just calls Debug). I think we can do better than that - Host(#[from] HostError), #[error("no matching contract data entries were found for the specified contract id")] NoContractDataEntryFoundForContractID, #[error(transparent)] diff --git a/cmd/soroban-cli/src/commands/contract/restore.rs b/cmd/soroban-cli/src/commands/contract/restore.rs index 05fa90695..627fd3eee 100644 --- a/cmd/soroban-cli/src/commands/contract/restore.rs +++ b/cmd/soroban-cli/src/commands/contract/restore.rs @@ -1,12 +1,12 @@ use std::{fmt::Debug, path::Path, str::FromStr}; -use clap::{command, Parser}; -use soroban_env_host::xdr::{ +use crate::xdr::{ Error as XdrError, ExtensionPoint, LedgerEntry, LedgerEntryChange, LedgerEntryData, LedgerFootprint, Limits, Memo, Operation, OperationBody, OperationMeta, Preconditions, RestoreFootprintOp, SequenceNumber, SorobanResources, SorobanTransactionData, Transaction, TransactionExt, TransactionMeta, TransactionMetaV3, TtlEntry, WriteXdr, }; +use clap::{command, Parser}; use stellar_strkey::DecodeError; use crate::{ diff --git a/cmd/soroban-cli/src/commands/events.rs b/cmd/soroban-cli/src/commands/events.rs index 5e2bda66f..0c4cfcc0e 100644 --- a/cmd/soroban-cli/src/commands/events.rs +++ b/cmd/soroban-cli/src/commands/events.rs @@ -1,7 +1,7 @@ use clap::{arg, command, Parser}; use std::io; -use soroban_env_host::xdr::{self, Limits, ReadXdr}; +use crate::xdr::{self, Limits, ReadXdr}; use super::{global, NetworkRunnable}; use crate::config::{self, locator, network}; diff --git a/cmd/soroban-cli/src/commands/tx/hash.rs b/cmd/soroban-cli/src/commands/tx/hash.rs index 8d8ec6d82..c422302f6 100644 --- a/cmd/soroban-cli/src/commands/tx/hash.rs +++ b/cmd/soroban-cli/src/commands/tx/hash.rs @@ -7,7 +7,7 @@ pub enum Error { #[error(transparent)] TxEnvelopeFromStdin(#[from] super::xdr::Error), #[error(transparent)] - XdrToBase64(#[from] soroban_env_host::xdr::Error), + XdrToBase64(#[from] crate::xdr::Error), #[error(transparent)] Config(#[from] network::Error), } 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 2955fe5b0..d9b70ecbd 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 @@ -1,8 +1,6 @@ use clap::{command, Parser}; -use soroban_sdk::xdr::{self}; - -use crate::{commands::tx, tx::builder}; +use crate::{commands::tx, tx::builder, xdr}; #[allow(clippy::struct_excessive_bools, clippy::doc_markdown)] #[derive(Parser, Debug, Clone)] diff --git a/cmd/soroban-cli/src/commands/tx/xdr.rs b/cmd/soroban-cli/src/commands/tx/xdr.rs index 71bd59af6..fcacce9ac 100644 --- a/cmd/soroban-cli/src/commands/tx/xdr.rs +++ b/cmd/soroban-cli/src/commands/tx/xdr.rs @@ -3,8 +3,7 @@ use std::{ path::PathBuf, }; -use soroban_env_host::xdr::ReadXdr; -use soroban_sdk::xdr::{Limits, Transaction, TransactionEnvelope, TransactionV1Envelope}; +use crate::xdr::{Limits, ReadXdr, Transaction, TransactionEnvelope, TransactionV1Envelope}; #[derive(Debug, thiserror::Error)] pub enum Error { diff --git a/cmd/soroban-cli/src/commands/txn_result.rs b/cmd/soroban-cli/src/commands/txn_result.rs index 08482e94f..d6b308b3a 100644 --- a/cmd/soroban-cli/src/commands/txn_result.rs +++ b/cmd/soroban-cli/src/commands/txn_result.rs @@ -1,4 +1,4 @@ -use soroban_env_host::xdr::{Transaction, TransactionEnvelope, TransactionV1Envelope, VecM}; +use crate::xdr::{Transaction, TransactionEnvelope, TransactionV1Envelope, VecM}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum TxnResult { diff --git a/cmd/soroban-cli/src/commands/version.rs b/cmd/soroban-cli/src/commands/version.rs index 5e6d0e4dd..f785399e9 100644 --- a/cmd/soroban-cli/src/commands/version.rs +++ b/cmd/soroban-cli/src/commands/version.rs @@ -1,5 +1,4 @@ use clap::Parser; -use soroban_env_host::meta; use std::fmt::Debug; #[derive(Parser, Debug, Clone)] @@ -22,12 +21,9 @@ pub fn git() -> &'static str { } pub fn long() -> String { - let env = soroban_env_host::VERSION; - let xdr = soroban_env_host::VERSION.xdr; + let xdr = stellar_xdr::VERSION; [ format!("{} ({})", pkg(), git()), - format!("soroban-env {} ({})", env.pkg, env.rev), - format!("soroban-env interface version {}", meta::INTERFACE_VERSION), format!( "stellar-xdr {} ({}) xdr curr ({})", diff --git a/cmd/soroban-cli/src/fee.rs b/cmd/soroban-cli/src/fee.rs index c2bc32bdb..f6afdc500 100644 --- a/cmd/soroban-cli/src/fee.rs +++ b/cmd/soroban-cli/src/fee.rs @@ -1,7 +1,7 @@ use clap::arg; use crate::assembled::Assembled; -use soroban_env_host::xdr; +use crate::xdr; use crate::commands::HEADING_RPC; diff --git a/cmd/soroban-cli/src/get_spec.rs b/cmd/soroban-cli/src/get_spec.rs index 125fa984c..26e609543 100644 --- a/cmd/soroban-cli/src/get_spec.rs +++ b/cmd/soroban-cli/src/get_spec.rs @@ -1,8 +1,6 @@ -use soroban_env_host::xdr; +use crate::xdr; -use soroban_env_host::xdr::{ - ContractDataEntry, ContractExecutable, ScContractInstance, ScSpecEntry, ScVal, -}; +use crate::xdr::{ContractDataEntry, ContractExecutable, ScContractInstance, ScSpecEntry, ScVal}; use soroban_spec::read::FromWasmError; pub use soroban_spec_tools::contract as contract_spec; diff --git a/cmd/soroban-cli/src/key.rs b/cmd/soroban-cli/src/key.rs index b4fd358aa..3f4dcaf7c 100644 --- a/cmd/soroban-cli/src/key.rs +++ b/cmd/soroban-cli/src/key.rs @@ -1,13 +1,13 @@ +use crate::xdr::{ + self, LedgerKey, LedgerKeyContractCode, LedgerKeyContractData, Limits, ReadXdr, ScAddress, + ScVal, +}; use crate::{ commands::contract::Durability, config::{locator, network::Network}, wasm, }; use clap::arg; -use soroban_env_host::xdr::{ - self, LedgerKey, LedgerKeyContractCode, LedgerKeyContractData, Limits, ReadXdr, ScAddress, - ScVal, -}; use std::path::PathBuf; #[derive(thiserror::Error, Debug)] diff --git a/cmd/soroban-cli/src/lib.rs b/cmd/soroban-cli/src/lib.rs index 4c904855c..302ecab00 100644 --- a/cmd/soroban-cli/src/lib.rs +++ b/cmd/soroban-cli/src/lib.rs @@ -5,8 +5,8 @@ )] use std::path::Path; -pub(crate) use soroban_env_host::xdr; pub(crate) use soroban_rpc as rpc; +pub use stellar_xdr::curr as xdr; mod cli; pub use cli::main; diff --git a/cmd/soroban-cli/src/log.rs b/cmd/soroban-cli/src/log.rs index 28ed4041b..1a1c27035 100644 --- a/cmd/soroban-cli/src/log.rs +++ b/cmd/soroban-cli/src/log.rs @@ -1,17 +1,14 @@ use crate::xdr; + pub mod auth; -pub mod budget; pub mod cost; pub mod event; pub mod footprint; -pub mod host_event; pub use auth::*; -pub use budget::*; pub use cost::*; pub use event::*; pub use footprint::*; -pub use host_event::*; pub fn extract_events(tx_meta: &xdr::TransactionMeta) -> Vec { match tx_meta { diff --git a/cmd/soroban-cli/src/log/auth.rs b/cmd/soroban-cli/src/log/auth.rs index c37e7ed3e..4a6b4bea8 100644 --- a/cmd/soroban-cli/src/log/auth.rs +++ b/cmd/soroban-cli/src/log/auth.rs @@ -1,4 +1,4 @@ -use soroban_env_host::xdr::{SorobanAuthorizationEntry, VecM}; +use crate::xdr::{SorobanAuthorizationEntry, VecM}; pub fn auth(auth: &[VecM]) { if !auth.is_empty() { diff --git a/cmd/soroban-cli/src/log/budget.rs b/cmd/soroban-cli/src/log/budget.rs deleted file mode 100644 index 59ff4aad4..000000000 --- a/cmd/soroban-cli/src/log/budget.rs +++ /dev/null @@ -1,5 +0,0 @@ -use soroban_env_host::budget::Budget; - -pub fn budget(budget: &Budget) { - tracing::debug!("{budget:#?}"); -} diff --git a/cmd/soroban-cli/src/log/cost.rs b/cmd/soroban-cli/src/log/cost.rs index 3e049a6cd..8dfc18df6 100644 --- a/cmd/soroban-cli/src/log/cost.rs +++ b/cmd/soroban-cli/src/log/cost.rs @@ -1,4 +1,4 @@ -use soroban_env_host::xdr::SorobanResources; +use crate::xdr::SorobanResources; use std::fmt::{Debug, Display}; struct Cost<'a>(&'a SorobanResources); diff --git a/cmd/soroban-cli/src/log/footprint.rs b/cmd/soroban-cli/src/log/footprint.rs index bfbc9f7a3..7c351de1d 100644 --- a/cmd/soroban-cli/src/log/footprint.rs +++ b/cmd/soroban-cli/src/log/footprint.rs @@ -1,4 +1,4 @@ -use soroban_env_host::xdr::LedgerFootprint; +use crate::xdr::LedgerFootprint; pub fn footprint(footprint: &LedgerFootprint) { tracing::debug!("{footprint:#?}"); diff --git a/cmd/soroban-cli/src/log/host_event.rs b/cmd/soroban-cli/src/log/host_event.rs deleted file mode 100644 index 4238a74c3..000000000 --- a/cmd/soroban-cli/src/log/host_event.rs +++ /dev/null @@ -1,7 +0,0 @@ -use soroban_env_host::events::HostEvent; - -pub fn host_events(events: &[HostEvent]) { - for (i, event) in events.iter().enumerate() { - tracing::info!("{i}: {event:#?}"); - } -} diff --git a/cmd/soroban-cli/src/print.rs b/cmd/soroban-cli/src/print.rs index 5b98687bd..5b8ca2bd2 100644 --- a/cmd/soroban-cli/src/print.rs +++ b/cmd/soroban-cli/src/print.rs @@ -1,6 +1,6 @@ use std::{env, fmt::Display}; -use soroban_env_host::xdr::{Error as XdrError, Transaction}; +use crate::xdr::{Error as XdrError, Transaction}; use crate::{ config::network::Network, utils::explorer_url_for_transaction, utils::transaction_hash, diff --git a/cmd/soroban-cli/src/signer.rs b/cmd/soroban-cli/src/signer.rs index bf02fdb17..5bf22499c 100644 --- a/cmd/soroban-cli/src/signer.rs +++ b/cmd/soroban-cli/src/signer.rs @@ -1,7 +1,7 @@ use ed25519_dalek::ed25519::signature::Signer as _; use sha2::{Digest, Sha256}; -use soroban_env_host::xdr::{ +use crate::xdr::{ self, AccountId, DecoratedSignature, Hash, HashIdPreimage, HashIdPreimageSorobanAuthorization, InvokeHostFunctionOp, Limits, Operation, OperationBody, PublicKey, ScAddress, ScMap, ScSymbol, ScVal, Signature, SignatureHint, SorobanAddressCredentials, SorobanAuthorizationEntry, diff --git a/cmd/soroban-cli/src/tx/builder/transaction.rs b/cmd/soroban-cli/src/tx/builder/transaction.rs index 51232d5c5..7cd922679 100644 --- a/cmd/soroban-cli/src/tx/builder/transaction.rs +++ b/cmd/soroban-cli/src/tx/builder/transaction.rs @@ -28,7 +28,7 @@ impl TxExt for xdr::Transaction { source_account, fee, seq_num: seq_num.into(), - cond: soroban_env_host::xdr::Preconditions::None, + cond: crate::xdr::Preconditions::None, memo: Memo::None, operations: [operation].try_into().unwrap(), ext: TransactionExt::V0, diff --git a/cmd/soroban-cli/src/utils.rs b/cmd/soroban-cli/src/utils.rs index ee8bb1ece..0729edb27 100644 --- a/cmd/soroban-cli/src/utils.rs +++ b/cmd/soroban-cli/src/utils.rs @@ -2,7 +2,7 @@ use phf::phf_map; use sha2::{Digest, Sha256}; use stellar_strkey::ed25519::PrivateKey; -use soroban_env_host::xdr::{ +use crate::xdr::{ self, Asset, ContractIdPreimage, Hash, HashIdPreimage, HashIdPreimageContractId, Limits, ScMap, ScMapEntry, ScVal, Transaction, TransactionSignaturePayload, TransactionSignaturePayloadTaggedTransaction, WriteXdr, @@ -197,7 +197,7 @@ pub mod http { } pub mod rpc { - use soroban_env_host::xdr; + use crate::xdr; use soroban_rpc::{Client, Error}; use stellar_xdr::curr::{Hash, LedgerEntryData, LedgerKey, Limits, ReadXdr}; diff --git a/cmd/soroban-cli/src/wasm.rs b/cmd/soroban-cli/src/wasm.rs index 7ab2c243d..bc202a4b3 100644 --- a/cmd/soroban-cli/src/wasm.rs +++ b/cmd/soroban-cli/src/wasm.rs @@ -1,8 +1,8 @@ use crate::config::locator; use crate::config::network::Network; +use crate::xdr::{self, Hash, LedgerKey, LedgerKeyContractCode}; use clap::arg; use sha2::{Digest, Sha256}; -use soroban_env_host::xdr::{self, Hash, LedgerKey, LedgerKeyContractCode}; use soroban_rpc::Client; use soroban_spec_tools::contract::{self, Spec}; use std::{ diff --git a/scripts/check-dependencies.bash b/scripts/check-dependencies.bash deleted file mode 100755 index c82d2f2b1..000000000 --- a/scripts/check-dependencies.bash +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/bash - -set -e - -SED=sed -if [ -z "$(sed --version 2>&1 | grep GNU)" ]; then - SED=gsed -fi - -CURL="curl -sL --fail-with-body" -if ! CARGO_OUTPUT=$(cargo tree -p soroban-env-host 2>&1); then - echo "The project depends on multiple versions of the soroban-env-host Rust library, please unify them." - echo "Make sure the soroban-sdk dependency indirectly points to the same soroban-env-host dependency imported explicitly." - echo - echo "This is soroban-env-host version imported by soroban-sdk:" - cargo tree --depth 1 -p soroban-sdk | grep env-host - echo - echo - echo - echo "Full error:" - echo $CARGO_OUTPUT - exit 1 -fi - -# revision of the https://github.com/stellar/rs-stellar-xdr library used by the Rust code -RS_STELLAR_XDR_REVISION="" - -# revision of https://github.com/stellar/stellar-xdr/ used by the Rust code -STELLAR_XDR_REVISION_FROM_RUST="" - -function stellar_xdr_version_from_rust_dep_tree { - LINE=$(grep stellar-xdr | head -n 1) - # try to obtain a commit - COMMIT=$(echo $LINE | $SED -n 's/.*rev=\(.*\)#.*/\1/p') - if [ -n "$COMMIT" ]; then - echo "$COMMIT" - return - fi - # obtain a crate version - echo $LINE | $SED -n 's/.*stellar-xdr \(v\)\{0,1\}\([^ ]*\).*/\2/p' -} - -if CARGO_OUTPUT=$(cargo tree --depth 0 -p stellar-xdr 2>&1); then - RS_STELLAR_XDR_REVISION=$(echo "$CARGO_OUTPUT" | stellar_xdr_version_from_rust_dep_tree) - if [ ${#RS_STELLAR_XDR_REVISION} -eq 40 ]; then - # revision is a git hash - STELLAR_XDR_REVISION_FROM_RUST=$($CURL https://raw.githubusercontent.com/stellar/rs-stellar-xdr/${RS_STELLAR_XDR_REVISION}/xdr/curr-version) - else - # revision is a crate version - CARGO_SRC_BASE_DIR=$(realpath ${CARGO_HOME:-$HOME/.cargo}/registry/src/index*) - STELLAR_XDR_REVISION_FROM_RUST=$(cat "${CARGO_SRC_BASE_DIR}/stellar-xdr-${RS_STELLAR_XDR_REVISION}/xdr/curr-version") - fi -else - echo "The project depends on multiple versions of the Rust rs-stellar-xdr library" - echo "Make sure a single version of stellar-xdr is used" - echo - echo - echo - echo "Full error:" - echo $CARGO_OUTPUT -fi From 440b75d784bf7e095ebc65334625cd3561deeaac Mon Sep 17 00:00:00 2001 From: "Thomas M. DuBuisson" Date: Wed, 9 Oct 2024 13:51:48 -0700 Subject: [PATCH 03/30] Fix flake for nixpkgs on darwin (#1665) * Do not use SHELL (default shell) but $0 (current shell) * Cleanup shell hook --------- Co-authored-by: Gleb --- flake.nix | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/flake.nix b/flake.nix index 3b826ee77..1923d75bb 100644 --- a/flake.nix +++ b/flake.nix @@ -18,25 +18,18 @@ with pkgs; { devShells.default = mkShell { + nativeBuildInputs = lib.optionals (stdenv.isDarwin) [ + pkgs.darwin.apple_sdk.frameworks.SystemConfiguration + ]; buildInputs = [ openssl pkg-config - libudev-zero jq (rust-bin.stable.latest.default.override { extensions = [ "rust-src" ]; targets = [ "wasm32-unknown-unknown" ]; }) - ]; - shellHook = - '' - echo "Using `nix --version`" - alias stellar="cargo run --bin stellar --" - [ -f ./local.sh ] && source ./local.sh - shell=$0 - shell=`basename $SHELL` - source <(stellar completion --shell $shell) - ''; + ] ++ lib.optionals (stdenv.isLinux) [libudev-zero]; }; } ); From 09a63abd6e87accd5b874171138e8adfe2c9c8db Mon Sep 17 00:00:00 2001 From: Gleb Date: Wed, 9 Oct 2024 18:23:07 -0700 Subject: [PATCH 04/30] Add warning on no fund flag (#1637) --- FULL_HELP_DOCS.md | 3 +++ cmd/soroban-cli/src/commands/keys/generate.rs | 16 +++++++++++++++- cmd/soroban-cli/src/commands/keys/mod.rs | 5 +++-- cmd/soroban-cli/src/commands/mod.rs | 2 +- cookbook/contract-lifecycle.mdx | 2 +- cookbook/payments-and-assets.mdx | 4 ++-- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 2fd02cafb..5d83daeb2 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -977,6 +977,9 @@ Generate a new identity with a seed phrase, currently 12 words * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config +* `--fund` — Fund generated key pair + + Default value: `false` diff --git a/cmd/soroban-cli/src/commands/keys/generate.rs b/cmd/soroban-cli/src/commands/keys/generate.rs index 16e6a7fdb..b59e227fc 100644 --- a/cmd/soroban-cli/src/commands/keys/generate.rs +++ b/cmd/soroban-cli/src/commands/keys/generate.rs @@ -4,6 +4,7 @@ use super::super::config::{ locator, network, secret::{self, Secret}, }; +use crate::{commands::global, print::Print}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -17,6 +18,7 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] #[group(skip)] +#[allow(clippy::struct_excessive_bools)] pub struct Cmd { /// Name of identity pub name: String, @@ -46,10 +48,22 @@ pub struct Cmd { #[command(flatten)] pub network: network::Args, + + /// Fund generated key pair + #[arg(long, default_value = "false")] + pub fund: bool, } impl Cmd { - pub async fn run(&self) -> Result<(), Error> { + pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { + if !self.fund { + Print::new(global_args.quiet).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 { diff --git a/cmd/soroban-cli/src/commands/keys/mod.rs b/cmd/soroban-cli/src/commands/keys/mod.rs index 42814092f..30df5ccee 100644 --- a/cmd/soroban-cli/src/commands/keys/mod.rs +++ b/cmd/soroban-cli/src/commands/keys/mod.rs @@ -1,3 +1,4 @@ +use crate::commands::global; use clap::Parser; pub mod add; @@ -48,12 +49,12 @@ pub enum Error { } impl Cmd { - pub async fn run(&self) -> Result<(), Error> { + pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match self { Cmd::Add(cmd) => cmd.run()?, Cmd::Address(cmd) => cmd.run()?, Cmd::Fund(cmd) => cmd.run().await?, - Cmd::Generate(cmd) => cmd.run().await?, + Cmd::Generate(cmd) => cmd.run(global_args).await?, Cmd::Ls(cmd) => cmd.run()?, Cmd::Rm(cmd) => cmd.run()?, Cmd::Show(cmd) => cmd.run()?, diff --git a/cmd/soroban-cli/src/commands/mod.rs b/cmd/soroban-cli/src/commands/mod.rs index b2e431e6e..0a1d4629b 100644 --- a/cmd/soroban-cli/src/commands/mod.rs +++ b/cmd/soroban-cli/src/commands/mod.rs @@ -113,7 +113,7 @@ impl Root { Cmd::Network(network) => network.run(&self.global_args).await?, Cmd::Snapshot(snapshot) => snapshot.run(&self.global_args).await?, Cmd::Version(version) => version.run(), - Cmd::Keys(id) => id.run().await?, + Cmd::Keys(id) => id.run(&self.global_args).await?, Cmd::Tx(tx) => tx.run(&self.global_args).await?, Cmd::Cache(data) => data.run()?, }; diff --git a/cookbook/contract-lifecycle.mdx b/cookbook/contract-lifecycle.mdx index e38a233de..2be63c23f 100644 --- a/cookbook/contract-lifecycle.mdx +++ b/cookbook/contract-lifecycle.mdx @@ -9,7 +9,7 @@ To manage the lifecycle of a Stellar smart contract using the CLI, follow these 1. Create an identity for Alice: ```bash -stellar keys generate alice +stellar keys generate alice -q ``` 2. Fund the identity: diff --git a/cookbook/payments-and-assets.mdx b/cookbook/payments-and-assets.mdx index e3be8dafc..a198973e1 100644 --- a/cookbook/payments-and-assets.mdx +++ b/cookbook/payments-and-assets.mdx @@ -17,11 +17,11 @@ By setting the `STELLAR_NETWORK` environment variable, we will not have to set t 2. Fund the accounts: ```bash -stellar keys generate alice +stellar keys generate alice -q ``` ```bash -stellar keys generate bob +stellar keys generate bob -q ``` ```bash From e8aba2531ff2e59cd912a9759384e99a344cea34 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:55:02 +1000 Subject: [PATCH 05/30] Fix tests (#1666) --- .github/workflows/full-help-docs.yml | 47 ------------------- .github/workflows/rust.yml | 11 ++++- Cargo.lock | 6 +-- .../test-wasms/hello_world/src/lib.rs | 2 +- .../fixtures/test-wasms/token/Cargo.toml | 2 +- .../tests/it/integration/tx/operations.rs | 2 +- 6 files changed, 16 insertions(+), 54 deletions(-) delete mode 100644 .github/workflows/full-help-docs.yml diff --git a/.github/workflows/full-help-docs.yml b/.github/workflows/full-help-docs.yml deleted file mode 100644 index f564ae9ae..000000000 --- a/.github/workflows/full-help-docs.yml +++ /dev/null @@ -1,47 +0,0 @@ -name: CLI Help Doc - -on: - push: - branches: [main, release/**] - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref_protected == 'true' && github.sha || github.ref }} - cancel-in-progress: true - -permissions: - contents: read - # Optional: allow read access to pull request. Use with `only-new-issues` option. - pull-requests: read - -jobs: - complete: - if: always() - needs: [doc-check] - runs-on: ubuntu-latest - steps: - - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') - run: exit 1 - - doc-check: - runs-on: ubuntu-latest-16-cores - steps: - - uses: actions/checkout@v4 - - uses: stellar/actions/rust-cache@main - - run: rustup update - - name: Generate help doc - # this looks goofy to get GITHUB_OUTPUT to work with multi-line return values; - # see https://stackoverflow.com/a/74266196/249801 - run: | - make generate-full-help-doc - raw_diff=$(git diff FULL_HELP_DOCS.md) - if [ "$raw_diff" != "" ]; then echo ""; echo "Unexpected docs change:"; echo "======================="; echo ""; echo "$raw_diff"; echo ""; echo "======================="; echo ""; fi - echo diff=$raw_diff >> $GITHUB_OUTPUT - id: doc-gen - - - name: Check diff - if: steps.doc-gen.outputs.diff != '' - uses: actions/github-script@v7 - with: - script: | - core.setFailed('Expected `doc-gen` to generate no diffs, but got diff shown in previous step.\n\nUpdate the full help docs:\n\n cargo md-gen\n\nDo this automatically on every commit by installing the pre-commit hook as explained in the README.') diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index eb4e4c414..d7c49389b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,7 +17,7 @@ jobs: complete: if: always() - needs: [fmt, build-and-test, publish-dry-run] + needs: [fmt, 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') @@ -38,6 +38,15 @@ jobs: - name: Check no diffs exist run: git add -N . && git diff HEAD --exit-code + check-generated-full-help-docs: + runs-on: ubuntu-latest-16-cores + steps: + - uses: actions/checkout@v4 + - uses: stellar/actions/rust-cache@main + - run: rustup update + - run: make generate-full-help-doc + - run: git add -N . && git diff HEAD --exit-code + build-and-test: strategy: fail-fast: false diff --git a/Cargo.lock b/Cargo.lock index 33f0962d8..81e2e4c7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5794,11 +5794,11 @@ dependencies = [ [[package]] name = "soroban-token-sdk" -version = "22.0.0-rc.1.1" +version = "21.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7baa9e15d0838973cfa0aa0eee6e0fa062bec2e4a115c82396f452fa6148d731" +checksum = "0c6ede0da76646037f3ea5db9ccd37830865444bb24f137cb8f0af8282c784f5" dependencies = [ - "soroban-sdk 22.0.0-rc.1.1", + "soroban-sdk 21.7.2", ] [[package]] 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 b4b53c237..40006a1b7 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, ()); + let contract_id = env.register_contract(None, 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/token/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/token/Cargo.toml index 8875b87e7..03055f2b7 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 @@ -13,7 +13,7 @@ crate-type = ["cdylib"] [dependencies] soroban-sdk = { version = "=21.7.2" } -soroban-token-sdk = { workspace = true } +soroban-token-sdk = { version = "=21.7.2" } [dev-dependencies] soroban-sdk = { version = "=21.7.2", features = ["testutils"] } 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 9df808b34..0a0a103e8 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx/operations.rs @@ -1,8 +1,8 @@ use soroban_cli::{ tx::{builder, ONE_XLM}, utils::contract_id_hash_from_asset, + xdr::{self, ReadXdr, SequenceNumber}, }; -use soroban_sdk::xdr::{self, ReadXdr, SequenceNumber}; use soroban_test::{AssertExt, TestEnv}; use crate::integration::{ From 9880ad603765effecc1048da990b580a1b14623e Mon Sep 17 00:00:00 2001 From: Gleb Date: Thu, 10 Oct 2024 07:19:53 -0700 Subject: [PATCH 06/30] Add sim-only deprecation notice (#1634) * Add sim-only deprecation notice * Update display order * After-merge fixes --------- Co-authored-by: Willem Wyndham --- FULL_HELP_DOCS.md | 28 ++++++++++++++-------------- cmd/soroban-cli/src/fee.rs | 16 +++++++++++++--- cmd/soroban-cli/src/utils.rs | 18 ++++++++++++++++++ 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 5d83daeb2..3efb16dda 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -146,7 +146,7 @@ Deploy builtin Soroban Asset Contract * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout @@ -371,7 +371,7 @@ If no keys are specified the contract itself is extended. * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout @@ -399,7 +399,7 @@ Deploy a wasm contract * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `-i`, `--ignore-checks` — Whether to ignore safety checks when deploying contracts Default value: `false` @@ -675,7 +675,7 @@ Install a WASM file to the ledger without creating a contract instance * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--wasm ` — Path to wasm binary * `-i`, `--ignore-checks` — Whether to ignore safety checks when deploying contracts @@ -714,7 +714,7 @@ stellar contract invoke ... -- --help * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--send ` — Whether or not to send a transaction Default value: `default` @@ -826,7 +826,7 @@ If no keys are specificed the contract itself is restored. * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout @@ -1394,7 +1394,7 @@ Transfers the XLM balance of an account to another account and removes the sourc * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -1420,7 +1420,7 @@ Bumps forward the sequence number of the source account to the given sequence nu * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -1446,7 +1446,7 @@ Creates, updates, or deletes a trustline Learn more about trustlines https://dev * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -1475,7 +1475,7 @@ Creates and funds a new account with the specified starting balance * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -1504,7 +1504,7 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -1531,7 +1531,7 @@ Sends an amount in a specific asset to a destination account * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -1561,7 +1561,7 @@ Set option for an account such as flags, inflation destination, signers, home do * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config @@ -1602,7 +1602,7 @@ Allows issuing account to configure authorization and trustline flags to an asse * `--cost` — Output the cost execution to stderr * `--instructions ` — Number of instructions to simulate * `--build-only` — Build the transaction and only write the base64 xdr to stdout -* `--sim-only` — Simulate the transaction and only write the base64 xdr to stdout +* `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--rpc-url ` — RPC server endpoint * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--network ` — Name of network to use from config diff --git a/cmd/soroban-cli/src/fee.rs b/cmd/soroban-cli/src/fee.rs index f6afdc500..ea968870f 100644 --- a/cmd/soroban-cli/src/fee.rs +++ b/cmd/soroban-cli/src/fee.rs @@ -3,7 +3,11 @@ use clap::arg; use crate::assembled::Assembled; use crate::xdr; -use crate::commands::HEADING_RPC; +use crate::{commands::HEADING_RPC, deprecated_arg}; + +const DEPRECATION_MESSAGE: &str = "--sim-only is deprecated and will be removed \ +in the future versions of CLI. The same functionality is offered by `tx simulate` command. To \ +replicate the behaviour, run `stellar --build only | stellar tx simulate`"; #[derive(Debug, clap::Args, Clone)] #[group(skip)] @@ -20,8 +24,14 @@ pub struct Args { /// Build the transaction and only write the base64 xdr to stdout #[arg(long, help_heading = HEADING_RPC)] pub build_only: bool, - /// Simulate the transaction and only write the base64 xdr to stdout - #[arg(long, help_heading = HEADING_RPC, conflicts_with = "build_only")] + /// (Deprecated) simulate the transaction and only write the base64 xdr to stdout + #[arg( + long, + help_heading = HEADING_RPC, + conflicts_with = "build_only", + display_order = 100, + value_parser = deprecated_arg!(bool, DEPRECATION_MESSAGE)) + ] pub sim_only: bool, } diff --git a/cmd/soroban-cli/src/utils.rs b/cmd/soroban-cli/src/utils.rs index 0729edb27..b52a7b5fe 100644 --- a/cmd/soroban-cli/src/utils.rs +++ b/cmd/soroban-cli/src/utils.rs @@ -196,6 +196,24 @@ pub mod http { } } +pub mod args { + /// Mark argument as deprecated with warning to be printed when it's used. + #[macro_export] + macro_rules! deprecated_arg { + (bool, $message: expr) => { + <_ as clap::builder::TypedValueParser>::map( + clap::builder::BoolValueParser::new(), + |x| { + if (x) { + $crate::print::Print::new(false).warnln($message); + } + x + }, + ) + }; + } +} + pub mod rpc { use crate::xdr; use soroban_rpc::{Client, Error}; From 18fd1ff2b4d120e93a506278e7888c625fe13cbf Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Thu, 10 Oct 2024 11:07:47 -0700 Subject: [PATCH 07/30] Add support for contract id alias and key name to `stellar snapshot create`. (#1662) --- FULL_HELP_DOCS.md | 6 +- .../src/commands/snapshot/create.rs | 61 ++++++++++++++++--- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 3efb16dda..d0e7cd9dd 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -1249,18 +1249,20 @@ Create a ledger snapshot using a history archive. Filters (address, wasm-hash) specify what ledger entries to include. -Account addresses include the account, and trust lines. +Account addresses include the account, and trustlines. Contract addresses include the related wasm, contract data. If a contract is a Stellar asset contract, it includes the asset issuer's account and trust lines, but does not include all the trust lines of other accounts holding the asset. To include them specify the addresses of relevant accounts. +Any invalid contract id passed as `--address` will be ignored. + **Usage:** `stellar snapshot create [OPTIONS] --output ` ###### **Options:** * `--ledger ` — The ledger sequence number to snapshot. Defaults to latest history archived ledger -* `--address
` — Account or contract address to include in the snapshot +* `--address
` — Account or contract address/alias to include in the snapshot * `--wasm-hash ` — WASM hashes to include in the snapshot * `--output ` — Format of the out file diff --git a/cmd/soroban-cli/src/commands/snapshot/create.rs b/cmd/soroban-cli/src/commands/snapshot/create.rs index 13bef9465..6ce48d3f2 100644 --- a/cmd/soroban-cli/src/commands/snapshot/create.rs +++ b/cmd/soroban-cli/src/commands/snapshot/create.rs @@ -27,7 +27,6 @@ use tokio::io::BufReader; use tokio_util::io::StreamReader; use url::Url; -use crate::utils::http; use crate::{ commands::{config::data, global, HEADING_RPC}, config::{self, locator, network::passphrase}, @@ -35,6 +34,7 @@ use crate::{ tx::builder, utils::get_name_from_stellar_asset_contract_storage, }; +use crate::{config::address::Address, utils::http}; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, ValueEnum)] pub enum Output { @@ -55,7 +55,7 @@ fn default_out_path() -> PathBuf { /// /// Filters (address, wasm-hash) specify what ledger entries to include. /// -/// Account addresses include the account, and trust lines. +/// Account addresses include the account, and trustlines. /// /// Contract addresses include the related wasm, contract data. /// @@ -63,6 +63,9 @@ fn default_out_path() -> PathBuf { /// account and trust lines, but does not include all the trust lines of other /// accounts holding the asset. To include them specify the addresses of /// relevant accounts. +/// +/// Any invalid contract id passed as `--address` will be ignored. +/// #[derive(Parser, Debug, Clone)] #[group(skip)] #[command(arg_required_else_help = true)] @@ -70,9 +73,9 @@ pub struct Cmd { /// The ledger sequence number to snapshot. Defaults to latest history archived ledger. #[arg(long)] ledger: Option, - /// Account or contract address to include in the snapshot. + /// Account or contract address/alias to include in the snapshot. #[arg(long = "address", help_heading = "Filter Options")] - address: Vec, + address: Vec, /// WASM hashes to include in the snapshot. #[arg(long = "wasm-hash", help_heading = "Filter Options")] wasm_hashes: Vec, @@ -213,11 +216,13 @@ impl Cmd { } // Search the buckets using the user inputs as the starting inputs. - let (account_ids, contract_ids): (HashSet, HashSet) = - self.address.iter().cloned().partition_map(|a| match a { - ScAddress::Account(account_id) => Either::Left(account_id), - ScAddress::Contract(_) => Either::Right(a), - }); + let (account_ids, contract_ids): (HashSet, HashSet) = self + .address + .iter() + .cloned() + .filter_map(|a| self.resolve_address(&a, network_passphrase)) + .partition_map(|a| a); + let mut current = SearchInputs { account_ids, contract_ids, @@ -388,6 +393,44 @@ impl Cmd { }) .ok_or(Error::ArchiveUrlNotConfigured) } + + fn resolve_address( + &self, + address: &str, + network_passphrase: &str, + ) -> Option> { + self.resolve_contract(address, network_passphrase) + .map(Either::Right) + .or_else(|| self.resolve_account(address).map(Either::Left)) + } + + // 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()?; + + Some(AccountId(xdr::PublicKey::PublicKeyTypeEd25519( + match address.resolve_muxed_account(&self.locator, None).ok()? { + xdr::MuxedAccount::Ed25519(uint256) => uint256, + xdr::MuxedAccount::MuxedEd25519(xdr::MuxedAccountMed25519 { ed25519, .. }) => { + ed25519 + } + }, + ))) + } + // Resolve a contract address to a contract id. The contract can be a + // C-address or a contract alias. + fn resolve_contract(&self, address: &str, network_passphrase: &str) -> Option { + address.parse().ok().or_else(|| { + Some(ScAddress::Contract( + self.locator + .resolve_contract_id(address, network_passphrase) + .ok()? + .0 + .into(), + )) + }) + } } async fn get_history( From a1ee9449428d2fae6938089cdf1a68bca84f66ca Mon Sep 17 00:00:00 2001 From: Gleb Date: Thu, 10 Oct 2024 11:49:02 -0700 Subject: [PATCH 08/30] Contract init: add flag removal message (#1628) * contract init: add removal memo * Rename macro to removed_arg * Refactoring * Clippy * Remove gix from dependencies * revert Cargo.lock * minimal updates to lock file * Address comments --------- Co-authored-by: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> --- Cargo.lock | 899 +----------------- FULL_HELP_DOCS.md | 7 - cmd/soroban-cli/Cargo.toml | 4 - cmd/soroban-cli/src/commands/contract/init.rs | 674 +------------ cmd/soroban-cli/src/utils.rs | 19 + 5 files changed, 64 insertions(+), 1539 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81e2e4c7a..71ca2b35f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,12 +117,6 @@ dependencies = [ "derive_arbitrary", ] -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - [[package]] name = "ark-bls12-381" version = "0.4.0" @@ -727,15 +721,6 @@ dependencies = [ "serde", ] -[[package]] -name = "btoi" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd6407f73a9b8b6162d8a2ef999fe6afd7cc15902ebf42c5cd296addf17e0ad" -dependencies = [ - "num-traits", -] - [[package]] name = "bumpalo" version = "3.16.0" @@ -893,12 +878,6 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" -[[package]] -name = "clru" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd0f76e066e64fdc5631e3bb46381254deab9ef1158292f27c8c57e3bf3fe59" - [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1399,12 +1378,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "dyn-clone" version = "1.0.17" @@ -1613,12 +1586,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "faster-hex" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" - [[package]] name = "fastrand" version = "1.9.0" @@ -1650,18 +1617,6 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[package]] -name = "filetime" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", -] - [[package]] name = "fixedbitset" version = "0.4.2" @@ -1876,760 +1831,6 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" -[[package]] -name = "gix" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31887c304d9a935f3e5494fb5d6a0106c34e965168ec0db9b457424eedd0c741" -dependencies = [ - "gix-actor", - "gix-attributes", - "gix-command", - "gix-commitgraph", - "gix-config", - "gix-credentials", - "gix-date", - "gix-diff", - "gix-discover", - "gix-features", - "gix-filter", - "gix-fs", - "gix-glob", - "gix-hash", - "gix-hashtable", - "gix-ignore", - "gix-index", - "gix-lock", - "gix-macros", - "gix-negotiate", - "gix-object", - "gix-odb", - "gix-pack", - "gix-path", - "gix-pathspec", - "gix-prompt", - "gix-protocol", - "gix-ref", - "gix-refspec", - "gix-revision", - "gix-revwalk", - "gix-sec", - "gix-submodule", - "gix-tempfile", - "gix-trace", - "gix-transport", - "gix-traverse", - "gix-url", - "gix-utils", - "gix-validate", - "gix-worktree", - "gix-worktree-state", - "once_cell", - "parking_lot", - "reqwest 0.11.27", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-actor" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7bb9fad6125c81372987c06469601d37e1a2d421511adb69971b9083517a8a" -dependencies = [ - "bstr", - "btoi", - "gix-date", - "itoa", - "thiserror", - "winnow 0.5.40", -] - -[[package]] -name = "gix-attributes" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37ce99c7e81288c28b703641b6d5d119aacc45c1a6b247156e6249afa486257" -dependencies = [ - "bstr", - "gix-glob", - "gix-path", - "gix-quote", - "gix-trace", - "kstring", - "smallvec", - "thiserror", - "unicode-bom", -] - -[[package]] -name = "gix-bitmap" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a371db66cbd4e13f0ed9dc4c0fea712d7276805fccc877f77e96374d317e87ae" -dependencies = [ - "thiserror", -] - -[[package]] -name = "gix-chunk" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c8751169961ba7640b513c3b24af61aa962c967aaf04116734975cd5af0c52" -dependencies = [ - "thiserror", -] - -[[package]] -name = "gix-command" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d76867867da891cbe32021ad454e8cae90242f6afb06762e4dd0d357afd1d7b" -dependencies = [ - "bstr", - "gix-path", - "gix-trace", - "shell-words", -] - -[[package]] -name = "gix-commitgraph" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "133b06f67f565836ec0c473e2116a60fb74f80b6435e21d88013ac0e3c60fc78" -dependencies = [ - "bstr", - "gix-chunk", - "gix-features", - "gix-hash", - "memmap2", - "thiserror", -] - -[[package]] -name = "gix-config" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e62bf2073b6ce3921ffa6d8326f645f30eec5fc4a8e8a4bc0fcb721a2f3f69dc" -dependencies = [ - "bstr", - "gix-config-value", - "gix-features", - "gix-glob", - "gix-path", - "gix-ref", - "gix-sec", - "memchr", - "once_cell", - "smallvec", - "thiserror", - "unicode-bom", - "winnow 0.5.40", -] - -[[package]] -name = "gix-config-value" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b328997d74dd15dc71b2773b162cb4af9a25c424105e4876e6d0686ab41c383e" -dependencies = [ - "bitflags 2.6.0", - "bstr", - "gix-path", - "libc", - "thiserror", -] - -[[package]] -name = "gix-credentials" -version = "0.24.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198588f532e4d1202e04e6c3f50e4d7c060dffc66801c6f53cc246f1d234739e" -dependencies = [ - "bstr", - "gix-command", - "gix-config-value", - "gix-path", - "gix-prompt", - "gix-sec", - "gix-trace", - "gix-url", - "thiserror", -] - -[[package]] -name = "gix-date" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eed6931f21491ee0aeb922751bd7ec97b4b2fe8fbfedcb678e2a2dce5f3b8c0" -dependencies = [ - "bstr", - "itoa", - "thiserror", - "time", -] - -[[package]] -name = "gix-diff" -version = "0.40.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdcb5e49c4b9729dd1c361040ae5c3cd7c497b2260b18c954f62db3a63e98cf" -dependencies = [ - "bstr", - "gix-hash", - "gix-object", - "thiserror", -] - -[[package]] -name = "gix-discover" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4669218f3ec0cbbf8f16857b32200890f8ca585f36f5817242e4115fe4551af" -dependencies = [ - "bstr", - "dunce", - "gix-fs", - "gix-hash", - "gix-path", - "gix-ref", - "gix-sec", - "thiserror", -] - -[[package]] -name = "gix-features" -version = "0.38.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac7045ac9fe5f9c727f38799d002a7ed3583cd777e3322a7c4b43e3cf437dc69" -dependencies = [ - "bytes", - "crc32fast", - "flate2", - "gix-hash", - "gix-trace", - "gix-utils", - "libc", - "once_cell", - "prodash", - "sha1_smol", - "thiserror", - "walkdir", -] - -[[package]] -name = "gix-filter" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9240862840fb740d209422937195e129e4ed3da49af212383260134bea8f6c1a" -dependencies = [ - "bstr", - "encoding_rs", - "gix-attributes", - "gix-command", - "gix-hash", - "gix-object", - "gix-packetline-blocking", - "gix-path", - "gix-quote", - "gix-trace", - "gix-utils", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-fs" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2184c40e7910529677831c8b481acf788ffd92427ed21fad65b6aa637e631b8" -dependencies = [ - "gix-features", - "gix-utils", -] - -[[package]] -name = "gix-glob" -version = "0.16.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7df15afa265cc8abe92813cd354d522f1ac06b29ec6dfa163ad320575cb447" -dependencies = [ - "bitflags 2.6.0", - "bstr", - "gix-features", - "gix-path", -] - -[[package]] -name = "gix-hash" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93d7df7366121b5018f947a04d37f034717e113dcf9ccd85c34b58e57a74d5e" -dependencies = [ - "faster-hex", - "thiserror", -] - -[[package]] -name = "gix-hashtable" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242" -dependencies = [ - "gix-hash", - "hashbrown 0.14.5", - "parking_lot", -] - -[[package]] -name = "gix-ignore" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6afb8f98e314d4e1adc822449389ada863c174b5707cedd327d67b84dba527" -dependencies = [ - "bstr", - "gix-glob", - "gix-path", - "gix-trace", - "unicode-bom", -] - -[[package]] -name = "gix-index" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7152181ba8f0a3addc5075dd612cea31fc3e252b29c8be8c45f4892bf87426" -dependencies = [ - "bitflags 2.6.0", - "bstr", - "btoi", - "filetime", - "gix-bitmap", - "gix-features", - "gix-fs", - "gix-hash", - "gix-lock", - "gix-object", - "gix-traverse", - "itoa", - "libc", - "memmap2", - "rustix 0.38.34", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-lock" -version = "13.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c359f81f01b8352063319bcb39789b7ea0887b406406381106e38c4a34d049" -dependencies = [ - "gix-tempfile", - "gix-utils", - "thiserror", -] - -[[package]] -name = "gix-macros" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "999ce923619f88194171a67fb3e6d613653b8d4d6078b529b15a765da0edcc17" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] - -[[package]] -name = "gix-negotiate" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a163adb84149e522e991cbe27250a6e01de56f98cd05b174614ce3f8a4e8b140" -dependencies = [ - "bitflags 2.6.0", - "gix-commitgraph", - "gix-date", - "gix-hash", - "gix-object", - "gix-revwalk", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-object" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693ce9d30741506cb082ef2d8b797415b48e032cce0ab23eff894c19a7e4777b" -dependencies = [ - "bstr", - "btoi", - "gix-actor", - "gix-date", - "gix-features", - "gix-hash", - "gix-validate", - "itoa", - "smallvec", - "thiserror", - "winnow 0.5.40", -] - -[[package]] -name = "gix-odb" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba2fa9e81f2461b78b4d81a807867667326c84cdab48e0aed7b73a593aa1be4" -dependencies = [ - "arc-swap", - "gix-date", - "gix-features", - "gix-fs", - "gix-hash", - "gix-object", - "gix-pack", - "gix-path", - "gix-quote", - "parking_lot", - "tempfile", - "thiserror", -] - -[[package]] -name = "gix-pack" -version = "0.47.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da5f3e78c96b76c4e6fe5e8e06b76221e4a0ee9a255aa935ed1fdf68988dfd8" -dependencies = [ - "clru", - "gix-chunk", - "gix-features", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-path", - "gix-tempfile", - "memmap2", - "parking_lot", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-packetline" -version = "0.17.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b70486beda0903b6d5b65dfa6e40585098cdf4e6365ca2dff4f74c387354a515" -dependencies = [ - "bstr", - "faster-hex", - "gix-trace", - "thiserror", -] - -[[package]] -name = "gix-packetline-blocking" -version = "0.17.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31d42378a3d284732e4d589979930d0d253360eccf7ec7a80332e5ccb77e14a" -dependencies = [ - "bstr", - "faster-hex", - "gix-trace", - "thiserror", -] - -[[package]] -name = "gix-path" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d23d5bbda31344d8abc8de7c075b3cf26e5873feba7c4a15d916bce67382bd9" -dependencies = [ - "bstr", - "gix-trace", - "home", - "once_cell", - "thiserror", -] - -[[package]] -name = "gix-pathspec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cbd49750edb26b0a691e5246fc635fa554d344da825cd20fa9ee0da9c1b761f" -dependencies = [ - "bitflags 2.6.0", - "bstr", - "gix-attributes", - "gix-config-value", - "gix-glob", - "gix-path", - "thiserror", -] - -[[package]] -name = "gix-prompt" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e0595d2be4b6d6a71a099e989bdd610882b882da35fb8503d91d6f81aa0936f" -dependencies = [ - "gix-command", - "gix-config-value", - "parking_lot", - "rustix 0.38.34", - "thiserror", -] - -[[package]] -name = "gix-protocol" -version = "0.44.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a905cd00946ed8ed6f4f2281f98a889c5b3d38361cd94b8d5a5771d25ab33b99" -dependencies = [ - "bstr", - "gix-credentials", - "gix-date", - "gix-features", - "gix-hash", - "gix-transport", - "gix-utils", - "maybe-async", - "thiserror", - "winnow 0.6.18", -] - -[[package]] -name = "gix-quote" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbff4f9b9ea3fa7a25a70ee62f545143abef624ac6aa5884344e70c8b0a1d9ff" -dependencies = [ - "bstr", - "gix-utils", - "thiserror", -] - -[[package]] -name = "gix-ref" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5818958994ad7879fa566f5441ebcc48f0926aa027b28948e6fbf6578894dc31" -dependencies = [ - "gix-actor", - "gix-date", - "gix-features", - "gix-fs", - "gix-hash", - "gix-lock", - "gix-object", - "gix-path", - "gix-tempfile", - "gix-utils", - "gix-validate", - "memmap2", - "thiserror", - "winnow 0.5.40", -] - -[[package]] -name = "gix-refspec" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613aa4d93034c5791d13bdc635e530f4ddab1412ddfb4a8215f76213177b61c7" -dependencies = [ - "bstr", - "gix-hash", - "gix-revision", - "gix-validate", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-revision" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288f6549d7666db74dc3f169a9a333694fc28ecd2f5aa7b2c979c89eb556751a" -dependencies = [ - "bstr", - "gix-date", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-revwalk", - "gix-trace", - "thiserror", -] - -[[package]] -name = "gix-revwalk" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9b4d91dfc5c14fee61a28c65113ded720403b65a0f46169c0460f731a5d03c" -dependencies = [ - "gix-commitgraph", - "gix-date", - "gix-hash", - "gix-hashtable", - "gix-object", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-sec" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1547d26fa5693a7f34f05b4a3b59a90890972922172653bcb891ab3f09f436df" -dependencies = [ - "bitflags 2.6.0", - "gix-path", - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "gix-submodule" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73182f6c1f5ed1ed94ba16581ac62593d5e29cd1c028b2af618f836283b8f8d4" -dependencies = [ - "bstr", - "gix-config", - "gix-path", - "gix-pathspec", - "gix-refspec", - "gix-url", - "thiserror", -] - -[[package]] -name = "gix-tempfile" -version = "13.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a761d76594f4443b675e85928e4902dec333273836bd386906f01e7e346a0d11" -dependencies = [ - "gix-fs", - "libc", - "once_cell", - "parking_lot", - "tempfile", -] - -[[package]] -name = "gix-trace" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e" - -[[package]] -name = "gix-transport" -version = "0.41.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8e5f72ec9cad9ee44714b9a4ec7427b540a2418b62111f5e3a715bebe1ed9d" -dependencies = [ - "base64 0.21.7", - "bstr", - "gix-command", - "gix-credentials", - "gix-features", - "gix-packetline", - "gix-quote", - "gix-sec", - "gix-url", - "reqwest 0.11.27", - "thiserror", -] - -[[package]] -name = "gix-traverse" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc30c5b5e4e838683b59e1b0574ce6bc1c35916df9709aaab32bb7751daf08b" -dependencies = [ - "gix-commitgraph", - "gix-date", - "gix-hash", - "gix-hashtable", - "gix-object", - "gix-revwalk", - "smallvec", - "thiserror", -] - -[[package]] -name = "gix-url" -version = "0.27.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2eb9b35bba92ea8f0b5ab406fad3cf6b87f7929aa677ff10aa042c6da621156" -dependencies = [ - "bstr", - "gix-features", - "gix-path", - "home", - "thiserror", - "url", -] - -[[package]] -name = "gix-utils" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35192df7fd0fa112263bad8021e2df7167df4cc2a6e6d15892e1e55621d3d4dc" -dependencies = [ - "fastrand 2.1.0", - "unicode-normalization", -] - -[[package]] -name = "gix-validate" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c27dd34a49b1addf193c92070bcbf3beaf6e10f16a78544de6372e146a0acf" -dependencies = [ - "bstr", - "thiserror", -] - -[[package]] -name = "gix-worktree" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca36bb3dc54038c66507dc75c4d8edbee2d6d5cc45227b4eb508ad13dd60a006" -dependencies = [ - "bstr", - "gix-attributes", - "gix-features", - "gix-fs", - "gix-glob", - "gix-hash", - "gix-ignore", - "gix-index", - "gix-object", - "gix-path", -] - -[[package]] -name = "gix-worktree-state" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae178614b70bdb0c7f6f21b8c9fb711ab78bd7e8e1866f565fcf28876747f1d" -dependencies = [ - "bstr", - "gix-features", - "gix-filter", - "gix-fs", - "gix-glob", - "gix-hash", - "gix-index", - "gix-object", - "gix-path", - "gix-worktree", - "io-close", - "thiserror", -] - [[package]] name = "glob" version = "0.3.1" @@ -3102,7 +2303,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.0", "tower-service", - "webpki-roots 0.26.3", + "webpki-roots", ] [[package]] @@ -3275,16 +2476,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "io-close" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "io-lifetimes" version = "1.0.11" @@ -3455,15 +2646,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "kstring" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" -dependencies = [ - "static_assertions", -] - [[package]] name = "kv-log-macro" version = "1.0.7" @@ -3645,32 +2827,12 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "maybe-async" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.77", -] - [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memmap2" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" -dependencies = [ - "libc", -] - [[package]] name = "mime" version = "0.3.17" @@ -3820,15 +2982,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - [[package]] name = "object" version = "0.32.2" @@ -3953,7 +3106,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.3", + "redox_syscall", "smallvec", "windows-targets 0.52.6", ] @@ -4267,12 +3420,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prodash" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" - [[package]] name = "quick-error" version = "1.2.3" @@ -4372,15 +3519,6 @@ dependencies = [ "getrandom", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.3" @@ -4460,7 +3598,6 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", - "hyper-rustls 0.24.2", "hyper-tls", "ipnet", "js-sys", @@ -4470,7 +3607,6 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.12", "rustls-pemfile 1.0.4", "serde", "serde_json", @@ -4479,13 +3615,11 @@ dependencies = [ "system-configuration", "tokio", "tokio-native-tls", - "tokio-rustls 0.24.1", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.25.4", "winreg", ] @@ -4534,7 +3668,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.26.3", + "webpki-roots", "windows-registry", ] @@ -5104,12 +4238,6 @@ dependencies = [ "syn 2.0.77", ] -[[package]] -name = "sha1_smol" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" - [[package]] name = "sha2" version = "0.9.9" @@ -5153,12 +4281,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shell-words" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" - [[package]] name = "shlex" version = "1.3.0" @@ -5332,7 +4454,6 @@ dependencies = [ "fqdn", "futures", "futures-util", - "gix", "glob", "heck 0.5.0", "hex", @@ -6354,9 +5475,7 @@ checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", - "libc", "num-conv", - "num_threads", "powerfmt", "serde", "time-core", @@ -6704,12 +5823,6 @@ version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" -[[package]] -name = "unicode-bom" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" - [[package]] name = "unicode-ident" version = "1.0.12" @@ -7039,12 +6152,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.25.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" - [[package]] name = "webpki-roots" version = "0.26.3" diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index d0e7cd9dd..5d7816538 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -617,13 +617,6 @@ Initialize a Soroban project with an example contract ###### **Options:** -* `-w`, `--with-example ` — An optional flag to specify Soroban example contracts to include. A hello-world contract will be included by default. - - Possible values: `account`, `alloc`, `atomic_multiswap`, `atomic_swap`, `auth`, `cross_contract`, `custom_types`, `deep_contract_auth`, `deployer`, `errors`, `eth_abi`, `events`, `fuzzing`, `increment`, `liquidity_pool`, `logging`, `mint-lock`, `other_custom_types`, `simple_account`, `single_offer`, `timelock`, `token`, `ttl`, `upgradeable_contract`, `workspace` - -* `--frontend-template ` — An optional flag to pass in a url for a frontend template repository. - - Default value: `` * `--overwrite` — Overwrite all existing files. diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index da142ad57..0cc12e74f 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -106,10 +106,6 @@ directories = { workspace = true } ulid = { workspace = true, features = ["serde"] } strum = "0.17.1" strum_macros = "0.17.1" -gix = { version = "0.58.0", default-features = false, features = [ - "blocking-http-transport-reqwest-rust-tls", - "worktree-mutation", -] } async-compression = { version = "0.4.12", features = ["tokio", "gzip"] } tempfile = "3.8.1" diff --git a/cmd/soroban-cli/src/commands/contract/init.rs b/cmd/soroban-cli/src/commands/contract/init.rs index fd4cf483a..48eb837ad 100644 --- a/cmd/soroban-cli/src/commands/contract/init.rs +++ b/cmd/soroban-cli/src/commands/contract/init.rs @@ -1,85 +1,69 @@ -use clap::{ - builder::{PossibleValue, PossibleValuesParser, ValueParser}, - Parser, -}; -use gix::{clone, create, open, progress, remote}; -use rust_embed::RustEmbed; -use serde_json::{from_str, json, to_string_pretty, Error as JsonError, Value as JsonValue}; use std::{ - env, - ffi::OsStr, - fs::{ - copy, create_dir_all, metadata, read_dir, read_to_string, write, File, Metadata, - OpenOptions, - }, - io::{self, Read, Write}, - num::NonZeroU32, + fs::{create_dir_all, metadata, write, Metadata}, + io, path::{Path, PathBuf}, str, - sync::atomic::AtomicBool, }; -use toml_edit::{Document, TomlError}; -use crate::utils::http; -use crate::{commands::global, print}; +use clap::Parser; +use rust_embed::RustEmbed; -const SOROBAN_EXAMPLES_URL: &str = "https://github.com/stellar/soroban-examples.git"; -const GITHUB_URL: &str = "https://github.com"; -const WITH_EXAMPLE_LONG_HELP_TEXT: &str = - "An optional flag to specify Soroban example contracts to include. A hello-world contract will be included by default."; +use crate::{commands::global, error_on_use_of_removed_arg, print, utils}; + +const EXAMPLE_REMOVAL_NOTICE: &str = "Adding examples via cli is no longer supported. \ +You can still clone examples from the repo https://github.com/stellar/soroban-examples"; +const FRONTEND_EXAMPLE_REMOVAL_NOTICE: &str = "Using frontend template via cli is no longer \ +supported. You can search for frontend templates using github tags, \ +such as `soroban-template` or `soroban-frontend-template`"; #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { pub project_path: String, - #[arg(short, long, num_args = 1.., value_parser=possible_example_values(), long_help=WITH_EXAMPLE_LONG_HELP_TEXT)] - pub with_example: Vec, + // TODO: remove in future version (23+) https://github.com/stellar/stellar-cli/issues/1586 + #[arg( + short, + long, + hide = true, + display_order = 100, + value_parser = error_on_use_of_removed_arg!(String, EXAMPLE_REMOVAL_NOTICE) + )] + pub with_example: Option, + // TODO: remove in future version (23+) https://github.com/stellar/stellar-cli/issues/1586 #[arg( long, - default_value = "", - long_help = "An optional flag to pass in a url for a frontend template repository." + hide = true, + display_order = 100, + value_parser = error_on_use_of_removed_arg!(String, FRONTEND_EXAMPLE_REMOVAL_NOTICE), )] - pub frontend_template: String, + pub frontend_template: Option, #[arg(long, long_help = "Overwrite all existing files.")] pub overwrite: bool, } -fn possible_example_values() -> ValueParser { - let example_contracts = include_str!("../../../example_contracts.list") - .lines() - .collect::>(); - let parser = PossibleValuesParser::new(example_contracts.iter().map(PossibleValue::new)); - parser.into() -} - #[derive(thiserror::Error, Debug)] pub enum Error { #[error("{0}: {1}")] Io(String, io::Error), - #[error("io error:")] - StdIo(#[from] io::Error), - - #[error("{0}: {1}")] - Json(String, JsonError), - - #[error("failed to parse toml file: {0}")] - TomlParse(#[from] TomlError), + #[error(transparent)] + Std(#[from] std::io::Error), #[error("failed to convert bytes to string: {0}")] ConvertBytesToString(#[from] str::Utf8Error), - #[error("preparing fetch repository: {0}")] - PrepareFetch(Box), + #[error("contract package already exists: {0}")] + AlreadyExists(String), - #[error("failed to fetch repository: {0}")] - Fetch(Box), + #[error("provided project path exists and is not a directory")] + PathExistsNotDir, - #[error("failed to checkout main worktree: {0}")] - Checkout(#[from] clone::checkout::main_worktree::Error), + #[error("provided project path exists and is not a cargo workspace root directory. Hint: run init on an empty or non-existing directory" + )] + PathExistsNotCargoProject, } impl Cmd { @@ -97,6 +81,7 @@ impl Cmd { #[derive(RustEmbed)] #[folder = "src/utils/contract-init-template"] struct TemplateFiles; + struct Runner { args: Cmd, print: print::Print, @@ -112,40 +97,6 @@ impl Runner { Self::create_dir_all(&project_path)?; self.copy_template_files()?; - if !Self::check_internet_connection() { - self.print.warnln("It doesn't look like you're connected to the internet. We're still able to initialize a new project, but additional examples and the frontend template will not be included."); - return Ok(()); - } - - if !self.args.frontend_template.is_empty() { - // create a temp dir for the template repo - let fe_template_dir = tempfile::tempdir() - .map_err(|e| Error::Io("creating temp dir for frontend template".to_string(), e))?; - - // clone the template repo into the temp dir - Self::clone_repo(&self.args.frontend_template, fe_template_dir.path())?; - - // copy the frontend template files into the project - self.copy_frontend_files(fe_template_dir.path(), &project_path)?; - } - - // if there are --with-example flags, include the example contracts - if self.include_example_contracts() { - // create an examples temp dir - let examples_dir = tempfile::tempdir() - .map_err(|e| Error::Io("creating temp dir for soroban-examples".to_string(), e))?; - - // clone the soroban-examples repo into the temp dir - Self::clone_repo(SOROBAN_EXAMPLES_URL, examples_dir.path())?; - - // copy the example contracts into the project - self.copy_example_contracts( - examples_dir.path(), - &project_path, - &self.args.with_example, - )?; - } - Ok(()) } @@ -169,7 +120,7 @@ impl Runner { }; let file_contents = - std::str::from_utf8(file.data.as_ref()).map_err(Error::ConvertBytesToString)?; + str::from_utf8(file.data.as_ref()).map_err(Error::ConvertBytesToString)?; // We need to include the Cargo.toml file as Cargo.toml.removeextension in the template so that it will be included the package. This is making sure that the Cargo file is written as Cargo.toml in the new project. This is a workaround for this issue: https://github.com/rust-lang/cargo/issues/8597. let item_path = Path::new(item.as_ref()); @@ -186,69 +137,8 @@ impl Runner { } Self::write(&to, file_contents)?; } - Ok(()) - } - - fn copy_contents(&self, from: &Path, to: &Path) -> Result<(), Error> { - let contents_to_exclude_from_copy = [ - ".git", - ".github", - "Makefile", - ".vscode", - "target", - "Cargo.lock", - ]; - for entry in - read_dir(from).map_err(|e| Error::Io(format!("reading directory: {from:?}"), e))? - { - let entry = - entry.map_err(|e| Error::Io(format!("reading entry in directory {from:?}",), e))?; - let path = entry.path(); - let entry_name = entry.file_name().to_string_lossy().to_string(); - let new_path = to.join(&entry_name); - - if contents_to_exclude_from_copy.contains(&entry_name.as_str()) { - continue; - } - if path.is_dir() { - Self::create_dir_all(&new_path)?; - self.copy_contents(&path, &new_path)?; - } else { - let exists = Self::file_exists(&new_path); - let new_path_str = new_path.to_string_lossy(); - if exists { - let append = - new_path_str.contains(".gitignore") || new_path_str.contains("README.md"); - if append { - self.append_contents(&path, &new_path)?; - } - - if self.args.overwrite && !append { - self.print.plusln(format!( - "Writing {new_path_str} (overwriting existing file)" - )); - } else { - self.print.infoln(format!( - "Skipped creating {new_path_str} as it already exists" - )); - continue; - } - } else { - self.print.plus(format!("Writing {new_path_str}")); - } - copy(&path, &new_path).map_err(|e| { - Error::Io( - format!( - "copying from {:?} to {:?}", - path.to_string_lossy(), - new_path - ), - e, - ) - })?; - } - } + Self::create_dir_all(project_path.join("contracts").as_path())?; Ok(()) } @@ -260,172 +150,6 @@ impl Runner { .unwrap_or(false) } - fn check_internet_connection() -> bool { - if let Ok(_req) = http::blocking_client().get(GITHUB_URL).send() { - return true; - } - - false - } - - fn include_example_contracts(&self) -> bool { - !self.args.with_example.is_empty() - } - - fn clone_repo(from_url: &str, to_path: &Path) -> Result<(), Error> { - let mut prepare = clone::PrepareFetch::new( - from_url, - to_path, - create::Kind::WithWorktree, - create::Options { - destination_must_be_empty: false, - fs_capabilities: None, - }, - open::Options::isolated(), - ) - .map_err(|e| Error::PrepareFetch(Box::new(e)))? - .with_shallow(remote::fetch::Shallow::DepthAtRemote( - NonZeroU32::new(1).unwrap(), - )); - - let (mut checkout, _outcome) = prepare - .fetch_then_checkout(progress::Discard, &AtomicBool::new(false)) - .map_err(|e| Error::Fetch(Box::new(e)))?; - let (_repo, _outcome) = checkout - .main_worktree(progress::Discard, &AtomicBool::new(false)) - .map_err(Error::Checkout)?; - - Ok(()) - } - - fn copy_example_contracts( - &self, - from: &Path, - to: &Path, - contracts: &[String], - ) -> Result<(), Error> { - let project_contracts_path = to.join("contracts"); - for contract in contracts { - self.print - .infoln(format!("Initializing example contract: {contract}")); - let contract_as_string = contract.to_string(); - let contract_path = Path::new(&contract_as_string); - let from_contract_path = from.join(contract_path); - let to_contract_path = project_contracts_path.join(contract_path); - Self::create_dir_all(&to_contract_path)?; - - self.copy_contents(&from_contract_path, &to_contract_path)?; - Self::edit_contract_cargo_file(&to_contract_path)?; - } - - Ok(()) - } - - fn edit_contract_cargo_file(contract_path: &Path) -> Result<(), Error> { - let cargo_path = contract_path.join("Cargo.toml"); - - let cargo_toml_str = Self::read_to_string(&cargo_path)?; - let cargo_toml_str = regex::Regex::new(r#"soroban-sdk = "[^\"]+""#) - .unwrap() - .replace_all( - cargo_toml_str.as_str(), - "soroban-sdk = { workspace = true }", - ); - - let cargo_toml_str = regex::Regex::new(r#"soroban-sdk = \{(.*) version = "[^"]+"(.+)}"#) - .unwrap() - .replace_all(&cargo_toml_str, "soroban-sdk = {$1 workspace = true$2}"); - - let mut doc = cargo_toml_str - .parse::() - .map_err(Error::TomlParse)?; - doc.remove("profile"); - - Self::write(&cargo_path, &doc.to_string())?; - - Ok(()) - } - - fn copy_frontend_files(&self, from: &Path, to: &Path) -> Result<(), Error> { - self.print.infoln("Initializing with frontend template"); - self.copy_contents(from, to)?; - Self::edit_package_json_files(to) - } - - fn edit_package_json_files(project_path: &Path) -> Result<(), Error> { - let package_name = if let Some(name) = project_path.file_name() { - name.to_owned() - } else { - let current_dir = env::current_dir() - .map_err(|e| Error::Io("getting current dir from env".to_string(), e))?; - let file_name = current_dir - .file_name() - .unwrap_or(OsStr::new("soroban-astro-template")) - .to_os_string(); - file_name - }; - - Self::edit_package_name(project_path, &package_name, "package.json")?; - Self::edit_package_name(project_path, &package_name, "package-lock.json") - } - - fn edit_package_name( - project_path: &Path, - package_name: &OsStr, - file_name: &str, - ) -> Result<(), Error> { - let file_path = project_path.join(file_name); - let file_contents = Self::read_to_string(&file_path)?; - - let mut doc: JsonValue = from_str(&file_contents).map_err(|e| { - Error::Json(format!("parsing {file_name} file in: {project_path:?}"), e) - })?; - - doc["name"] = json!(package_name.to_string_lossy()); - - let formatted_json = to_string_pretty(&doc) - .map_err(|e| Error::Json("calling to_string_pretty for package.json".to_string(), e))?; - - Self::write(&file_path, &formatted_json)?; - - Ok(()) - } - - // Appends the contents of a file to another file, separated by a delimiter - fn append_contents(&self, from: &Path, to: &Path) -> Result<(), Error> { - let mut from_file = File::open(from)?; - let mut from_content = String::new(); - from_file.read_to_string(&mut from_content)?; - - let mut to_file = OpenOptions::new().read(true).append(true).open(to)?; - let mut to_content = String::new(); - to_file.read_to_string(&mut to_content)?; - - let delimiter = Self::get_merged_file_delimiter(to); - // if the to file already contains the delimiter, we don't need to append the contents again - if to_content.contains(&delimiter) { - return Ok(()); - } - - to_file.write_all(delimiter.as_bytes())?; - to_file.write_all(from_content.as_bytes())?; - - self.print.infoln(format!("Merging {to:?} contents")); - Ok(()) - } - - fn get_merged_file_delimiter(file_path: &Path) -> String { - let comment = if file_path.to_string_lossy().contains("README.md") { - "---\n".to_string() - } else if file_path.to_string_lossy().contains("gitignore") { - "# The following is from the Frontend Template's .gitignore".to_string() - } else { - String::new() - }; - - format!("\n\n{comment}\n\n").to_string() - } - fn create_dir_all(path: &Path) -> Result<(), Error> { create_dir_all(path).map_err(|e| Error::Io(format!("creating directory: {path:?}"), e)) } @@ -433,22 +157,14 @@ impl Runner { fn write(path: &Path, contents: &str) -> Result<(), Error> { write(path, contents).map_err(|e| Error::Io(format!("writing file: {path:?}"), e)) } - - fn read_to_string(path: &Path) -> Result { - read_to_string(path).map_err(|e| Error::Io(format!("reading file: {path:?}"), e)) - } } #[cfg(test)] mod tests { + use std::fs; + use std::fs::read_to_string; + use itertools::Itertools; - use std::{ - collections::HashMap, - fs::{self, read_to_string}, - path::PathBuf, - time::SystemTime, - }; - use walkdir::WalkDir; use super::*; @@ -461,8 +177,8 @@ mod tests { let runner = Runner { args: Cmd { project_path: project_dir.to_string_lossy().to_string(), - with_example: vec![], - frontend_template: String::new(), + with_example: None, + frontend_template: None, overwrite: false, }, print: print::Print::new(false), @@ -480,258 +196,6 @@ mod tests { temp_dir.close().unwrap(); } - #[test] - fn test_init_including_example_contract() { - let temp_dir = tempfile::tempdir().unwrap(); - let project_dir = temp_dir.path().join(TEST_PROJECT_NAME); - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: ["alloc".to_owned()].to_vec(), - frontend_template: String::new(), - overwrite: false, - }, - print: print::Print::new(false), - }; - runner.run().unwrap(); - - assert_base_template_files_exist(&project_dir); - assert_default_hello_world_contract_files_exist(&project_dir); - assert_excluded_paths_do_not_exist(&project_dir); - - // check that alloc contract files exist - assert_contract_files_exist(&project_dir, "alloc"); - - // check that expected files are excluded from the alloc contract dir - assert_example_contract_excluded_files_do_not_exist(&project_dir, "alloc"); - - // check that the alloc contract's Cargo.toml file uses the workspace for dependencies - assert_contract_cargo_file_is_well_formed(&project_dir, "alloc"); - - temp_dir.close().unwrap(); - } - - #[test] - fn test_init_including_multiple_example_contracts() { - let temp_dir = tempfile::tempdir().unwrap(); - let project_dir = temp_dir.path().join("project"); - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: ["account".to_owned(), "atomic_swap".to_owned()].to_vec(), - frontend_template: String::new(), - overwrite: false, - }, - print: print::Print::new(false), - }; - runner.run().unwrap(); - - assert_base_template_files_exist(&project_dir); - assert_default_hello_world_contract_files_exist(&project_dir); - assert_excluded_paths_do_not_exist(&project_dir); - - // check that account contract files exist and that expected files are excluded - assert_contract_files_exist(&project_dir, "account"); - assert_example_contract_excluded_files_do_not_exist(&project_dir, "account"); - assert_contract_cargo_file_is_well_formed(&project_dir, "account"); - - // check that atomic_swap contract files exist and that expected files are excluded - assert_contract_files_exist(&project_dir, "atomic_swap"); - assert_example_contract_excluded_files_do_not_exist(&project_dir, "atomic_swap"); - assert_contract_cargo_file_is_well_formed(&project_dir, "atomic_swap"); - - temp_dir.close().unwrap(); - } - - #[test] - fn test_init_with_invalid_example_contract() { - let temp_dir = tempfile::tempdir().unwrap(); - let project_dir = temp_dir.path().join("project"); - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: ["invalid_example".to_owned(), "atomic_swap".to_owned()].to_vec(), - frontend_template: String::new(), - overwrite: false, - }, - print: print::Print::new(false), - }; - assert!(runner.run().is_err()); - - temp_dir.close().unwrap(); - } - - #[test] - fn test_init_with_frontend_template() { - let temp_dir = tempfile::tempdir().unwrap(); - let project_dir = temp_dir.path().join(TEST_PROJECT_NAME); - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: vec![], - frontend_template: "https://github.com/stellar/soroban-astro-template".to_owned(), - overwrite: false, - }, - print: print::Print::new(false), - }; - runner.run().unwrap(); - - assert_base_template_files_exist(&project_dir); - assert_default_hello_world_contract_files_exist(&project_dir); - assert_excluded_paths_do_not_exist(&project_dir); - - // check that the contract's Cargo.toml file uses the workspace for dependencies - assert_contract_cargo_file_is_well_formed(&project_dir, "hello_world"); - assert_excluded_paths_do_not_exist(&project_dir); - - assert_astro_files_exist(&project_dir); - assert_gitignore_includes_astro_paths(&project_dir); - assert_package_json_files_have_correct_name(&project_dir, TEST_PROJECT_NAME); - assert_readme_includes_frontend_readme_appended(&project_dir); - - temp_dir.close().unwrap(); - } - - #[test] - fn test_init_with_overwrite() { - let temp_dir = tempfile::tempdir().unwrap(); - let project_dir = temp_dir.path().join(TEST_PROJECT_NAME); - - // First initialization - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: vec![], - frontend_template: "https://github.com/stellar/soroban-astro-template".to_owned(), - overwrite: false, - }, - print: print::Print::new(false), - }; - runner.run().unwrap(); - - // Get initial modification times - let initial_mod_times = get_mod_times(&project_dir); - - // Second initialization with overwrite - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: vec![], - frontend_template: "https://github.com/stellar/soroban-astro-template".to_owned(), - overwrite: true, - }, - print: print::Print::new(false), - }; - runner.run().unwrap(); - - // Get new modification times - let new_mod_times = get_mod_times(&project_dir); - - // Compare modification times - for (path, initial_time) in initial_mod_times { - let new_time = new_mod_times.get(&path).expect("File should still exist"); - assert!( - new_time > &initial_time, - "File {} should have a later modification time", - path.display() - ); - } - - temp_dir.close().unwrap(); - } - - fn get_mod_times(dir: &Path) -> HashMap { - let mut mod_times = HashMap::new(); - for entry in WalkDir::new(dir) { - let entry = entry.unwrap(); - if entry.file_type().is_file() { - let path = entry.path().to_owned(); - let metadata = fs::metadata(&path).unwrap(); - mod_times.insert(path, metadata.modified().unwrap()); - } - } - mod_times - } - - #[test] - fn test_init_from_within_an_existing_project() { - let temp_dir = tempfile::tempdir().unwrap(); - let project_dir = temp_dir.path().join("./"); - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: vec![], - frontend_template: "https://github.com/stellar/soroban-astro-template".to_owned(), - overwrite: false, - }, - print: print::Print::new(false), - }; - runner.run().unwrap(); - - assert_base_template_files_exist(&project_dir); - assert_default_hello_world_contract_files_exist(&project_dir); - assert_excluded_paths_do_not_exist(&project_dir); - - // check that the contract's Cargo.toml file uses the workspace for dependencies - assert_contract_cargo_file_is_well_formed(&project_dir, "hello_world"); - assert_excluded_paths_do_not_exist(&project_dir); - - assert_astro_files_exist(&project_dir); - assert_gitignore_includes_astro_paths(&project_dir); - assert_package_json_files_have_correct_name( - &project_dir, - &project_dir.file_name().unwrap().to_string_lossy(), - ); - - temp_dir.close().unwrap(); - } - - #[test] - fn test_init_does_not_duplicate_frontend_readme_contents_when_run_more_than_once() { - let temp_dir = tempfile::tempdir().unwrap(); - let project_dir = temp_dir.path().join(TEST_PROJECT_NAME); - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: vec![], - frontend_template: "https://github.com/stellar/soroban-astro-template".to_owned(), - overwrite: false, - }, - print: print::Print::new(false), - }; - runner.run().unwrap(); - - // call init again to make sure the README.md's contents are not duplicated - let runner = Runner { - args: Cmd { - project_path: project_dir.to_string_lossy().to_string(), - with_example: vec![], - frontend_template: "https://github.com/stellar/soroban-astro-template".to_owned(), - overwrite: false, - }, - print: print::Print::new(false), - }; - runner.run().unwrap(); - - assert_base_template_files_exist(&project_dir); - assert_default_hello_world_contract_files_exist(&project_dir); - assert_excluded_paths_do_not_exist(&project_dir); - - // check that the contract's Cargo.toml file uses the workspace for dependencies - assert_contract_cargo_file_is_well_formed(&project_dir, "hello_world"); - assert_excluded_paths_do_not_exist(&project_dir); - - assert_astro_files_exist(&project_dir); - assert_gitignore_includes_astro_paths(&project_dir); - assert_package_json_files_have_correct_name( - &project_dir, - &project_dir.file_name().unwrap().to_string_lossy(), - ); - assert_readme_includes_frontend_readme_appended(&project_dir); - - temp_dir.close().unwrap(); - } - // test helpers fn assert_base_template_files_exist(project_dir: &Path) { let expected_paths = ["contracts", "Cargo.toml", "README.md"]; @@ -813,14 +277,6 @@ mod tests { ); } - fn assert_example_contract_excluded_files_do_not_exist( - project_dir: &Path, - contract_name: &str, - ) { - let contract_dir = project_dir.join("contracts").join(contract_name); - assert!(!contract_dir.as_path().join("Makefile").exists()); - } - fn assert_excluded_paths_do_not_exist(project_dir: &Path) { let base_excluded_paths = [".git", ".github", "Makefile", ".vscode", "target"]; for path in &base_excluded_paths { @@ -838,50 +294,4 @@ mod tests { assert!(!filepath.exists(), "{filepath:?} should not exist"); }); } - - fn assert_gitignore_includes_astro_paths(project_dir: &Path) { - let gitignore_path = project_dir.join(".gitignore"); - let gitignore_str = read_to_string(gitignore_path).unwrap(); - assert!(gitignore_str.contains(".astro/")); - assert!(gitignore_str.contains("node_modules")); - assert!(gitignore_str.contains("npm-debug.log*")); - } - - fn assert_astro_files_exist(project_dir: &Path) { - assert!(project_dir.join("public").exists()); - assert!(project_dir.join("src").exists()); - assert!(project_dir.join("src").join("components").exists()); - assert!(project_dir.join("src").join("layouts").exists()); - assert!(project_dir.join("src").join("pages").exists()); - assert!(project_dir.join("astro.config.mjs").exists()); - assert!(project_dir.join("tsconfig.json").exists()); - } - - fn assert_package_json_files_have_correct_name( - project_dir: &Path, - expected_package_name: &str, - ) { - let package_json_path = project_dir.join("package.json"); - let package_json_str = read_to_string(package_json_path).unwrap(); - assert!(package_json_str.contains(&format!("\"name\": \"{expected_package_name}\""))); - - let package_lock_json_path = project_dir.join("package-lock.json"); - let package_lock_json_str = read_to_string(package_lock_json_path).unwrap(); - assert!(package_lock_json_str.contains(&format!("\"name\": \"{expected_package_name}\""))); - } - - fn assert_readme_includes_frontend_readme_appended(project_dir: &Path) { - let readme_path = project_dir.join("README.md"); - let readme_str = read_to_string(readme_path).unwrap(); - assert!(readme_str.contains("Soroban Frontend in Astro")); - let expected = "The following is the Frontend Template's README.md"; - assert!(readme_str.contains(expected)); - - let readme_path = project_dir.join("README.md"); - let readme_str = read_to_string(readme_path).unwrap(); - let readme_frontend_merge_delimiter = "The following is the Frontend Template's README.md"; - let count = readme_str.matches(readme_frontend_merge_delimiter).count(); - // making sure it is in there just once so that it isn't duplicated if `contract init` is run again - assert!(count == 1); - } } diff --git a/cmd/soroban-cli/src/utils.rs b/cmd/soroban-cli/src/utils.rs index b52a7b5fe..6e87d15a6 100644 --- a/cmd/soroban-cli/src/utils.rs +++ b/cmd/soroban-cli/src/utils.rs @@ -197,6 +197,25 @@ pub mod http { } pub mod args { + #[derive(thiserror::Error, Debug)] + pub enum DeprecatedError<'a> { + #[error("This argument has been removed and will be not be recognized by the future versions of CLI: {0}" + )] + RemovedArgument(&'a str), + } + + #[macro_export] + /// Mark argument as removed with an error to be printed when it's used. + macro_rules! error_on_use_of_removed_arg { + ($_type:ident, $message: expr) => { + |a: &str| { + Err::<$_type, utils::args::DeprecatedError>( + utils::args::DeprecatedError::RemovedArgument($message), + ) + } + }; + } + /// Mark argument as deprecated with warning to be printed when it's used. #[macro_export] macro_rules! deprecated_arg { From 8f8d2ac1734b56dc385c3fc281a0f9a5aa4a0f74 Mon Sep 17 00:00:00 2001 From: Gleb Date: Thu, 10 Oct 2024 18:20:36 -0700 Subject: [PATCH 09/30] Remove example_contracts.list (#1667) --- .github/workflows/rust.yml | 8 -------- Makefile | 5 ----- cmd/soroban-cli/example_contracts.list | 25 ------------------------- 3 files changed, 38 deletions(-) delete mode 100644 cmd/soroban-cli/example_contracts.list diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d7c49389b..048015009 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -30,14 +30,6 @@ jobs: - run: rustup update - run: cargo fmt --all --check - check-generated-examples-list: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: make generate-examples-list - - name: Check no diffs exist - run: git add -N . && git diff HEAD --exit-code - check-generated-full-help-docs: runs-on: ubuntu-latest-16-cores steps: diff --git a/Makefile b/Makefile index 6d55aacc4..4db0946ce 100644 --- a/Makefile +++ b/Makefile @@ -46,11 +46,6 @@ build-test: build-test-wasms install generate-full-help-doc: cargo run --bin doc-gen --features clap-markdown -generate-examples-list: - curl -sSL https://api.github.com/repos/stellar/soroban-examples/git/trees/main \ - | jq -r '.tree[] | select(.type != "blob" and .path != "hello_world" and (.path | startswith(".") | not)) | .path' \ - > cmd/soroban-cli/example_contracts.list - test: build-test cargo test diff --git a/cmd/soroban-cli/example_contracts.list b/cmd/soroban-cli/example_contracts.list deleted file mode 100644 index 2ad5f2c6e..000000000 --- a/cmd/soroban-cli/example_contracts.list +++ /dev/null @@ -1,25 +0,0 @@ -account -alloc -atomic_multiswap -atomic_swap -auth -cross_contract -custom_types -deep_contract_auth -deployer -errors -eth_abi -events -fuzzing -increment -liquidity_pool -logging -mint-lock -other_custom_types -simple_account -single_offer -timelock -token -ttl -upgradeable_contract -workspace From a041c68b86030f171526d8fa086268a72fbd845f Mon Sep 17 00:00:00 2001 From: Gleb Date: Fri, 11 Oct 2024 00:43:31 -0700 Subject: [PATCH 10/30] Update contract init (#1625) * contract init: add removal memo * Rework contract init * Update impl * Improve messages --- FULL_HELP_DOCS.md | 9 +- cmd/crates/soroban-test/tests/it/init.rs | 63 ++++++++++- cmd/soroban-cli/src/commands/contract/init.rs | 106 +++++++++++++----- cmd/soroban-cli/src/commands/contract/mod.rs | 7 +- .../Cargo.toml.removeextension | 2 +- .../src/utils/contract-template/Makefile | 16 +++ .../src/lib.rs | 0 .../src/test.rs | 0 .../.gitignore | 0 .../Cargo.toml.removeextension | 0 .../README.md | 0 11 files changed, 172 insertions(+), 31 deletions(-) rename cmd/soroban-cli/src/utils/{contract-init-template/contracts/hello_world => contract-template}/Cargo.toml.removeextension (89%) create mode 100644 cmd/soroban-cli/src/utils/contract-template/Makefile rename cmd/soroban-cli/src/utils/{contract-init-template/contracts/hello_world => contract-template}/src/lib.rs (100%) rename cmd/soroban-cli/src/utils/{contract-init-template/contracts/hello_world => contract-template}/src/test.rs (100%) rename cmd/soroban-cli/src/utils/{contract-init-template => contract-workspace-template}/.gitignore (100%) rename cmd/soroban-cli/src/utils/{contract-init-template => contract-workspace-template}/Cargo.toml.removeextension (100%) rename cmd/soroban-cli/src/utils/{contract-init-template => contract-workspace-template}/README.md (100%) diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 5d7816538..c52636226 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -84,7 +84,7 @@ Tools for smart contract developers * `fetch` — Fetch a contract's Wasm binary * `id` — Generate the contract id for a given contract or asset * `info` — Access info about contracts -* `init` — Initialize a Soroban project with an example contract +* `init` — Initialize a Soroban contract project * `inspect` — (Deprecated in favor of `contract info` subcommands) Inspect a WASM file listing contract functions, meta, etc * `install` — Install a WASM file to the ledger without creating a contract instance * `invoke` — Invoke a contract function @@ -607,7 +607,9 @@ Outputs no data when no data is present in the contract. ## `stellar contract init` -Initialize a Soroban project with an example contract +Initialize a Soroban contract project. + +This command will create a Cargo workspace project and add a sample Stellar contract. The name of the contract can be specified by `--name`. It can be run multiple times with different names in order to generate multiple contracts, and files won't be overwritten unless `--overwrite` is passed. **Usage:** `stellar contract init [OPTIONS] ` @@ -617,6 +619,9 @@ Initialize a Soroban project with an example contract ###### **Options:** +* `--name ` — An optional flag to specify a new contract's name. + + Default value: `hello-world` * `--overwrite` — Overwrite all existing files. diff --git a/cmd/crates/soroban-test/tests/it/init.rs b/cmd/crates/soroban-test/tests/it/init.rs index 6eada4ce6..c3cc9b694 100644 --- a/cmd/crates/soroban-test/tests/it/init.rs +++ b/cmd/crates/soroban-test/tests/it/init.rs @@ -1,6 +1,6 @@ use assert_fs::prelude::*; use predicates::prelude::predicate; -use soroban_test::TestEnv; +use soroban_test::{AssertExt, TestEnv}; #[test] fn init() { @@ -24,3 +24,64 @@ fn init() { == Some(&format!("{major}.0.0")) })); } + +#[test] +fn init_and_deploy() { + let name = "hello_world"; + let sandbox = TestEnv::default(); + + sandbox + .new_assert_cmd("contract") + .arg("init") + .arg("--name") + .arg(name) + .arg("project") + .assert() + .success(); + + let manifest_path = sandbox + .dir() + .join(format!("project/contracts/{name}/Cargo.toml")); + assert!(manifest_path.exists()); + + sandbox + .new_assert_cmd("contract") + .arg("build") + .arg("--manifest-path") + .arg(manifest_path) + .assert() + .success(); + + let target_dir = sandbox + .dir() + .join("project/target/wasm32-unknown-unknown/release"); + assert!(target_dir.exists()); + + let assert = sandbox + .new_assert_cmd("contract") + .arg("deploy") + .arg("--wasm") + .arg(target_dir.join(format!("{name}.wasm"))) + .assert(); + + let contract = assert.stdout_as_str(); + + assert.success(); + + let assert = sandbox + .new_assert_cmd("contract") + .arg("invoke") + .arg("--id") + .arg(contract) + .arg("--") + .arg("hello") + .arg("--to") + .arg("bar") + .assert(); + + let output = assert.stdout_as_str(); + + assert_eq!(output, r#"["Hello","bar"]"#); + + assert.success(); +} diff --git a/cmd/soroban-cli/src/commands/contract/init.rs b/cmd/soroban-cli/src/commands/contract/init.rs index 48eb837ad..96f28c64e 100644 --- a/cmd/soroban-cli/src/commands/contract/init.rs +++ b/cmd/soroban-cli/src/commands/contract/init.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::{ fs::{create_dir_all, metadata, write, Metadata}, io, @@ -21,12 +22,19 @@ such as `soroban-template` or `soroban-frontend-template`"; pub struct Cmd { pub project_path: String, + #[arg( + long, + default_value = "hello-world", + long_help = "An optional flag to specify a new contract's name." + )] + pub name: String, + // TODO: remove in future version (23+) https://github.com/stellar/stellar-cli/issues/1586 #[arg( short, long, hide = true, - display_order = 100, + display_order = 100, value_parser = error_on_use_of_removed_arg!(String, EXAMPLE_REMOVAL_NOTICE) )] pub with_example: Option, @@ -79,8 +87,12 @@ impl Cmd { } #[derive(RustEmbed)] -#[folder = "src/utils/contract-init-template"] -struct TemplateFiles; +#[folder = "src/utils/contract-workspace-template"] +struct WorkspaceTemplateFiles; + +#[derive(RustEmbed)] +#[folder = "src/utils/contract-template"] +struct ContractTemplateFiles; struct Runner { args: Cmd, @@ -91,19 +103,49 @@ impl Runner { fn run(&self) -> Result<(), Error> { let project_path = PathBuf::from(&self.args.project_path); self.print - .infoln(format!("Initializing project at {project_path:?}")); + .infoln(format!("Initializing workspace at {project_path:?}")); // create a project dir, and copy the contents of the base template (contract-init-template) into it Self::create_dir_all(&project_path)?; - self.copy_template_files()?; + self.copy_template_files( + project_path.as_path(), + &mut WorkspaceTemplateFiles::iter(), + WorkspaceTemplateFiles::get, + )?; + + let contract_path = project_path.join("contracts").join(&self.args.name); + self.print + .infoln(format!("Initializing contract at {contract_path:?}")); + + Self::create_dir_all(contract_path.as_path())?; + self.copy_template_files( + contract_path.as_path(), + &mut ContractTemplateFiles::iter(), + ContractTemplateFiles::get, + )?; Ok(()) } - fn copy_template_files(&self) -> Result<(), Error> { - let project_path = Path::new(&self.args.project_path); - for item in TemplateFiles::iter() { - let mut to = project_path.join(item.as_ref()); + fn copy_template_files( + &self, + root_path: &Path, + files: &mut dyn Iterator>, + getter: fn(&str) -> Option, + ) -> Result<(), Error> { + for item in &mut *files { + let mut to = root_path.join(item.as_ref()); + // We need to include the Cargo.toml file as Cargo.toml.removeextension in the template + // so that it will be included the package. This is making sure that the Cargo file is + // written as Cargo.toml in the new project. This is a workaround for this issue: + // https://github.com/rust-lang/cargo/issues/8597. + let item_path = Path::new(item.as_ref()); + let is_toml = item_path.file_name().unwrap() == "Cargo.toml.removeextension"; + if is_toml { + let item_parent_path = item_path.parent().unwrap(); + to = root_path.join(item_parent_path).join("Cargo.toml"); + } + let exists = Self::file_exists(&to); if exists && !self.args.overwrite { self.print @@ -113,20 +155,19 @@ impl Runner { Self::create_dir_all(to.parent().unwrap())?; - let Some(file) = TemplateFiles::get(item.as_ref()) else { + let Some(file) = getter(item.as_ref()) else { self.print .warnln(format!("Failed to read file: {}", item.as_ref())); continue; }; - let file_contents = - str::from_utf8(file.data.as_ref()).map_err(Error::ConvertBytesToString)?; + let mut file_contents = str::from_utf8(file.data.as_ref()) + .map_err(Error::ConvertBytesToString)? + .to_string(); - // We need to include the Cargo.toml file as Cargo.toml.removeextension in the template so that it will be included the package. This is making sure that the Cargo file is written as Cargo.toml in the new project. This is a workaround for this issue: https://github.com/rust-lang/cargo/issues/8597. - let item_path = Path::new(item.as_ref()); - if item_path.file_name().unwrap() == "Cargo.toml.removeextension" { - let item_parent_path = item_path.parent().unwrap(); - to = project_path.join(item_parent_path).join("Cargo.toml"); + if is_toml { + let new_content = file_contents.replace("%contract-template%", &self.args.name); + file_contents = new_content; } if exists { @@ -135,11 +176,9 @@ impl Runner { } else { self.print.plusln(format!("Writing {to:?}")); } - Self::write(&to, file_contents)?; + Self::write(&to, &file_contents)?; } - Self::create_dir_all(project_path.join("contracts").as_path())?; - Ok(()) } @@ -177,6 +216,7 @@ mod tests { let runner = Runner { args: Cmd { project_path: project_dir.to_string_lossy().to_string(), + name: "hello_world".to_string(), with_example: None, frontend_template: None, overwrite: false, @@ -186,11 +226,29 @@ mod tests { runner.run().unwrap(); assert_base_template_files_exist(&project_dir); - assert_default_hello_world_contract_files_exist(&project_dir); + + assert_contract_files_exist(&project_dir, "hello_world"); assert_excluded_paths_do_not_exist(&project_dir); assert_contract_cargo_file_is_well_formed(&project_dir, "hello_world"); + assert_excluded_paths_do_not_exist(&project_dir); + let runner = Runner { + args: Cmd { + project_path: project_dir.to_string_lossy().to_string(), + name: "contract2".to_string(), + with_example: None, + frontend_template: None, + overwrite: false, + }, + print: print::Print::new(false), + }; + runner.run().unwrap(); + + assert_contract_files_exist(&project_dir, "contract2"); + assert_excluded_paths_do_not_exist(&project_dir); + + assert_contract_cargo_file_is_well_formed(&project_dir, "contract2"); assert_excluded_paths_do_not_exist(&project_dir); temp_dir.close().unwrap(); @@ -204,10 +262,6 @@ mod tests { } } - fn assert_default_hello_world_contract_files_exist(project_dir: &Path) { - assert_contract_files_exist(project_dir, "hello_world"); - } - fn assert_contract_files_exist(project_dir: &Path, contract_name: &str) { let contract_dir = project_dir.join("contracts").join(contract_name); @@ -283,7 +337,7 @@ mod tests { let filepath = project_dir.join(path); assert!(!filepath.exists(), "{filepath:?} should not exist"); } - let contract_excluded_paths = ["Makefile", "target", "Cargo.lock"]; + let contract_excluded_paths = ["target", "Cargo.lock"]; let contract_dirs = fs::read_dir(project_dir.join("contracts")) .unwrap() .map(|entry| entry.unwrap().path()); diff --git a/cmd/soroban-cli/src/commands/contract/mod.rs b/cmd/soroban-cli/src/commands/contract/mod.rs index 4f3c6f7f4..d0524e82b 100644 --- a/cmd/soroban-cli/src/commands/contract/mod.rs +++ b/cmd/soroban-cli/src/commands/contract/mod.rs @@ -53,7 +53,12 @@ pub enum Cmd { #[command(subcommand)] Info(info::Cmd), - /// Initialize a Soroban project with an example contract + /// Initialize a Soroban contract project. + /// + /// This command will create a Cargo workspace project and add a sample Stellar contract. + /// The name of the contract can be specified by `--name`. It can be run multiple times + /// with different names in order to generate multiple contracts, and files won't + /// be overwritten unless `--overwrite` is passed. Init(init::Cmd), /// (Deprecated in favor of `contract info` subcommands) Inspect a WASM file listing contract functions, meta, etc diff --git a/cmd/soroban-cli/src/utils/contract-init-template/contracts/hello_world/Cargo.toml.removeextension b/cmd/soroban-cli/src/utils/contract-template/Cargo.toml.removeextension similarity index 89% rename from cmd/soroban-cli/src/utils/contract-init-template/contracts/hello_world/Cargo.toml.removeextension rename to cmd/soroban-cli/src/utils/contract-template/Cargo.toml.removeextension index 2d8b3ac4e..8da1aed87 100644 --- a/cmd/soroban-cli/src/utils/contract-init-template/contracts/hello_world/Cargo.toml.removeextension +++ b/cmd/soroban-cli/src/utils/contract-template/Cargo.toml.removeextension @@ -1,5 +1,5 @@ [package] -name = "hello-world" +name = "%contract-template%" version = "0.0.0" edition = "2021" publish = false diff --git a/cmd/soroban-cli/src/utils/contract-template/Makefile b/cmd/soroban-cli/src/utils/contract-template/Makefile new file mode 100644 index 000000000..7f774ad12 --- /dev/null +++ b/cmd/soroban-cli/src/utils/contract-template/Makefile @@ -0,0 +1,16 @@ +default: build + +all: test + +test: build + cargo test + +build: + stellar contract build + @ls -l target/wasm32-unknown-unknown/release/*.wasm + +fmt: + cargo fmt --all + +clean: + cargo clean diff --git a/cmd/soroban-cli/src/utils/contract-init-template/contracts/hello_world/src/lib.rs b/cmd/soroban-cli/src/utils/contract-template/src/lib.rs similarity index 100% rename from cmd/soroban-cli/src/utils/contract-init-template/contracts/hello_world/src/lib.rs rename to cmd/soroban-cli/src/utils/contract-template/src/lib.rs diff --git a/cmd/soroban-cli/src/utils/contract-init-template/contracts/hello_world/src/test.rs b/cmd/soroban-cli/src/utils/contract-template/src/test.rs similarity index 100% rename from cmd/soroban-cli/src/utils/contract-init-template/contracts/hello_world/src/test.rs rename to cmd/soroban-cli/src/utils/contract-template/src/test.rs diff --git a/cmd/soroban-cli/src/utils/contract-init-template/.gitignore b/cmd/soroban-cli/src/utils/contract-workspace-template/.gitignore similarity index 100% rename from cmd/soroban-cli/src/utils/contract-init-template/.gitignore rename to cmd/soroban-cli/src/utils/contract-workspace-template/.gitignore diff --git a/cmd/soroban-cli/src/utils/contract-init-template/Cargo.toml.removeextension b/cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension similarity index 100% rename from cmd/soroban-cli/src/utils/contract-init-template/Cargo.toml.removeextension rename to cmd/soroban-cli/src/utils/contract-workspace-template/Cargo.toml.removeextension diff --git a/cmd/soroban-cli/src/utils/contract-init-template/README.md b/cmd/soroban-cli/src/utils/contract-workspace-template/README.md similarity index 100% rename from cmd/soroban-cli/src/utils/contract-init-template/README.md rename to cmd/soroban-cli/src/utils/contract-workspace-template/README.md From 9cc8fcd99b6c2fa2a9c34e43439b3d13ce4ea0e5 Mon Sep 17 00:00:00 2001 From: Elizabeth Engelman <4752801+elizabethengelman@users.noreply.github.com> Date: Mon, 14 Oct 2024 02:19:14 -0400 Subject: [PATCH 11/30] Feat/add rpc header arg (#1618) --- Cargo.lock | 2 +- FULL_HELP_DOCS.md | 35 ++++ cmd/crates/soroban-test/src/lib.rs | 1 + .../src/commands/contract/deploy/asset.rs | 4 +- .../src/commands/contract/deploy/wasm.rs | 5 +- .../src/commands/contract/extend.rs | 6 +- .../src/commands/contract/fetch.rs | 12 +- .../src/commands/contract/info/shared.rs | 15 +- .../src/commands/contract/install.rs | 25 ++- .../src/commands/contract/invoke.rs | 35 ++-- cmd/soroban-cli/src/commands/contract/read.rs | 4 +- .../src/commands/contract/restore.rs | 6 +- cmd/soroban-cli/src/commands/events.rs | 8 +- cmd/soroban-cli/src/commands/tx/send.rs | 8 +- cmd/soroban-cli/src/commands/tx/simulate.rs | 4 +- cmd/soroban-cli/src/config/mod.rs | 6 +- cmd/soroban-cli/src/config/network.rs | 171 ++++++++++++++++++ cmd/soroban-cli/src/wasm.rs | 19 +- 18 files changed, 292 insertions(+), 74 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71ca2b35f..55ebf62a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5022,7 +5022,7 @@ dependencies = [ [[package]] name = "stellar-rpc-client" version = "21.4.0" -source = "git+https://github.com/stellar/rs-stellar-rpc-client?branch=main#9f748334fffb2762db01b566dee455eea3095c79" +source = "git+https://github.com/stellar/rs-stellar-rpc-client?branch=main#7554d4c87c026313a1f5b3c7ae66a92b5ff7e091" dependencies = [ "clap", "hex", diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index c52636226..41575aea0 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -117,6 +117,7 @@ Get Id of builtin Soroban Asset Contract. Deprecated, use `stellar contract id a * `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" * `--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 @@ -134,6 +135,7 @@ Deploy builtin Soroban Asset Contract * `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" * `--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 @@ -180,6 +182,7 @@ Remove contract alias * `--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 @@ -200,6 +203,7 @@ Add contract alias * `--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 * `--overwrite` — Overwrite the contract alias if it already exists @@ -222,6 +226,7 @@ Show the contract id associated with a given alias * `--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 @@ -293,6 +298,7 @@ Generate a TypeScript / JavaScript package * `--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 @@ -359,6 +365,7 @@ If no keys are specified the contract itself is extended. Temporary * `--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 @@ -387,6 +394,7 @@ Deploy a wasm contract * `--wasm-hash ` — Hash of the already installed/deployed WASM file * `--salt ` — Custom salt 32-byte salt for the token id * `--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 @@ -420,6 +428,7 @@ Fetch a contract's Wasm binary * `--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 @@ -448,6 +457,7 @@ Deploy builtin Soroban Asset Contract * `--asset ` — ID of the Stellar classic asset to wrap, e.g. "USDC:G...5" * `--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 @@ -465,6 +475,7 @@ Deploy normal Wasm Contract * `--salt ` — ID of the Soroban contract * `--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 @@ -506,6 +517,7 @@ Outputs no data when no data is present in the contract. * `--wasm-hash ` — Wasm hash to get the data for * `--id ` — Contract id 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 * `--network ` — Name of network to use from config * `--global` — Use global config @@ -545,6 +557,7 @@ Outputs no data when no data is present in the contract. * `--wasm-hash ` — Wasm hash to get the data for * `--id ` — Contract id 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 * `--network ` — Name of network to use from config * `--global` — Use global config @@ -584,6 +597,7 @@ Outputs no data when no data is present in the contract. * `--wasm-hash ` — Wasm hash to get the data for * `--id ` — Contract id 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 * `--network ` — Name of network to use from config * `--global` — Use global config @@ -661,6 +675,7 @@ Install a WASM file to the ledger without creating a contract instance ###### **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 @@ -700,6 +715,7 @@ stellar contract invoke ... -- --help * `--id ` — Contract ID to invoke * `--is-view` — View the result simulating and do not sign and submit transaction. Deprecated use `--send=no` * `--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 @@ -777,6 +793,7 @@ Print the current value of a contract-data ledger entry Temporary * `--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 @@ -812,6 +829,7 @@ If no keys are specificed the contract itself is restored. * `--ledgers-to-extend ` — Number of ledgers to extend the entry * `--ttl-ledger-only` — Only print the new Time To Live ledger * `--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 @@ -872,6 +890,7 @@ Watch the network for contract events * `--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 @@ -945,6 +964,7 @@ Fund an identity on a test network ###### **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 * `--hd-path ` — If identity is a seed phrase use this hd path, default is 0 @@ -973,6 +993,7 @@ Generate a new identity with a seed phrase, currently 12 words * `--hd-path ` — When generating a secret key, which `hd_path` should be used from the original `seed_phrase` * `-d`, `--default-seed` — Generate the default seed phrase. Useful for testing. Equivalent to --seed 0000000000000000 * `--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 * `--fund` — Fund generated key pair @@ -1060,6 +1081,7 @@ Add a new network ###### **Options:** * `--rpc-url ` — RPC server endpoint +* `--rpc-header ` — Optional header (e.g. API Key) to include in requests to the RPC * `--network-passphrase ` — Network passphrase to sign the transaction sent to the rpc server * `--global` — Use global config * `--config-dir ` — Location of config directory, default is "." @@ -1272,6 +1294,7 @@ Any invalid contract id passed as `--address` will be ignored. * `--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 * `--archive-url ` — Archive URL @@ -1303,6 +1326,7 @@ Simulate a transaction envelope from stdin ###### **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 @@ -1321,6 +1345,7 @@ Calculate the hash of a transaction envelope from stdin ###### **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 @@ -1338,6 +1363,7 @@ Sign a transaction envelope appending the signature to the envelope * `--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 @@ -1354,6 +1380,7 @@ Send a transaction envelope to the network ###### **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 @@ -1396,6 +1423,7 @@ Transfers the XLM balance of an account to another account and removes the sourc * `--build-only` — Build the transaction and only write the base64 xdr to stdout * `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--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 @@ -1422,6 +1450,7 @@ Bumps forward the sequence number of the source account to the given sequence nu * `--build-only` — Build the transaction and only write the base64 xdr to stdout * `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--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 @@ -1448,6 +1477,7 @@ Creates, updates, or deletes a trustline Learn more about trustlines https://dev * `--build-only` — Build the transaction and only write the base64 xdr to stdout * `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--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 @@ -1477,6 +1507,7 @@ Creates and funds a new account with the specified starting balance * `--build-only` — Build the transaction and only write the base64 xdr to stdout * `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--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 @@ -1506,6 +1537,7 @@ Sets, modifies, or deletes a data entry (name/value pair) that is attached to an * `--build-only` — Build the transaction and only write the base64 xdr to stdout * `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--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 @@ -1533,6 +1565,7 @@ Sends an amount in a specific asset to a destination account * `--build-only` — Build the transaction and only write the base64 xdr to stdout * `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--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 @@ -1563,6 +1596,7 @@ Set option for an account such as flags, inflation destination, signers, home do * `--build-only` — Build the transaction and only write the base64 xdr to stdout * `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--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 @@ -1604,6 +1638,7 @@ Allows issuing account to configure authorization and trustline flags to an asse * `--build-only` — Build the transaction and only write the base64 xdr to stdout * `--sim-only` — (Deprecated) simulate the transaction and only write the base64 xdr to stdout * `--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 diff --git a/cmd/crates/soroban-test/src/lib.rs b/cmd/crates/soroban-test/src/lib.rs index 849b78796..2c62578ef 100644 --- a/cmd/crates/soroban-test/src/lib.rs +++ b/cmd/crates/soroban-test/src/lib.rs @@ -235,6 +235,7 @@ impl TestEnv { config::Args { network: network::Args { rpc_url: Some(self.rpc_url.clone()), + rpc_headers: [].to_vec(), network_passphrase: Some(LOCAL_NETWORK_PASSPHRASE.to_string()), network: None, }, diff --git a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs index ad0afce5e..263908521 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/asset.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/asset.rs @@ -16,7 +16,7 @@ use crate::{ NetworkRunnable, }, config::{self, data, network}, - rpc::{Client, Error as SorobanRpcError}, + rpc::Error as SorobanRpcError, tx::builder, utils::contract_id_hash_from_asset, }; @@ -88,7 +88,7 @@ impl NetworkRunnable for Cmd { let asset = &self.asset; let network = config.get_network()?; - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; client .verify_network_passphrase(Some(&network.network_passphrase)) .await?; diff --git a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs index 03ed3f438..21c685b93 100644 --- a/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs +++ b/cmd/soroban-cli/src/commands/contract/deploy/wasm.rs @@ -16,8 +16,7 @@ use crate::{ assembled::simulate_and_assemble_transaction, commands::{contract::install, HEADING_RPC}, config::{self, data, locator, network}, - rpc::{self, Client}, - utils, wasm, + rpc, utils, wasm, }; use crate::{ commands::{ @@ -208,7 +207,7 @@ impl NetworkRunnable for Cmd { None => rand::thread_rng().gen::<[u8; 32]>(), }; - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; client .verify_network_passphrase(Some(&network.network_passphrase)) .await?; diff --git a/cmd/soroban-cli/src/commands/contract/extend.rs b/cmd/soroban-cli/src/commands/contract/extend.rs index 92b986a22..24aac54c5 100644 --- a/cmd/soroban-cli/src/commands/contract/extend.rs +++ b/cmd/soroban-cli/src/commands/contract/extend.rs @@ -16,9 +16,7 @@ use crate::{ NetworkRunnable, }, config::{self, data, locator, network}, - key, - rpc::{self, Client}, - wasm, Pwd, + key, rpc, wasm, Pwd, }; const MAX_LEDGERS_TO_EXTEND: u32 = 535_679; @@ -132,7 +130,7 @@ impl NetworkRunnable for Cmd { let network = config.get_network()?; tracing::trace!(?network); let keys = self.key.parse_keys(&config.locator, &network)?; - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; let source_account = config.source_account()?; let extend_to = self.ledgers_to_extend(); diff --git a/cmd/soroban-cli/src/commands/contract/fetch.rs b/cmd/soroban-cli/src/commands/contract/fetch.rs index fd8070898..2714b1f07 100644 --- a/cmd/soroban-cli/src/commands/contract/fetch.rs +++ b/cmd/soroban-cli/src/commands/contract/fetch.rs @@ -7,12 +7,14 @@ use std::{fmt::Debug, fs, io}; use clap::{arg, command, Parser}; -use crate::commands::{global, NetworkRunnable}; -use crate::config::{ - self, locator, - network::{self, Network}, +use crate::{ + commands::{global, NetworkRunnable}, + config::{ + self, locator, + network::{self, Network}, + }, + wasm, Pwd, }; -use crate::{wasm, Pwd}; #[derive(Parser, Debug, Default, Clone)] #[allow(clippy::struct_excessive_bools)] diff --git a/cmd/soroban-cli/src/commands/contract/info/shared.rs b/cmd/soroban-cli/src/commands/contract/info/shared.rs index 4113f7d5b..0974632ae 100644 --- a/cmd/soroban-cli/src/commands/contract/info/shared.rs +++ b/cmd/soroban-cli/src/commands/contract/info/shared.rs @@ -2,13 +2,13 @@ use std::path::PathBuf; use crate::xdr; use clap::arg; -use soroban_rpc::Client; -use crate::commands::contract::info::shared::Error::InvalidWasmHash; -use crate::config::{locator, network}; -use crate::utils::rpc::get_remote_wasm_from_hash; -use crate::wasm; -use crate::wasm::Error::ContractIsStellarAsset; +use crate::{ + commands::contract::info::shared::Error::InvalidWasmHash, + config::{locator, network}, + utils::rpc::get_remote_wasm_from_hash, + wasm::{self, Error::ContractIsStellarAsset}, +}; #[derive(Debug, clap::Args, Clone, Default)] #[command(group( @@ -71,7 +71,8 @@ pub async fn fetch_wasm(args: &Args) -> Result>, Error> { let hash = xdr::Hash(hash); - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; + client .verify_network_passphrase(Some(&network.network_passphrase)) .await?; diff --git a/cmd/soroban-cli/src/commands/contract/install.rs b/cmd/soroban-cli/src/commands/contract/install.rs index d51158ec3..cd6e93b24 100644 --- a/cmd/soroban-cli/src/commands/contract/install.rs +++ b/cmd/soroban-cli/src/commands/contract/install.rs @@ -10,15 +10,20 @@ use crate::xdr::{ use clap::{command, Parser}; use super::restore; -use crate::assembled::simulate_and_assemble_transaction; -use crate::commands::txn_result::{TxnEnvelopeResult, TxnResult}; -use crate::commands::{global, NetworkRunnable}; -use crate::config::{self, data, network}; -use crate::key; -use crate::print::Print; -use crate::rpc::{self, Client}; -use crate::tx::builder::{self, TxExt}; -use crate::{utils, wasm}; +use crate::{ + assembled::simulate_and_assemble_transaction, + commands::{ + global, + txn_result::{TxnEnvelopeResult, TxnResult}, + NetworkRunnable, + }, + config::{self, data, network}, + key, + print::Print, + rpc, + tx::builder::{self, TxExt}, + utils, wasm, +}; const CONTRACT_META_SDK_KEY: &str = "rssdkver"; const PUBLIC_NETWORK_PASSPHRASE: &str = "Public Global Stellar Network ; September 2015"; @@ -103,7 +108,7 @@ impl NetworkRunnable for Cmd { let config = config.unwrap_or(&self.config); let contract = self.wasm.read()?; let network = config.get_network()?; - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; client .verify_network_passphrase(Some(&network.network_passphrase)) .await?; diff --git a/cmd/soroban-cli/src/commands/contract/invoke.rs b/cmd/soroban-cli/src/commands/contract/invoke.rs index e32d5d5a6..5d43f9bfa 100644 --- a/cmd/soroban-cli/src/commands/contract/invoke.rs +++ b/cmd/soroban-cli/src/commands/contract/invoke.rs @@ -7,29 +7,30 @@ use std::{fmt::Debug, fs, io}; use clap::{arg, command, Parser, ValueEnum}; -use crate::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, -}; - use soroban_rpc::{SimulateHostFunctionResult, SimulateTransactionResponse}; use soroban_spec::read::FromWasmError; use super::super::events; use super::arg_parsing; -use crate::assembled::simulate_and_assemble_transaction; -use crate::commands::contract::arg_parsing::{build_host_function_parameters, output_to_string}; -use crate::commands::txn_result::{TxnEnvelopeResult, TxnResult}; -use crate::commands::NetworkRunnable; -use crate::get_spec::{self, get_remote_contract_spec}; -use crate::print; use crate::{ - commands::global, + assembled::simulate_and_assemble_transaction, + commands::{ + contract::arg_parsing::{build_host_function_parameters, output_to_string}, + global, + txn_result::{TxnEnvelopeResult, TxnResult}, + NetworkRunnable, + }, config::{self, data, locator, network}, - rpc, Pwd, + get_spec::{self, get_remote_contract_spec}, + 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, + }, + Pwd, }; use soroban_spec_tools::contract; @@ -203,7 +204,7 @@ impl NetworkRunnable for Cmd { // For testing wasm arg parsing let _ = build_host_function_parameters(&contract_id, &self.slop, spec_entries, config)?; } - let client = rpc::Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; let account_details = if self.is_view { default_account_entry() } else { diff --git a/cmd/soroban-cli/src/commands/contract/read.rs b/cmd/soroban-cli/src/commands/contract/read.rs index 4e013a1f4..58efc93b7 100644 --- a/cmd/soroban-cli/src/commands/contract/read.rs +++ b/cmd/soroban-cli/src/commands/contract/read.rs @@ -13,7 +13,7 @@ use crate::{ commands::{global, NetworkRunnable}, config::{self, locator}, key, - rpc::{self, Client, FullLedgerEntries, FullLedgerEntry}, + rpc::{self, FullLedgerEntries, FullLedgerEntry}, }; #[derive(Parser, Debug, Clone)] @@ -181,7 +181,7 @@ impl NetworkRunnable for Cmd { let network = self.config.network.get(&locator)?; tracing::trace!(?network); - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; let keys = self.key.parse_keys(&locator, &network)?; Ok(client.get_full_ledger_entries(&keys).await?) } diff --git a/cmd/soroban-cli/src/commands/contract/restore.rs b/cmd/soroban-cli/src/commands/contract/restore.rs index 627fd3eee..87a52a9f6 100644 --- a/cmd/soroban-cli/src/commands/contract/restore.rs +++ b/cmd/soroban-cli/src/commands/contract/restore.rs @@ -17,9 +17,7 @@ use crate::{ NetworkRunnable, }, config::{self, data, locator, network}, - key, - rpc::{self, Client}, - wasm, Pwd, + key, rpc, wasm, Pwd, }; #[derive(Parser, Debug, Clone)] @@ -134,7 +132,7 @@ impl NetworkRunnable for Cmd { let network = config.get_network()?; tracing::trace!(?network); let entry_keys = self.key.parse_keys(&config.locator, &network)?; - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; let source_account = config.source_account()?; // Get the account sequence number diff --git a/cmd/soroban-cli/src/commands/events.rs b/cmd/soroban-cli/src/commands/events.rs index 0c4cfcc0e..a1f5de921 100644 --- a/cmd/soroban-cli/src/commands/events.rs +++ b/cmd/soroban-cli/src/commands/events.rs @@ -4,8 +4,10 @@ use std::io; use crate::xdr::{self, Limits, ReadXdr}; use super::{global, NetworkRunnable}; -use crate::config::{self, locator, network}; -use crate::rpc; +use crate::{ + config::{self, locator, network}, + rpc, +}; #[derive(Parser, Debug, Clone)] #[group(skip)] @@ -207,7 +209,7 @@ impl NetworkRunnable for Cmd { self.network.get(&self.locator) }?; - let client = rpc::Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; client .verify_network_passphrase(Some(&network.network_passphrase)) .await?; diff --git a/cmd/soroban-cli/src/commands/tx/send.rs b/cmd/soroban-cli/src/commands/tx/send.rs index c3856114d..22fbc860a 100644 --- a/cmd/soroban-cli/src/commands/tx/send.rs +++ b/cmd/soroban-cli/src/commands/tx/send.rs @@ -1,8 +1,10 @@ use async_trait::async_trait; use soroban_rpc::GetTransactionResponse; -use crate::commands::{global, NetworkRunnable}; -use crate::config::{self, locator, network}; +use crate::{ + commands::{global, NetworkRunnable}, + config::{self, locator, network}, +}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -52,7 +54,7 @@ impl NetworkRunnable for Cmd { } else { self.network.get(&self.locator)? }; - let client = crate::rpc::Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; let tx_env = super::xdr::tx_envelope_from_stdin()?; Ok(client.send_transaction_polling(&tx_env).await?) } diff --git a/cmd/soroban-cli/src/commands/tx/simulate.rs b/cmd/soroban-cli/src/commands/tx/simulate.rs index 1f534884d..cb2ed7c69 100644 --- a/cmd/soroban-cli/src/commands/tx/simulate.rs +++ b/cmd/soroban-cli/src/commands/tx/simulate.rs @@ -16,6 +16,8 @@ pub enum Error { Rpc(#[from] crate::rpc::Error), #[error(transparent)] Xdr(#[from] xdr::Error), + #[error(transparent)] + Network(#[from] config::network::Error), } /// Command to simulate a transaction envelope via rpc @@ -50,7 +52,7 @@ impl NetworkRunnable for Cmd { ) -> Result { let config = config.unwrap_or(&self.config); let network = config.get_network()?; - let client = crate::rpc::Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; let tx = super::xdr::unwrap_envelope_v1(super::xdr::tx_envelope_from_stdin()?)?; let tx = simulate_and_assemble_transaction(&client, &tx).await?; Ok(tx) diff --git a/cmd/soroban-cli/src/config/mod.rs b/cmd/soroban-cli/src/config/mod.rs index 12f571a50..b961f0f67 100644 --- a/cmd/soroban-cli/src/config/mod.rs +++ b/cmd/soroban-cli/src/config/mod.rs @@ -2,8 +2,6 @@ use address::Address; use clap::{arg, command}; use serde::{Deserialize, Serialize}; -use soroban_rpc::Client; - use crate::{ print::Print, signer::{self, LocalKey, Signer, SignerKind}, @@ -98,7 +96,7 @@ impl Args { ) -> Result, Error> { let network = self.get_network()?; let source_key = self.key_pair()?; - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; let latest_ledger = client.get_latest_ledger().await?.sequence; let seq_num = latest_ledger + 60; // ~ 5 min Ok(signer::sign_soroban_authorizations( @@ -116,7 +114,7 @@ impl Args { pub async fn next_sequence_number(&self, account_str: &str) -> Result { let network = self.get_network()?; - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; Ok((client.get_account(account_str).await?.seq_num.0 + 1).into()) } } diff --git a/cmd/soroban-cli/src/config/network.rs b/cmd/soroban-cli/src/config/network.rs index b6f6d8c1d..ac7dc04bc 100644 --- a/cmd/soroban-cli/src/config/network.rs +++ b/cmd/soroban-cli/src/config/network.rs @@ -1,7 +1,11 @@ use clap::arg; +use itertools::Itertools; +use jsonrpsee_http_client::HeaderMap; use phf::phf_map; +use reqwest::header::{HeaderName, HeaderValue, InvalidHeaderName, InvalidHeaderValue}; use serde::{Deserialize, Serialize}; use serde_json::Value; +use std::collections::HashMap; use std::str::FromStr; use stellar_strkey::ed25519::PublicKey; use url::Url; @@ -30,6 +34,12 @@ pub enum Error { InvalidUrl(String), #[error("funding failed: {0}")] FundingFailed(String), + #[error(transparent)] + InvalidHeaderName(#[from] InvalidHeaderName), + #[error(transparent)] + InvalidHeaderValue(#[from] InvalidHeaderValue), + #[error("invalid HTTP header: must be in the form 'key:value'")] + InvalidHeader, } #[derive(Debug, clap::Args, Clone, Default)] @@ -44,6 +54,17 @@ pub struct Args { help_heading = HEADING_RPC, )] pub rpc_url: Option, + /// RPC Header(s) to include in requests to the RPC provider + #[arg( + long = "rpc-header", + env = "STELLAR_RPC_HEADERS", + help_heading = HEADING_RPC, + num_args = 1, + action = clap::ArgAction::Append, + value_delimiter = '\n', + value_parser = parse_http_header, + )] + pub rpc_headers: Vec<(String, String)>, /// Network passphrase to sign the transaction sent to the rpc server #[arg( long = "network-passphrase", @@ -76,6 +97,7 @@ impl Args { { Ok(Network { rpc_url, + rpc_headers: self.rpc_headers.clone(), network_passphrase, }) } else { @@ -94,6 +116,17 @@ pub struct Network { help_heading = HEADING_RPC, )] pub rpc_url: String, + /// Optional header (e.g. API Key) to include in requests to the RPC + #[arg( + long = "rpc-header", + env = "STELLAR_RPC_HEADERS", + help_heading = HEADING_RPC, + num_args = 1, + action = clap::ArgAction::Append, + value_delimiter = '\n', + value_parser = parse_http_header, + )] + pub rpc_headers: Vec<(String, String)>, /// Network passphrase to sign the transaction sent to the rpc server #[arg( long, @@ -103,6 +136,21 @@ pub struct Network { pub network_passphrase: String, } +fn parse_http_header(header: &str) -> Result<(String, String), Error> { + let header_components = header.splitn(2, ':'); + + let (key, value) = header_components + .map(str::trim) + .next_tuple() + .ok_or_else(|| Error::InvalidHeader)?; + + // Check that the headers are properly formatted + HeaderName::from_str(key)?; + HeaderValue::from_str(value)?; + + Ok((key.to_string(), value.to_string())) +} + impl Network { pub async fn helper_url(&self, addr: &str) -> Result { tracing::debug!("address {addr:?}"); @@ -160,6 +208,19 @@ impl Network { pub fn rpc_uri(&self) -> Result { Url::from_str(&self.rpc_url).map_err(|_| Error::InvalidUrl(self.rpc_url.to_string())) } + + pub fn rpc_client(&self) -> Result { + let mut header_hash_map = HashMap::new(); + for (header_name, header_value) in &self.rpc_headers { + header_hash_map.insert(header_name.to_string(), header_value.to_string()); + } + + let header_map: HeaderMap = (&header_hash_map) + .try_into() + .map_err(|_| Error::InvalidHeader)?; + + Ok(rpc::Client::new_with_headers(&self.rpc_url, header_map)?) + } } pub static DEFAULTS: phf::Map<&'static str, (&'static str, &'static str)> = phf_map! { @@ -186,6 +247,7 @@ impl From<&(&str, &str)> for Network { fn from(n: &(&str, &str)) -> Self { Self { rpc_url: n.0.to_string(), + rpc_headers: Vec::new(), network_passphrase: n.1.to_string(), } } @@ -197,11 +259,15 @@ mod tests { use mockito::Server; use serde_json::json; + const INVALID_HEADER_NAME: &str = "api key"; + const INVALID_HEADER_VALUE: &str = "cannot include a carriage return \r in the value"; + #[tokio::test] async fn test_helper_url_local_network() { let network = Network { rpc_url: "http://localhost:8000".to_string(), network_passphrase: passphrase::LOCAL.to_string(), + rpc_headers: Vec::new(), }; let result = network @@ -239,6 +305,7 @@ mod tests { let network = Network { rpc_url: server.url(), network_passphrase: passphrase::TESTNET.to_string(), + rpc_headers: Vec::new(), }; let url = network .helper_url("GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI") @@ -269,6 +336,7 @@ mod tests { let network = Network { rpc_url: server.url(), network_passphrase: passphrase::TESTNET.to_string(), + rpc_headers: Vec::new(), }; let url = network .helper_url("GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI") @@ -276,4 +344,107 @@ mod tests { .unwrap(); assert_eq!(url.as_str(), "https://friendbot.stellar.org/secret?api_key=123456&user=demo&addr=GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI"); } + + // testing parse_header function + #[tokio::test] + async fn test_parse_http_header_ok() { + let result = parse_http_header("Authorization: Bearer 1234"); + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_parse_http_header_error_with_invalid_name() { + let invalid_header = format!("{INVALID_HEADER_NAME}: Bearer 1234"); + let result = parse_http_header(&invalid_header); + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + format!("invalid HTTP header name") + ); + } + + #[tokio::test] + async fn test_parse_http_header_error_with_invalid_value() { + let invalid_header = format!("Authorization: {INVALID_HEADER_VALUE}"); + let result = parse_http_header(&invalid_header); + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + format!("failed to parse header value") + ); + } + + // testing rpc_client function - we're testing this and the parse_http_header function separately because when a user has their network already configured in a toml file, the parse_http_header function is not called and we want to make sure that if the toml file is correctly formatted, the rpc_client function will work as expected + + #[tokio::test] + async fn test_rpc_client_is_ok_when_there_are_no_headers() { + let network = Network { + rpc_url: "http://localhost:1234".to_string(), + network_passphrase: "Network passphrase".to_string(), + rpc_headers: [].to_vec(), + }; + + let result = network.rpc_client(); + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_rpc_client_is_ok_with_correctly_formatted_headers() { + let network = Network { + rpc_url: "http://localhost:1234".to_string(), + network_passphrase: "Network passphrase".to_string(), + rpc_headers: [("Authorization".to_string(), "Bearer 1234".to_string())].to_vec(), + }; + + let result = network.rpc_client(); + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_rpc_client_is_ok_with_multiple_headers() { + let network = Network { + rpc_url: "http://localhost:1234".to_string(), + network_passphrase: "Network passphrase".to_string(), + rpc_headers: [ + ("Authorization".to_string(), "Bearer 1234".to_string()), + ("api-key".to_string(), "5678".to_string()), + ] + .to_vec(), + }; + + let result = network.rpc_client(); + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_rpc_client_returns_err_with_invalid_header_name() { + let network = Network { + rpc_url: "http://localhost:8000".to_string(), + network_passphrase: passphrase::LOCAL.to_string(), + rpc_headers: [(INVALID_HEADER_NAME.to_string(), "Bearer".to_string())].to_vec(), + }; + + let result = network.rpc_client(); + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + format!("invalid HTTP header: must be in the form 'key:value'") + ); + } + + #[tokio::test] + async fn test_rpc_client_returns_err_with_invalid_header_value() { + let network = Network { + rpc_url: "http://localhost:8000".to_string(), + network_passphrase: passphrase::LOCAL.to_string(), + rpc_headers: [("api-key".to_string(), INVALID_HEADER_VALUE.to_string())].to_vec(), + }; + + let result = network.rpc_client(); + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + format!("invalid HTTP header: must be in the form 'key:value'") + ); + } } diff --git a/cmd/soroban-cli/src/wasm.rs b/cmd/soroban-cli/src/wasm.rs index bc202a4b3..5f0ed3b5c 100644 --- a/cmd/soroban-cli/src/wasm.rs +++ b/cmd/soroban-cli/src/wasm.rs @@ -1,9 +1,6 @@ -use crate::config::locator; -use crate::config::network::Network; use crate::xdr::{self, Hash, LedgerKey, LedgerKeyContractCode}; use clap::arg; use sha2::{Digest, Sha256}; -use soroban_rpc::Client; use soroban_spec_tools::contract::{self, Spec}; use std::{ fs, io, @@ -11,10 +8,14 @@ use std::{ }; use stellar_xdr::curr::{ContractDataEntry, ContractExecutable, ScVal}; -use crate::utils::rpc::get_remote_wasm_from_hash; -use crate::utils::{self}; - -use crate::wasm::Error::{ContractIsStellarAsset, UnexpectedContractToken}; +use crate::{ + config::{ + locator, + network::{Error as NetworkError, Network}, + }, + utils::{self, rpc::get_remote_wasm_from_hash}, + wasm::Error::{ContractIsStellarAsset, UnexpectedContractToken}, +}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -47,6 +48,8 @@ pub enum Error { a network built-in asset contract that does not have a downloadable code binary" )] ContractIsStellarAsset, + #[error(transparent)] + Network(#[from] NetworkError), } #[derive(Debug, clap::Args, Clone)] @@ -128,7 +131,7 @@ pub async fn fetch_from_contract( .resolve_contract_id(contract_id, &network.network_passphrase)? .0; - let client = Client::new(&network.rpc_url)?; + let client = network.rpc_client()?; client .verify_network_passphrase(Some(&network.network_passphrase)) .await?; From d538ea9a1b5bbf1847a987ccf316d34e55465313 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:21:01 +1000 Subject: [PATCH 12/30] Add GitHub Action for installing stellar-cli in repos (#1669) --- action.yml | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 action.yml diff --git a/action.yml b/action.yml new file mode 100644 index 000000000..3ed6af8e7 --- /dev/null +++ b/action.yml @@ -0,0 +1,47 @@ +name: 'Install stellar-cli' +description: 'Install the stellar-cli' +inputs: + version: + description: | + Recommended for use only in testing new versions of the action prior to + release. For regular use, use the version of the action corresponding to + the version of the stellar-cli that should be installed. + required: false +runs: + using: "composite" + steps: + - name: Setup install path + shell: bash + run: | + mkdir -p $HOME/.local/bin + echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Copy binary to install location + shell: bash + env: + REF: ${{ github.action_ref }} + run: | + version="${{ inputs.version || env.REF }}" + case "${{ runner.os }}-${{ runner.arch }}" in + 'Linux-X64') + os_arch=x86_64-unknown-linux-gnu + ;; + 'Linux-ARM64') + os_arch=aarch64-unknown-linux-gnu + ;; + 'macOS-X64') + os_arch=x86_64-apple-darwin + ;; + 'macOS-ARM64') + os_arch=aarch64-apple-darwin + ;; + 'Windows-X64') + os_arch=x86_64-pc-windows-msvc + ;; + *) + echo "Unsupported OS / Arch pair: ${{ runner.os }} ${{ runner.arch }}" >&2 + exit 1 + esac + file="stellar-cli-$version-$os_arch.tar.gz" + url="https://github.com/stellar/stellar-cli/releases/download/v$version/$file" + echo "$url" + curl -fL "$url" | tar xvz -C $HOME/.local/bin From 18adf2b620e55bd29c3615afffa8a4b0fff0695f Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Tue, 15 Oct 2024 12:24:26 +1000 Subject: [PATCH 13/30] Add attestation of binaries uploaded to release (#1670) --- .github/workflows/binaries.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 42ddb786a..e3fd14926 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -62,6 +62,11 @@ jobs: 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 From 5dbc0a7e3559c14b80b21631f93a1bb16b6180b7 Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 16 Oct 2024 00:16:40 +1000 Subject: [PATCH 14/30] Fix attestation during binary release (#1674) --- .github/workflows/binaries.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index e3fd14926..08641b9ad 100644 --- a/.github/workflows/binaries.yml +++ b/.github/workflows/binaries.yml @@ -13,6 +13,11 @@ defaults: run: shell: bash +permissions: + id-token: write + contents: write + attestations: write + jobs: build: 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 15/30] 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 16/30] 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 17/30] 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 18/30] 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 19/30] 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 20/30] 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 21/30] 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 22/30] 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 23/30] 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 24/30] 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 25/30] 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 26/30] 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 27/30] 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 28/30] =?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 29/30] 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 30/30] 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()) } }