diff --git a/Cargo.lock b/Cargo.lock index b377548c6..39b18f07b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4863,9 +4863,9 @@ dependencies = [ [[package]] name = "soroban-builtin-sdk-macros" -version = "21.1.2" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa78f4b1c752f5471b033fe54279ef0617ace342be7be11acc7d90e5677790e" +checksum = "44877373b3dc6c662377cb1600e3a62706d75e484b6064f9cd22e467c676b159" dependencies = [ "itertools 0.11.0", "proc-macro2", @@ -4875,7 +4875,7 @@ dependencies = [ [[package]] name = "soroban-cli" -version = "21.1.1" +version = "21.2.0" dependencies = [ "assert_cmd", "assert_fs", @@ -4954,9 +4954,9 @@ dependencies = [ [[package]] name = "soroban-env-common" -version = "21.1.2" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9acd7dbf8fc4222f62a4f06c5b32c3e097de97f5ff48218c8d77676d3424f363" +checksum = "590add16843a61b01844e19e89bccaaee6aa21dc76809017b0662c17dc139ee9" dependencies = [ "arbitrary", "crate-git-revision 0.0.6", @@ -4973,9 +4973,9 @@ dependencies = [ [[package]] name = "soroban-env-guest" -version = "21.1.2" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "558a69d53d543a4b1ac60681332594dc1417080cffd2a6851bb6e0a376ebc76f" +checksum = "05ec8dc43acdd6c7e7b371acf44fc1a7dac24934ae3b2f05fafd618818548176" dependencies = [ "soroban-env-common", "static_assertions", @@ -4983,9 +4983,9 @@ dependencies = [ [[package]] name = "soroban-env-host" -version = "21.1.2" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956beee1e959b7b8ac7bea8396454d1534927276830430bf015eafdc756d84ae" +checksum = "4e25aaffe0c62eb65e0e349f725b4b8b13ad0764d78a15aab5bbccb5c4797726" dependencies = [ "backtrace", "curve25519-dalek 4.1.3", @@ -5016,9 +5016,9 @@ dependencies = [ [[package]] name = "soroban-env-macros" -version = "21.1.2" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04b96c8cf73c941ca134eefd00aa5085c4bcae5d534dd3937f4d69b401a838b" +checksum = "3e16b761459fdf3c4b62b24df3941498d14e5246e6fadfb4774ed8114d243aa4" dependencies = [ "itertools 0.11.0", "proc-macro2", @@ -5031,13 +5031,13 @@ dependencies = [ [[package]] name = "soroban-hello" -version = "21.1.1" +version = "21.2.0" [[package]] name = "soroban-ledger-snapshot" -version = "21.1.1" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e99e474b9faf76142348780651b0129747d004818447a71c44325152d3ec71" +checksum = "667a040c424d5a479387a6ca71f9591c364cdd2cfdfb1f4227753b4d1bab2a80" dependencies = [ "serde", "serde_json", @@ -5049,9 +5049,9 @@ dependencies = [ [[package]] name = "soroban-sdk" -version = "21.1.1" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056d762146fba4d5c0798920484f0120526b3e019b021e6efff6ad7dd62cdcbb" +checksum = "1e76cfdcf2610f97d595db27dd164abe8f38c00b745e822220c2874c185d9c6f" dependencies = [ "arbitrary", "bytes-lit", @@ -5069,9 +5069,9 @@ dependencies = [ [[package]] name = "soroban-sdk-macros" -version = "21.1.1" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7d4d78936704cc2e686e1bb77fb5e9075adc392756aea74a3eb47aab74dd7e" +checksum = "21c0ed4e51a37c8ef530f6704a25f14447e8bc74b9e0c2046a21cfecc5ced329" dependencies = [ "crate-git-revision 0.0.6", "darling", @@ -5089,9 +5089,9 @@ dependencies = [ [[package]] name = "soroban-spec" -version = "21.1.1" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c72bb3677167ba79c8f0f307b3a5b6469c40fd3ff01599298b3eff5c3f6e19" +checksum = "1b411868046bc9aad3d481ef57ec5db34c58016c715bf871d854c8c752872b19" dependencies = [ "base64 0.13.1", "stellar-xdr", @@ -5101,7 +5101,7 @@ dependencies = [ [[package]] name = "soroban-spec-json" -version = "21.1.1" +version = "21.2.0" dependencies = [ "pretty_assertions", "serde", @@ -5115,9 +5115,9 @@ dependencies = [ [[package]] name = "soroban-spec-rust" -version = "21.1.1" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c6ca7570c91f2a54120269e6a7edb2f968b1661c54d0faca40b0f727fbc24b7" +checksum = "e71e218a6ea10c0f858993d35b168a21ac7185c936c745a34a371d76d24fba0c" dependencies = [ "prettyplease", "proc-macro2", @@ -5131,7 +5131,7 @@ dependencies = [ [[package]] name = "soroban-spec-tools" -version = "21.1.1" +version = "21.2.0" dependencies = [ "base64 0.21.7", "ethnum", @@ -5150,7 +5150,7 @@ dependencies = [ [[package]] name = "soroban-spec-typescript" -version = "21.1.1" +version = "21.2.0" dependencies = [ "base64 0.21.7", "heck 0.4.1", @@ -5171,7 +5171,7 @@ dependencies = [ [[package]] name = "soroban-test" -version = "21.1.1" +version = "21.2.0" dependencies = [ "assert_cmd", "assert_fs", @@ -5199,9 +5199,9 @@ dependencies = [ [[package]] name = "soroban-token-sdk" -version = "21.1.1" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56459abc11f5d1d8a3a9a0bbdb51513b679179b4389fa90bb5f072819645d1e0" +checksum = "54a758c3af83d174cd5f512d28a1c03983fc10888f75ebcc884ce303e782d409" dependencies = [ "soroban-sdk", ] @@ -5243,14 +5243,14 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stellar-cli" -version = "21.1.1" +version = "21.2.0" dependencies = [ "soroban-cli", ] [[package]] name = "stellar-ledger" -version = "21.1.1" +version = "21.2.0" dependencies = [ "async-trait", "bollard", @@ -5289,9 +5289,9 @@ dependencies = [ [[package]] name = "stellar-rpc-client" -version = "21.3.1" +version = "21.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db1dca8e70a6e43a42bd365e61063807bb24cf04de46bcd60140a27e00a3a076" +checksum = "c735c8e456fa7c37f72dd2a6abc022a111b3bf9b0520d50eef091eb1336ad370" dependencies = [ "clap", "hex", @@ -5325,9 +5325,9 @@ dependencies = [ [[package]] name = "stellar-xdr" -version = "21.1.0" +version = "21.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec43c9c5ae7ec7b6ac9e263b6d5b9e3781aa05ba3a1c05f6e70701c5c6600665" +checksum = "2675a71212ed39a806e415b0dbf4702879ff288ec7f5ee996dda42a135512b50" dependencies = [ "arbitrary", "base64 0.13.1", @@ -5573,35 +5573,35 @@ dependencies = [ [[package]] name = "test_custom_account" -version = "21.1.1" +version = "21.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_custom_types" -version = "21.1.1" +version = "21.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_hello_world" -version = "21.1.1" +version = "21.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_swap" -version = "21.1.1" +version = "21.2.0" dependencies = [ "soroban-sdk", ] [[package]] name = "test_token" -version = "21.1.1" +version = "21.2.0" dependencies = [ "soroban-sdk", "soroban-token-sdk", @@ -5609,7 +5609,7 @@ dependencies = [ [[package]] name = "test_udt" -version = "21.1.1" +version = "21.2.0" dependencies = [ "soroban-sdk", ] diff --git a/Cargo.toml b/Cargo.toml index 7feebcf21..1976a0581 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,52 +11,52 @@ default-members = ["cmd/soroban-cli", "cmd/crates/soroban-spec-tools", "cmd/crat exclude = ["cmd/crates/soroban-test/tests/fixtures/hello"] [workspace.package] -version = "21.1.1" +version = "21.2.0" rust-version = "1.79.0" [workspace.dependencies.soroban-env-host] -version = "=21.1.2" +version = "=21.2.0" [workspace.dependencies.soroban-simulation] -version = "21.1.2" +version = "21.2.0" [workspace.dependencies.soroban-spec] -version = "=21.1.1" +version = "=21.2.0" [workspace.dependencies.soroban-spec-rust] -version = "=21.1.1" +version = "=21.2.0" [workspace.dependencies.soroban-spec-json] -version = "=21.1.1" +version = "=21.2.0" path = "./cmd/crates/soroban-spec-json" [workspace.dependencies.soroban-spec-typescript] -version = "21.1.1" +version = "21.2.0" path = "./cmd/crates/soroban-spec-typescript" [workspace.dependencies.soroban-spec-tools] -version = "21.1.1" +version = "21.2.0" path = "./cmd/crates/soroban-spec-tools" [workspace.dependencies.soroban-sdk] -version = "=21.1.1" +version = "=21.2.0" [workspace.dependencies.soroban-token-sdk] -version = "=21.1.1" +version = "=21.2.0" [workspace.dependencies.soroban-ledger-snapshot] -version = "=21.1.1" +version = "=21.2.0" [workspace.dependencies.soroban-cli] -version = "=21.1.1" +version = "=21.2.0" path = "cmd/soroban-cli" [workspace.dependencies.soroban-rpc] package = "stellar-rpc-client" -version = "21.3.1" +version = "21.4.0" [workspace.dependencies.stellar-xdr] -version = "21.1.0" +version = "21.2.0" default-features = true [workspace.dependencies] diff --git a/FULL_HELP_DOCS.md b/FULL_HELP_DOCS.md index 270cc0fa5..8dea0e36b 100644 --- a/FULL_HELP_DOCS.md +++ b/FULL_HELP_DOCS.md @@ -266,7 +266,7 @@ Extend the time to live ledger of a contract-data ledger entry. If no keys are specified the contract itself is extended. -**Usage:** `stellar contract extend [OPTIONS] --ledgers-to-extend --durability --source-account ` +**Usage:** `stellar contract extend [OPTIONS] --ledgers-to-extend --source-account ` ###### **Options:** @@ -534,7 +534,7 @@ Optimize a WASM file Print the current value of a contract-data ledger entry -**Usage:** `stellar contract read [OPTIONS] --durability --source-account ` +**Usage:** `stellar contract read [OPTIONS] --source-account ` ###### **Options:** @@ -581,7 +581,7 @@ Restore an evicted value for a contract-data legder entry. If no keys are specificed the contract itself is restored. -**Usage:** `stellar contract restore [OPTIONS] --durability --source-account ` +**Usage:** `stellar contract restore [OPTIONS] --source-account ` ###### **Options:** @@ -627,7 +627,7 @@ Watch the network for contract events ###### **Options:** -* `--start-ledger ` — The first ledger sequence number in the range to pull events +* `--start-ledger ` — The first ledger sequence number in the range to pull events https://developers.stellar.org/docs/learn/encyclopedia/network-configuration/ledger-headers#ledger-sequence * `--cursor ` — The cursor corresponding to the start of the event range * `--output ` — Output formatting options for event stream @@ -1060,7 +1060,7 @@ Start a container running a Stellar node, RPC, API, and friendbot (faucet). By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: -`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc` +`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` **Usage:** `stellar network start [OPTIONS] ` @@ -1074,6 +1074,7 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** * `-d`, `--docker-host ` — Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock +* `--name ` — Optional argument to specify the container name * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1089,14 +1090,11 @@ By default, when starting a testnet container, without any optional arguments, i 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. -**Usage:** `stellar network stop [OPTIONS] ` +**Usage:** `stellar network stop [OPTIONS] ` ###### **Arguments:** -* `` — Network to stop - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to stop ###### **Options:** @@ -1112,24 +1110,21 @@ Commands to start, stop and get logs for a quickstart container ###### **Subcommands:** -* `logs` — Tail logs of a running network container -* `start` — Start network -* `stop` — Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it +* `logs` — Get logs from a running network container +* `start` — Start a container running a Stellar node, RPC, API, and friendbot (faucet) +* `stop` — Stop a network container started with `network container start` ## `stellar network container logs` -Tail logs of a running network container +Get logs from a running network container -**Usage:** `stellar network container logs [OPTIONS] ` +**Usage:** `stellar network container logs [OPTIONS] ` ###### **Arguments:** -* `` — Network to tail - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to get logs from ###### **Options:** @@ -1139,15 +1134,13 @@ Tail logs of a running network container ## `stellar network container start` -Start network - Start a container running a Stellar node, RPC, API, and friendbot (faucet). -`stellar network start NETWORK [OPTIONS]` +`stellar network container start NETWORK [OPTIONS]` By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: -`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc` +`docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` **Usage:** `stellar network container start [OPTIONS] ` @@ -1161,6 +1154,7 @@ By default, when starting a testnet container, without any optional arguments, i ###### **Options:** * `-d`, `--docker-host ` — Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock +* `--name ` — Optional argument to specify the container name * `-l`, `--limits ` — Optional argument to specify the limits for the local network only * `-p`, `--ports-mapping ` — Argument to specify the `HOST_PORT:CONTAINER_PORT` mapping @@ -1172,16 +1166,13 @@ By default, when starting a testnet container, without any optional arguments, i ## `stellar network container stop` -Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it +Stop a network container started with `network container start` -**Usage:** `stellar network container stop [OPTIONS] ` +**Usage:** `stellar network container stop [OPTIONS] ` ###### **Arguments:** -* `` — Network to stop - - Possible values: `local`, `testnet`, `futurenet`, `pubnet` - +* `` — Container to stop ###### **Options:** @@ -1206,6 +1197,7 @@ Sign, Simulate, and Send transactions ###### **Subcommands:** * `simulate` — Simulate a transaction envelope from stdin +* `hash` — Calculate the hash of a transaction envelope from stdin @@ -1227,6 +1219,20 @@ Simulate a transaction envelope from stdin +## `stellar tx hash` + +Calculate the hash of a transaction envelope from stdin + +**Usage:** `stellar tx hash [OPTIONS]` + +###### **Options:** + +* `--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 + + + ## `stellar cache` Cache for transactions and contract specs diff --git a/cmd/crates/soroban-test/Cargo.toml b/cmd/crates/soroban-test/Cargo.toml index 430393d0c..add2aa90b 100644 --- a/cmd/crates/soroban-test/Cargo.toml +++ b/cmd/crates/soroban-test/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/soroban-test" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "21.1.1" +version = "21.2.0" edition = "2021" rust-version.workspace = true autobins = false diff --git a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml index 7c2f04055..68c5667c5 100644 --- a/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/hello/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "soroban-hello" -version = "21.1.1" +version = "21.2.0" edition = "2021" publish = false 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 721b29b88..ead561d8b 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_account/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_account" -version = "21.1.1" +version = "21.2.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml index fed42a2f2..5f58afe17 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_custom_types" -version = "21.1.1" +version = "21.2.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml index 50fcf65b0..f4e35da4f 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/hello_world/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "test_hello_world" -version = "21.1.1" +version = "21.2.0" authors = ["Stellar Development Foundation "] license = "Apache-2.0" edition = "2021" 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 7a6bd5881..defeaa4d2 100644 --- a/cmd/crates/soroban-test/tests/it/integration/hello_world.rs +++ b/cmd/crates/soroban-test/tests/it/integration/hello_world.rs @@ -301,6 +301,18 @@ async fn contract_data_read() { .assert() .success() .stdout(predicates::str::starts_with("COUNTER,2")); + + // ensure default durability = persistent works + sandbox + .new_assert_cmd("contract") + .arg("read") + .arg("--id") + .arg(id) + .arg("--key") + .arg(KEY) + .assert() + .success() + .stdout(predicates::str::starts_with("COUNTER,2")); } #[tokio::test] diff --git a/cmd/crates/soroban-test/tests/it/integration/tx.rs b/cmd/crates/soroban-test/tests/it/integration/tx.rs index 9f5204a8d..bcb880b18 100644 --- a/cmd/crates/soroban-test/tests/it/integration/tx.rs +++ b/cmd/crates/soroban-test/tests/it/integration/tx.rs @@ -30,3 +30,22 @@ async fn txn_simulate() { assembled_str ); } + +#[tokio::test] +async fn txn_hash() { + let sandbox = &TestEnv::new(); + + let xdr_base64 = "AAAAAgAAAACVk/0xt9tV/cUbF53iwQ3tkKLlq9zG2wV5qd9lRjZjlQAHt/sAFsKTAAAABAAAAAEAAAAAAAAAAAAAAABmOg6nAAAAAAAAAAEAAAAAAAAAGAAAAAAAAAABfcHs35M1GZ/JkY2+DHMs4dEUaqjynMnDYK/Gp0eulN8AAAAIdHJhbnNmZXIAAAADAAAAEgAAAAEFO1FR2Wg49QFY5KPOFAQ0bV5fN+7LD2GSQvOaHSH44QAAABIAAAAAAAAAAJWT/TG321X9xRsXneLBDe2QouWr3MbbBXmp32VGNmOVAAAACgAAAAAAAAAAAAAAADuaygAAAAABAAAAAQAAAAEFO1FR2Wg49QFY5KPOFAQ0bV5fN+7LD2GSQvOaHSH44QAAAY9SyLSVABbC/QAAABEAAAABAAAAAwAAAA8AAAASYXV0aGVudGljYXRvcl9kYXRhAAAAAAANAAAAJUmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjHQAAAAAAAAAAAAAPAAAAEGNsaWVudF9kYXRhX2pzb24AAAANAAAAcnsidHlwZSI6IndlYmF1dGhuLmdldCIsImNoYWxsZW5nZSI6ImhnMlRhOG8wWTliWFlyWlMyZjhzWk1kRFp6ektCSXhQNTZSd1FaNE90bTgiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjQ1MDcifQAAAAAADwAAAAlzaWduYXR1cmUAAAAAAAANAAAAQBcpuTFMxzkAdBs+5VIyJCBHaNuwEAva+kZVET4YuHVKF8gNII567RhxsnhBBSo5dDvssTN6vf2i42eEty66MtoAAAAAAAAAAX3B7N+TNRmfyZGNvgxzLOHRFGqo8pzJw2CvxqdHrpTfAAAACHRyYW5zZmVyAAAAAwAAABIAAAABBTtRUdloOPUBWOSjzhQENG1eXzfuyw9hkkLzmh0h+OEAAAASAAAAAAAAAACVk/0xt9tV/cUbF53iwQ3tkKLlq9zG2wV5qd9lRjZjlQAAAAoAAAAAAAAAAAAAAAA7msoAAAAAAAAAAAEAAAAAAAAAAwAAAAYAAAABfcHs35M1GZ/JkY2+DHMs4dEUaqjynMnDYK/Gp0eulN8AAAAUAAAAAQAAAAYAAAABBTtRUdloOPUBWOSjzhQENG1eXzfuyw9hkkLzmh0h+OEAAAAUAAAAAQAAAAeTiL4Gr2piUAmsXTev1ZzJ4kE2NUGZ0QMObd05iAMyzAAAAAMAAAAGAAAAAX3B7N+TNRmfyZGNvgxzLOHRFGqo8pzJw2CvxqdHrpTfAAAAEAAAAAEAAAACAAAADwAAAAdCYWxhbmNlAAAAABIAAAABBTtRUdloOPUBWOSjzhQENG1eXzfuyw9hkkLzmh0h+OEAAAABAAAAAAAAAACVk/0xt9tV/cUbF53iwQ3tkKLlq9zG2wV5qd9lRjZjlQAAAAYAAAABBTtRUdloOPUBWOSjzhQENG1eXzfuyw9hkkLzmh0h+OEAAAAVAAABj1LItJUAAAAAAEyTowAAGMgAAAG4AAAAAAADJBsAAAABRjZjlQAAAEASFnAIzNqpfdzv6yT0rSLMUDFgt7a/inCHurNCG55Jp8Imho04qRH+JNdkq0BgMC7yAJqH4N6Y2iGflFt3Lp4L"; + + let expected_hash = "bcc9fa60c8f6607c981d6e1c65d77ae07617720113f9080fe5883d8e4a331a68"; + + let hash = sandbox + .new_assert_cmd("tx") + .arg("hash") + .write_stdin(xdr_base64.as_bytes()) + .assert() + .success() + .stdout_as_str(); + + assert_eq!(hash.trim(), expected_hash); +} diff --git a/cmd/soroban-cli/Cargo.toml b/cmd/soroban-cli/Cargo.toml index 2a58b22d3..4501999cb 100644 --- a/cmd/soroban-cli/Cargo.toml +++ b/cmd/soroban-cli/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/stellar-cli" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "21.1.1" +version = "21.2.0" edition = "2021" rust-version.workspace = true autobins = false diff --git a/cmd/soroban-cli/src/commands/events.rs b/cmd/soroban-cli/src/commands/events.rs index 135f2f976..e9f3ba645 100644 --- a/cmd/soroban-cli/src/commands/events.rs +++ b/cmd/soroban-cli/src/commands/events.rs @@ -12,8 +12,9 @@ use crate::rpc; #[derive(Parser, Debug, Clone)] #[group(skip)] pub struct Cmd { + #[allow(clippy::doc_markdown)] /// The first ledger sequence number in the range to pull events - /// + /// https://developers.stellar.org/docs/learn/encyclopedia/network-configuration/ledger-headers#ledger-sequence #[arg(long, conflicts_with = "cursor", required_unless_present = "cursor")] start_ledger: Option, /// The cursor corresponding to the start of the event range. diff --git a/cmd/soroban-cli/src/commands/network/container.rs b/cmd/soroban-cli/src/commands/network/container.rs index 16e5d73be..511c0e11b 100644 --- a/cmd/soroban-cli/src/commands/network/container.rs +++ b/cmd/soroban-cli/src/commands/network/container.rs @@ -10,19 +10,17 @@ pub type StopCmd = stop::Cmd; #[derive(Debug, clap::Subcommand)] pub enum Cmd { - /// Tail logs of a running network container + /// Get logs from a running network container Logs(logs::Cmd), - /// Start network - /// /// Start a container running a Stellar node, RPC, API, and friendbot (faucet). /// - /// `stellar network start NETWORK [OPTIONS]` + /// `stellar network container start NETWORK [OPTIONS]` /// /// By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: /// - /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc` + /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` Start(start::Cmd), - /// Stop a network started with `network container start`. For example, if you ran `network container start local`, you can use `network container stop local` to stop it. + /// Stop a network container started with `network container start`. Stop(stop::Cmd), } diff --git a/cmd/soroban-cli/src/commands/network/container/logs.rs b/cmd/soroban-cli/src/commands/network/container/logs.rs index e37ceb098..99b36af9b 100644 --- a/cmd/soroban-cli/src/commands/network/container/logs.rs +++ b/cmd/soroban-cli/src/commands/network/container/logs.rs @@ -1,8 +1,8 @@ use futures_util::TryStreamExt; -use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, DOCKER_HOST_HELP, -}; +use crate::commands::network::container::shared::Error as ConnectionError; + +use super::shared::{Args, Name}; #[derive(thiserror::Error, Debug)] pub enum Error { @@ -15,17 +15,17 @@ pub enum Error { #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { - /// Network to tail - pub network: Network, + #[command(flatten)] + pub container_args: Args, - #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] - pub docker_host: Option, + /// Container to get logs from + pub name: String, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = format!("stellar-{}", self.network); - let docker = connect_to_docker(&self.docker_host).await?; + let container_name = Name(self.name.clone()).get_internal_container_name(); + let docker = self.container_args.connect_to_docker().await?; let logs_stream = &mut docker.logs( &container_name, Some(bollard::container::LogsOptions { diff --git a/cmd/soroban-cli/src/commands/network/container/shared.rs b/cmd/soroban-cli/src/commands/network/container/shared.rs index 9da8a1bea..f819f3ed3 100644 --- a/cmd/soroban-cli/src/commands/network/container/shared.rs +++ b/cmd/soroban-cli/src/commands/network/container/shared.rs @@ -31,7 +31,81 @@ pub enum Error { UnsupportedURISchemeError { uri: String }, } -#[derive(ValueEnum, Debug, Clone, PartialEq)] +#[derive(Debug, clap::Parser, Clone)] +pub struct Args { + /// Optional argument to override the default docker host. This is useful when you are using a non-standard docker host path for your Docker-compatible container runtime, e.g. Docker Desktop defaults to $HOME/.docker/run/docker.sock instead of /var/run/docker.sock + #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] + pub docker_host: Option, +} + +impl Args { + pub(crate) fn get_additional_flags(&self) -> String { + self.docker_host + .as_ref() + .map(|docker_host| format!("--docker-host {docker_host}")) + .unwrap_or_default() + } + + pub(crate) async fn connect_to_docker(&self) -> Result { + // if no docker_host is provided, use the default docker host: + // "unix:///var/run/docker.sock" on unix machines + // "npipe:////./pipe/docker_engine" on windows machines + let host = self.docker_host.as_ref().map_or_else( + || DEFAULT_DOCKER_HOST.to_string(), + std::string::ToString::to_string, + ); + + // this is based on the `connect_with_defaults` method which has not yet been released in the bollard crate + // https://github.com/fussybeaver/bollard/blob/0972b1aac0ad5c08798e100319ddd0d2ee010365/src/docker.rs#L660 + let connection = match host.clone() { + // if tcp or http, use connect_with_http_defaults + // if unix and host starts with "unix://" use connect_with_unix + // if windows and host starts with "npipe://", use connect_with_named_pipe + // else default to connect_with_unix + h if h.starts_with("tcp://") || h.starts_with("http://") => { + Docker::connect_with_http_defaults() + } + #[cfg(unix)] + h if h.starts_with("unix://") => { + Docker::connect_with_unix(&h, DEFAULT_TIMEOUT, API_DEFAULT_VERSION) + } + #[cfg(windows)] + h if h.starts_with("npipe://") => { + Docker::connect_with_named_pipe(&h, DEFAULT_TIMEOUT, API_DEFAULT_VERSION) + } + _ => { + return Err(Error::UnsupportedURISchemeError { + uri: host.to_string(), + }); + } + }?; + + match check_docker_connection(&connection).await { + Ok(()) => Ok(connection), + // If we aren't able to connect with the defaults, or with the provided docker_host + // try to connect with the default docker desktop socket since that is a common use case for devs + #[allow(unused_variables)] + Err(e) => { + // if on unix, try to connect to the default docker desktop socket + #[cfg(unix)] + { + let docker_desktop_connection = try_docker_desktop_socket(&host)?; + match check_docker_connection(&docker_desktop_connection).await { + Ok(()) => Ok(docker_desktop_connection), + Err(err) => Err(err)?, + } + } + + #[cfg(windows)] + { + Err(e)? + } + } + } + } +} + +#[derive(ValueEnum, Debug, Copy, Clone, PartialEq)] pub enum Network { Local, Testnet, @@ -52,61 +126,14 @@ impl fmt::Display for Network { } } -pub async fn connect_to_docker(docker_host: &Option) -> Result { - // if no docker_host is provided, use the default docker host: - // "unix:///var/run/docker.sock" on unix machines - // "npipe:////./pipe/docker_engine" on windows machines - - let host = docker_host - .clone() - .unwrap_or(DEFAULT_DOCKER_HOST.to_string()); - - // this is based on the `connect_with_defaults` method which has not yet been released in the bollard crate - // https://github.com/fussybeaver/bollard/blob/0972b1aac0ad5c08798e100319ddd0d2ee010365/src/docker.rs#L660 - let connection = match host.clone() { - // if tcp or http, use connect_with_http_defaults - // if unix and host starts with "unix://" use connect_with_unix - // if windows and host starts with "npipe://", use connect_with_named_pipe - // else default to connect_with_unix - h if h.starts_with("tcp://") || h.starts_with("http://") => { - Docker::connect_with_http_defaults() - } - #[cfg(unix)] - h if h.starts_with("unix://") => { - Docker::connect_with_unix(&h, DEFAULT_TIMEOUT, API_DEFAULT_VERSION) - } - #[cfg(windows)] - h if h.starts_with("npipe://") => { - Docker::connect_with_named_pipe(&h, DEFAULT_TIMEOUT, API_DEFAULT_VERSION) - } - _ => { - return Err(Error::UnsupportedURISchemeError { - uri: host.to_string(), - }); - } - }?; - - match check_docker_connection(&connection).await { - Ok(()) => Ok(connection), - // If we aren't able to connect with the defaults, or with the provided docker_host - // try to connect with the default docker desktop socket since that is a common use case for devs - #[allow(unused_variables)] - Err(e) => { - // if on unix, try to connect to the default docker desktop socket - #[cfg(unix)] - { - let docker_desktop_connection = try_docker_desktop_socket(&host)?; - match check_docker_connection(&docker_desktop_connection).await { - Ok(()) => Ok(docker_desktop_connection), - Err(err) => Err(err)?, - } - } +pub struct Name(pub String); +impl Name { + pub fn get_internal_container_name(&self) -> String { + format!("stellar-{}", self.0) + } - #[cfg(windows)] - { - Err(e)? - } - } + pub fn get_external_container_name(&self) -> String { + self.0.to_string() } } diff --git a/cmd/soroban-cli/src/commands/network/container/start.rs b/cmd/soroban-cli/src/commands/network/container/start.rs index cc9619f1d..46348c297 100644 --- a/cmd/soroban-cli/src/commands/network/container/start.rs +++ b/cmd/soroban-cli/src/commands/network/container/start.rs @@ -7,9 +7,9 @@ use bollard::{ }; use futures_util::TryStreamExt; -use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, DOCKER_HOST_HELP, -}; +use crate::commands::network::container::shared::{Error as ConnectionError, Network}; + +use super::shared::{Args, Name}; const DEFAULT_PORT_MAPPING: &str = "8000:8000"; const DOCKER_IMAGE: &str = "docker.io/stellar/quickstart"; @@ -17,19 +17,23 @@ const DOCKER_IMAGE: &str = "docker.io/stellar/quickstart"; #[derive(thiserror::Error, Debug)] pub enum Error { #[error("⛔ ️Failed to connect to docker: {0}")] - ConnectionError(#[from] ConnectionError), + DockerConnectionFailed(#[from] ConnectionError), #[error("⛔ ️Failed to create container: {0}")] - BollardErr(#[from] bollard::errors::Error), + CreateContainerFailed(#[from] bollard::errors::Error), } #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { + #[command(flatten)] + pub container_args: Args, + /// Network to start pub network: Network, - #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] - pub docker_host: Option, + /// Optional argument to specify the container name + #[arg(long)] + pub name: Option, /// Optional argument to specify the limits for the local network only #[arg(short = 'l', long)] @@ -51,137 +55,152 @@ pub struct Cmd { impl Cmd { pub async fn run(&self) -> Result<(), Error> { println!("ℹ️ Starting {} network", &self.network); - run_docker_command(self).await + self.run_docker_command().await } -} -async fn run_docker_command(cmd: &Cmd) -> Result<(), Error> { - let docker = connect_to_docker(&cmd.docker_host).await?; - - let image = get_image_name(cmd); - docker - .create_image( - Some(CreateImageOptions { - from_image: image.clone(), + async fn run_docker_command(&self) -> Result<(), Error> { + let docker = self.container_args.connect_to_docker().await?; + + let image = self.get_image_name(); + docker + .create_image( + Some(CreateImageOptions { + from_image: image.clone(), + ..Default::default() + }), + None, + None, + ) + .try_collect::>() + .await?; + + let config = Config { + image: Some(image), + cmd: Some(self.get_container_args()), + attach_stdout: Some(true), + attach_stderr: Some(true), + host_config: Some(HostConfig { + auto_remove: Some(true), + port_bindings: Some(self.get_port_mapping()), ..Default::default() }), - None, - None, - ) - .try_collect::>() - .await?; - - let container_args = get_container_args(cmd); - let port_mapping = get_port_mapping(cmd); - - let config = Config { - image: Some(image), - cmd: Some(container_args), - attach_stdout: Some(true), - attach_stderr: Some(true), - host_config: Some(HostConfig { - auto_remove: Some(true), - port_bindings: Some(port_mapping), ..Default::default() - }), - ..Default::default() - }; - - let container_name = format!("stellar-{}", cmd.network); - let create_container_response = docker - .create_container( - Some(CreateContainerOptions { - name: container_name.clone(), - ..Default::default() - }), - config, - ) - .await?; - - docker - .start_container( - &create_container_response.id, - None::>, - ) - .await?; - println!("✅ Container started: {container_name}"); - let stop_message = format!( - "ℹ️ To stop this container run: stellar network stop {network} {additional_flags}", - network = &cmd.network, - additional_flags = if cmd.docker_host.is_some() { - format!("--docker-host {}", cmd.docker_host.as_ref().unwrap()) - } else { - String::new() + }; + + let create_container_response = docker + .create_container( + Some(CreateContainerOptions { + name: self.container_name().get_internal_container_name(), + ..Default::default() + }), + config, + ) + .await?; + + docker + .start_container( + &create_container_response.id, + None::>, + ) + .await?; + println!( + "✅ Container started: {}", + self.container_name().get_external_container_name() + ); + self.print_log_message(); + self.print_stop_message(); + Ok(()) + } + + fn get_image_name(&self) -> String { + // this can be overriden with the `-t` flag + let mut image_tag = match &self.network { + Network::Pubnet => "latest", + Network::Futurenet => "future", + _ => "testing", // default to testing for local and testnet + }; + + if let Some(image_override) = &self.image_tag_override { + println!( + "Overriding docker image tag to use '{image_override}' instead of '{image_tag}'" + ); + image_tag = image_override; } - ); - println!("{stop_message}"); - Ok(()) -} + format!("{DOCKER_IMAGE}:{image_tag}") + } -fn get_container_args(cmd: &Cmd) -> Vec { - [ - format!("--{}", cmd.network), - "--enable rpc,horizon".to_string(), - get_protocol_version_arg(cmd), - get_limits_arg(cmd), - ] - .iter() - .filter(|&s| !s.is_empty()) - .cloned() - .collect() -} + fn get_container_args(&self) -> Vec { + [ + format!("--{}", self.network), + "--enable rpc,horizon".to_string(), + self.get_protocol_version_arg(), + self.get_limits_arg(), + ] + .iter() + .filter(|&s| !s.is_empty()) + .cloned() + .collect() + } + + // The port mapping in the bollard crate is formatted differently than the docker CLI. In the docker CLI, we usually specify exposed ports as `-p HOST_PORT:CONTAINER_PORT`. But with the bollard crate, it is expecting the port mapping to be a map of the container port (with the protocol) to the host port. + fn get_port_mapping(&self) -> HashMap>> { + let mut port_mapping_hash = HashMap::new(); + for port_mapping in &self.ports_mapping { + let ports_vec: Vec<&str> = port_mapping.split(':').collect(); + let from_port = ports_vec[0]; + let to_port = ports_vec[1]; + + port_mapping_hash.insert( + format!("{to_port}/tcp"), + Some(vec![PortBinding { + host_ip: None, + host_port: Some(from_port.to_string()), + }]), + ); + } -fn get_image_name(cmd: &Cmd) -> String { - // this can be overriden with the `-t` flag - let mut image_tag = match cmd.network { - Network::Pubnet => "latest", - Network::Futurenet => "future", - _ => "testing", // default to testing for local and testnet - }; - - if let Some(image_override) = &cmd.image_tag_override { - println!("Overriding docker image tag to use '{image_override}' instead of '{image_tag}'"); - image_tag = image_override; + port_mapping_hash } - format!("{DOCKER_IMAGE}:{image_tag}") -} + fn container_name(&self) -> Name { + Name(self.name.clone().unwrap_or(self.network.to_string())) + } -// The port mapping in the bollard crate is formatted differently than the docker CLI. In the docker CLI, we usually specify exposed ports as `-p HOST_PORT:CONTAINER_PORT`. But with the bollard crate, it is expecting the port mapping to be a map of the container port (with the protocol) to the host port. -fn get_port_mapping(cmd: &Cmd) -> HashMap>> { - let mut port_mapping_hash = HashMap::new(); - for port_mapping in &cmd.ports_mapping { - let ports_vec: Vec<&str> = port_mapping.split(':').collect(); - let from_port = ports_vec[0]; - let to_port = ports_vec[1]; - - port_mapping_hash.insert( - format!("{to_port}/tcp"), - Some(vec![PortBinding { - host_ip: None, - host_port: Some(from_port.to_string()), - }]), + fn print_log_message(&self) { + let log_message = format!( + "ℹ️ To see the logs for this container run: stellar network container logs {container_name} {additional_flags}", + container_name = self.container_name().get_external_container_name(), + additional_flags = self.container_args.get_additional_flags(), ); + println!("{log_message}"); } - port_mapping_hash -} + fn print_stop_message(&self) { + let stop_message = + format!( + "ℹ️ To stop this container run: stellar network container stop {container_name} {additional_flags}", + container_name = self.container_name().get_external_container_name(), + additional_flags = self.container_args.get_additional_flags(), + ); + println!("{stop_message}"); + } -fn get_protocol_version_arg(cmd: &Cmd) -> String { - if cmd.network == Network::Local && cmd.protocol_version.is_some() { - let version = cmd.protocol_version.as_ref().unwrap(); - format!("--protocol-version {version}") - } else { - String::new() + fn get_protocol_version_arg(&self) -> String { + if self.network == Network::Local && self.protocol_version.is_some() { + let version = self.protocol_version.as_ref().unwrap(); + format!("--protocol-version {version}") + } else { + String::new() + } } -} -fn get_limits_arg(cmd: &Cmd) -> String { - if cmd.network == Network::Local && cmd.limits.is_some() { - let limits = cmd.limits.as_ref().unwrap(); - format!("--limits {limits}") - } else { - String::new() + fn get_limits_arg(&self) -> String { + if self.network == Network::Local && self.limits.is_some() { + let limits = self.limits.as_ref().unwrap(); + format!("--limits {limits}") + } else { + String::new() + } } } diff --git a/cmd/soroban-cli/src/commands/network/container/stop.rs b/cmd/soroban-cli/src/commands/network/container/stop.rs index c511b5e4d..733c86436 100644 --- a/cmd/soroban-cli/src/commands/network/container/stop.rs +++ b/cmd/soroban-cli/src/commands/network/container/stop.rs @@ -1,29 +1,58 @@ -use crate::commands::network::container::shared::{ - connect_to_docker, Error as ConnectionError, Network, DOCKER_HOST_HELP, -}; +use crate::commands::network::container::shared::Error as BollardConnectionError; + +use super::shared::{Args, Name}; #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("Failed to stop container: {0}")] - StopContainerError(#[from] ConnectionError), + #[error("⛔ Failed to connect to docker: {0}")] + DockerConnectionFailed(#[from] BollardConnectionError), + + #[error("⛔ Container {container_name} not found")] + ContainerNotFound { + container_name: String, + #[source] + source: bollard::errors::Error, + }, + + #[error("⛔ Failed to stop container: {0}")] + ContainerStopFailed(#[from] bollard::errors::Error), } #[derive(Debug, clap::Parser, Clone)] pub struct Cmd { - /// Network to stop - pub network: Network, + #[command(flatten)] + pub container_args: Args, - #[arg(short = 'd', long, help = DOCKER_HOST_HELP, env = "DOCKER_HOST")] - pub docker_host: Option, + /// Container to stop + pub name: String, } impl Cmd { pub async fn run(&self) -> Result<(), Error> { - let container_name = format!("stellar-{}", self.network); - let docker = connect_to_docker(&self.docker_host).await?; - println!("ℹ️ Stopping container: {container_name}"); - docker.stop_container(&container_name, None).await.unwrap(); - println!("✅ Container stopped: {container_name}"); + let container_name = Name(self.name.clone()); + let docker = self.container_args.connect_to_docker().await?; + println!( + "ℹ️ Stopping container: {}", + container_name.get_external_container_name() + ); + docker + .stop_container(&container_name.get_internal_container_name(), None) + .await + .map_err(|e| { + let msg = e.to_string(); + if msg.contains("No such container") { + Error::ContainerNotFound { + container_name: container_name.get_external_container_name(), + source: e, + } + } else { + Error::ContainerStopFailed(e) + } + })?; + println!( + "✅ Container stopped: {}", + container_name.get_external_container_name() + ); Ok(()) } } diff --git a/cmd/soroban-cli/src/commands/network/mod.rs b/cmd/soroban-cli/src/commands/network/mod.rs index 435492295..1c34f92c8 100644 --- a/cmd/soroban-cli/src/commands/network/mod.rs +++ b/cmd/soroban-cli/src/commands/network/mod.rs @@ -38,7 +38,7 @@ pub enum Cmd { /// /// By default, when starting a testnet container, without any optional arguments, it will run the equivalent of the following docker command: /// - /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable-soroban-rpc` + /// `docker run --rm -p 8000:8000 --name stellar stellar/quickstart:testing --testnet --enable rpc,horizon` Start(container::StartCmd), /// ⚠️ Deprecated: use `stellar container stop` instead /// diff --git a/cmd/soroban-cli/src/commands/tx/hash.rs b/cmd/soroban-cli/src/commands/tx/hash.rs new file mode 100644 index 000000000..d5b2c42e6 --- /dev/null +++ b/cmd/soroban-cli/src/commands/tx/hash.rs @@ -0,0 +1,33 @@ +use crate::{commands::global, utils::transaction_hash}; +use hex; + +#[derive(thiserror::Error, Debug)] +pub enum Error { + #[error(transparent)] + TxEnvelopeFromStdin(#[from] super::xdr::Error), + #[error(transparent)] + XdrToBase64(#[from] soroban_env_host::xdr::Error), + #[error(transparent)] + Config(#[from] super::super::network::Error), +} + +// Command to return the transaction hash submitted to a network +/// e.g. `cat file.txt | soroban tx hash` +#[derive(Debug, clap::Parser, Clone, Default)] +#[group(skip)] +pub struct Cmd { + #[clap(flatten)] + pub network: super::super::network::Args, +} + +impl Cmd { + pub fn run(&self, global_args: &global::Args) -> Result<(), Error> { + let tx = super::xdr::unwrap_envelope_v1(super::xdr::tx_envelope_from_stdin()?)?; + let network = &self.network.get(&global_args.locator)?; + println!( + "{}", + hex::encode(transaction_hash(&tx, &network.network_passphrase)?) + ); + Ok(()) + } +} diff --git a/cmd/soroban-cli/src/commands/tx/mod.rs b/cmd/soroban-cli/src/commands/tx/mod.rs index 48161e3c7..59f07228a 100644 --- a/cmd/soroban-cli/src/commands/tx/mod.rs +++ b/cmd/soroban-cli/src/commands/tx/mod.rs @@ -2,6 +2,7 @@ use clap::Parser; use super::global; +pub mod hash; pub mod simulate; pub mod xdr; @@ -9,6 +10,8 @@ pub mod xdr; pub enum Cmd { /// Simulate a transaction envelope from stdin Simulate(simulate::Cmd), + /// Calculate the hash of a transaction envelope from stdin + Hash(hash::Cmd), } #[derive(thiserror::Error, Debug)] @@ -16,12 +19,16 @@ pub enum Error { /// An error during the simulation #[error(transparent)] Simulate(#[from] simulate::Error), + /// An error during hash calculation + #[error(transparent)] + Hash(#[from] hash::Error), } impl Cmd { pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> { match self { Cmd::Simulate(cmd) => cmd.run(global_args).await?, + Cmd::Hash(cmd) => cmd.run(global_args)?, }; Ok(()) } diff --git a/cmd/soroban-cli/src/key.rs b/cmd/soroban-cli/src/key.rs index 7a0ccb844..885295936 100644 --- a/cmd/soroban-cli/src/key.rs +++ b/cmd/soroban-cli/src/key.rs @@ -56,7 +56,7 @@ pub struct Args { )] pub wasm_hash: Option, /// Storage entry durability - #[arg(long, value_enum, required = true, default_value = "persistent")] + #[arg(long, value_enum, default_value = "persistent")] pub durability: Durability, } diff --git a/cmd/stellar-cli/Cargo.toml b/cmd/stellar-cli/Cargo.toml index 86d51a8dc..c5d93252b 100644 --- a/cmd/stellar-cli/Cargo.toml +++ b/cmd/stellar-cli/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/stellar/stellar-cli" authors = ["Stellar Development Foundation "] license = "Apache-2.0" readme = "README.md" -version = "21.1.1" +version = "21.2.0" edition = "2021" rust-version.workspace = true autobins = false