From 413056032ca878ea0a7115b8508c325244fbf9f1 Mon Sep 17 00:00:00 2001 From: Patrick Kuo Date: Thu, 30 Jun 2022 19:01:14 +0100 Subject: [PATCH] Unify sui, wallet, key-tool, sui-move binaries (#2786) * * unified sui, wallet, key-tool, sui-move binaries * moved benchmark bins to sui-benchmark crate * crate dependencies clean up * name changes * update wallet.md some minor refactoring * update wallet -> Sui CLI client to avoid confusion with the new wallet plugin * rename wallet.md to cli-client.md * minor fixes * revert accidental checkin * fixup after rebase * Make small edits directly to renamed cli-client file * Make small edits directly to install doc * Fix typo in Chapter 3 - Immutable Objects * Lowercase "client" for consistency * Qualify client command with sui * Capitalize Sui client, add fullnode ref * fix docker file Co-authored-by: Clay-Mysten <100217682+Clay-Mysten@users.noreply.github.com> --- Cargo.lock | 808 ++++++++++-- Cargo.toml | 1 + README.md | 2 +- crates/generate-json-rpc-spec/src/main.rs | 32 +- crates/sui-benchmark/Cargo.toml | 39 + .../{sui => sui-benchmark}/src/benchmark.rs | 0 .../src/benchmark/bench_types.rs | 3 +- .../src/benchmark/load_generator.rs | 0 .../src/benchmark/transaction_creator.rs | 0 .../src/benchmark/validator_preparer.rs | 0 .../{sui => sui-benchmark}/src/bin/bench.rs | 4 +- .../src/bin/bench_configure.rs | 0 .../src/bin/remote_load_generator.rs | 11 +- crates/sui-benchmark/src/lib.rs | 4 + crates/sui-cluster-test/Cargo.toml | 1 + crates/sui-cluster-test/src/main.rs | 17 +- crates/sui-config/src/lib.rs | 3 +- crates/sui-faucet/src/faucet/simple_faucet.rs | 2 +- crates/sui-faucet/src/main.rs | 8 +- crates/sui-gateway/Cargo.toml | 26 +- .../rpc-server.rs => sui-gateway/src/main.rs} | 2 +- .../src/unit_tests/rpc_server_tests.rs | 15 +- crates/sui-json-rpc-api/Cargo.toml | 1 + crates/sui-json-rpc-api/src/client.rs | 8 +- .../{sui => sui-json-rpc-api}/src/keystore.rs | 0 crates/sui-json-rpc-api/src/lib.rs | 1 + crates/sui/Cargo.toml | 56 +- crates/sui/src/bin/key_tool.rs | 39 - crates/sui/src/bin/sui.rs | 31 - crates/sui/src/bin/wallet.rs | 248 ---- ...{wallet_commands.rs => client_commands.rs} | 136 +- crates/sui/src/config/mod.rs | 8 +- crates/sui/src/console.rs | 137 ++ crates/sui/src/keytool.rs | 92 ++ crates/sui/src/lib.rs | 7 +- crates/sui/src/main.rs | 34 + crates/sui/src/sui_commands.rs | 224 +++- .../sui/src/{bin/sui-move.rs => sui_move.rs} | 27 +- crates/sui/src/unit_tests/cli_tests.rs | 193 +-- crates/sui/tests/full_node_tests.rs | 23 +- crates/test-utils/src/network.rs | 26 +- doc/src/build/cli-client.md | 1126 ++++++++++++++++ doc/src/build/index.md | 4 +- doc/src/build/install.md | 18 +- doc/src/build/json-rpc.md | 22 +- doc/src/build/move.md | 16 +- .../ch1-object-basics.md | 18 +- .../ch2-using-objects.md | 18 +- .../ch3-immutable-objects.md | 22 +- .../ch5-child-objects.md | 16 +- doc/src/build/pubsub.md | 8 +- doc/src/build/wallet.md | 1143 ----------------- doc/src/contribute/faq.md | 4 +- doc/src/contribute/observability.md | 2 +- doc/src/explore/devnet.md | 30 +- doc/src/explore/tutorials.md | 50 +- doc/src/learn/architecture/validators.md | 2 +- doc/src/learn/index.md | 6 +- doc/src/learn/sui-glossary.md | 8 +- doc/utils/sui-setup.sh | 2 +- docker/sui-tools/Dockerfile | 9 +- docker/sui-tools/build.sh | 2 +- 62 files changed, 2690 insertions(+), 2105 deletions(-) create mode 100644 crates/sui-benchmark/Cargo.toml rename crates/{sui => sui-benchmark}/src/benchmark.rs (100%) rename crates/{sui => sui-benchmark}/src/benchmark/bench_types.rs (99%) rename crates/{sui => sui-benchmark}/src/benchmark/load_generator.rs (100%) rename crates/{sui => sui-benchmark}/src/benchmark/transaction_creator.rs (100%) rename crates/{sui => sui-benchmark}/src/benchmark/validator_preparer.rs (100%) rename crates/{sui => sui-benchmark}/src/bin/bench.rs (95%) rename crates/{sui => sui-benchmark}/src/bin/bench_configure.rs (100%) rename crates/{sui => sui-benchmark}/src/bin/remote_load_generator.rs (92%) create mode 100644 crates/sui-benchmark/src/lib.rs rename crates/{sui/src/bin/rpc-server.rs => sui-gateway/src/main.rs} (98%) rename crates/{sui => sui-gateway}/src/unit_tests/rpc_server_tests.rs (93%) rename crates/{sui => sui-json-rpc-api}/src/keystore.rs (100%) delete mode 100644 crates/sui/src/bin/key_tool.rs delete mode 100644 crates/sui/src/bin/sui.rs delete mode 100644 crates/sui/src/bin/wallet.rs rename crates/sui/src/{wallet_commands.rs => client_commands.rs} (88%) create mode 100644 crates/sui/src/console.rs create mode 100644 crates/sui/src/keytool.rs create mode 100644 crates/sui/src/main.rs rename crates/sui/src/{bin/sui-move.rs => sui_move.rs} (73%) create mode 100644 doc/src/build/cli-client.md delete mode 100644 doc/src/build/wallet.md diff --git a/Cargo.lock b/Cargo.lock index 1876fb0f8d9..cff7435d24e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -992,13 +992,28 @@ dependencies = [ "memchr", ] +[[package]] +name = "config" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "arc-swap", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "multiaddr", + "serde 1.0.137", + "serde_json", + "thiserror", + "tracing", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", +] + [[package]] name = "config" version = "0.1.0" source = "git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d#3cf68183b22acfe014118ef2713d5094159f2f4d" dependencies = [ "arc-swap", - "crypto", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "multiaddr", "serde 1.0.137", "serde_json", @@ -1023,6 +1038,31 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "consensus" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "arc-swap", + "bincode", + "blake2", + "bytes", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "dag 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "match_opt", + "rand 0.7.3", + "rocksdb", + "serde 1.0.137", + "serde_bytes", + "thiserror", + "tokio", + "tracing", + "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", +] + [[package]] name = "consensus" version = "0.1.0" @@ -1032,9 +1072,9 @@ dependencies = [ "bincode", "blake2", "bytes", - "config 0.1.0", - "crypto", - "dag", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "dag 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "match_opt", "rand 0.7.3", "rocksdb", @@ -1044,7 +1084,7 @@ dependencies = [ "tokio", "tracing", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "types", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", ] @@ -1346,6 +1386,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "crypto" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "base64ct", + "blake2", + "blst", + "ed25519-dalek", + "eyre", + "once_cell", + "rand 0.7.3", + "readonly", + "serde 1.0.137", + "serde_bytes", + "signature", + "tokio", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "zeroize", +] + [[package]] name = "crypto" version = "0.1.0" @@ -1447,13 +1508,30 @@ dependencies = [ "zeroize", ] +[[package]] +name = "dag" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "arc-swap", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "dashmap", + "either", + "itertools", + "once_cell", + "rayon", + "serde 1.0.137", + "thiserror", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", +] + [[package]] name = "dag" version = "0.1.0" source = "git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d#3cf68183b22acfe014118ef2713d5094159f2f4d" dependencies = [ "arc-swap", - "crypto", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "dashmap", "either", "itertools", @@ -1917,6 +1995,35 @@ version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" +[[package]] +name = "executor" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "async-trait", + "bincode", + "blake2", + "bytes", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "consensus 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "futures", + "multiaddr", + "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "primary 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "rocksdb", + "serde 1.0.137", + "thiserror", + "tokio", + "tokio-util", + "tonic", + "tracing", + "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "worker 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", +] + [[package]] name = "executor" version = "0.1.0" @@ -1926,13 +2033,13 @@ dependencies = [ "bincode", "blake2", "bytes", - "config 0.1.0", - "consensus", - "crypto", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "consensus 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "futures", "multiaddr", "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "primary", + "primary 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "rocksdb", "serde 1.0.137", "thiserror", @@ -1941,8 +2048,8 @@ dependencies = [ "tonic", "tracing", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "types", - "worker", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "worker 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", ] @@ -4142,6 +4249,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b420f638f07fe83056b55ea190bb815f609ec5a35e7017884a10f78839c9e" +[[package]] +name = "network" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "async-trait", + "backoff", + "bytes", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "futures", + "multiaddr", + "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "rand 0.7.3", + "thiserror", + "tokio", + "tokio-util", + "tonic", + "tracing", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", +] + [[package]] name = "network" version = "0.1.0" @@ -4150,7 +4279,7 @@ dependencies = [ "async-trait", "backoff", "bytes", - "crypto", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "futures", "multiaddr", "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", @@ -4160,7 +4289,7 @@ dependencies = [ "tokio-util", "tonic", "tracing", - "types", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", ] @@ -4217,6 +4346,39 @@ dependencies = [ "memoffset", ] +[[package]] +name = "node" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "anyhow", + "arc-swap", + "async-trait", + "bincode", + "bytes", + "cfg-if 1.0.0", + "clap 2.34.0", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "consensus 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "executor 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "futures", + "primary 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "rand 0.7.3", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "tracing-log", + "tracing-subscriber 0.3.11", + "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "url", + "worker 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", +] + [[package]] name = "node" version = "0.1.0" @@ -4229,12 +4391,12 @@ dependencies = [ "bytes", "cfg-if 1.0.0", "clap 2.34.0", - "config 0.1.0", - "consensus", - "crypto", - "executor", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "consensus 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "executor 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "futures", - "primary", + "primary 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "rand 0.7.3", "thiserror", "tokio", @@ -4244,9 +4406,9 @@ dependencies = [ "tracing-log", "tracing-subscriber 0.3.11", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "types", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "url", - "worker", + "worker 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", ] @@ -4940,6 +5102,41 @@ dependencies = [ "syn 1.0.96", ] +[[package]] +name = "primary" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "async-recursion", + "async-trait", + "base64", + "bincode", + "blake2", + "bytes", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "consensus 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "derive_builder", + "ed25519-dalek", + "futures", + "itertools", + "multiaddr", + "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "network 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "prost", + "rand 0.7.3", + "serde 1.0.137", + "thiserror", + "tokio", + "tokio-util", + "tonic", + "tower", + "tracing", + "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", +] + [[package]] name = "primary" version = "0.1.0" @@ -4951,16 +5148,16 @@ dependencies = [ "bincode", "blake2", "bytes", - "config 0.1.0", - "consensus", - "crypto", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "consensus 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "derive_builder", "ed25519-dalek", "futures", "itertools", "multiaddr", "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "network", + "network 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "prost", "rand 0.7.3", "serde 1.0.137", @@ -4971,7 +5168,7 @@ dependencies = [ "tower", "tracing", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "types", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", ] @@ -6383,71 +6580,35 @@ version = "0.5.0" dependencies = [ "anyhow", "async-trait", - "base64ct", - "bcs", - "bytes", "clap 3.1.18", "colored", - "dirs", - "ed25519-dalek", "futures", - "hex", "jsonrpsee", - "jsonrpsee-core", - "jsonrpsee-proc-macros", - "move-binary-format", - "move-bytecode-utils", - "move-bytecode-verifier", "move-core-types", "move-package", "move-unit-test", - "multiaddr", - "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=94d7da89f6a52d7f60a9802b0a03147a9c89c3e4)", - "node", - "num_cpus", - "once_cell", - "parking_lot 0.12.1", - "pretty_assertions", - "prometheus", "rand 0.7.3", - "rayon", - "rocksdb", "rustyline", "rustyline-derive", - "schemars", "serde 1.0.137", - "serde-name", - "serde-value", "serde_json", "serde_with", "shell-words", - "strum", - "strum_macros", - "sui-adapter", "sui-config", "sui-core", "sui-framework", "sui-gateway", "sui-json", - "sui-json-rpc", "sui-json-rpc-api", - "sui-network", "sui-node", - "sui-open-rpc", - "sui-open-rpc-macros", "sui-quorum-driver", - "sui-storage", "sui-swarm", "sui-types", - "sui-verifier", "telemetry-subscribers", "tempfile", "test-utils", "tokio", - "tokio-util", - "toml", "tracing", - "tracing-subscriber 0.3.11", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=94d7da89f6a52d7f60a9802b0a03147a9c89c3e4)", "unescape", "workspace-hack 0.1.0", @@ -6484,6 +6645,36 @@ dependencies = [ "workspace-hack 0.1.0", ] +[[package]] +name = "sui-benchmark" +version = "0.0.0" +dependencies = [ + "anyhow", + "bcs", + "clap 3.1.18", + "futures", + "move-core-types", + "multiaddr", + "node 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "num_cpus", + "prometheus", + "rayon", + "rocksdb", + "serde 1.0.137", + "serde_json", + "serde_with", + "strum", + "strum_macros", + "sui-config", + "sui-core", + "sui-types", + "tempfile", + "tokio", + "tracing", + "tracing-subscriber 0.3.11", + "workspace-hack 0.1.0", +] + [[package]] name = "sui-cluster-test" version = "0.1.0" @@ -6495,6 +6686,7 @@ dependencies = [ "serde_json", "serde_with", "sui", + "sui-config", "sui-core", "sui-faucet", "sui-json", @@ -6515,8 +6707,8 @@ dependencies = [ "arc-swap", "base64ct", "bcs", - "config 0.1.0", - "crypto", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "debug-ignore", "dirs", "move-binary-format", @@ -6547,11 +6739,11 @@ dependencies = [ "chrono", "clap 3.1.18", "colored", - "crypto", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "curve25519-dalek", "ed25519-dalek", "either", - "executor", + "executor 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "futures", "hex", "itertools", @@ -6563,7 +6755,7 @@ dependencies = [ "move-vm-types", "multiaddr", "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=94d7da89f6a52d7f60a9802b0a03147a9c89c3e4)", - "node", + "node 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "once_cell", "parking_lot 0.12.1", "pretty_assertions", @@ -6598,7 +6790,7 @@ dependencies = [ "tokio-util", "tracing", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=94d7da89f6a52d7f60a9802b0a03147a9c89c3e4)", - "types", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "workspace-hack 0.1.0", ] @@ -6675,30 +6867,22 @@ version = "0.0.0" dependencies = [ "anyhow", "async-trait", - "ed25519-dalek", + "clap 3.1.18", "futures", - "jsonrpsee", - "jsonrpsee-core", - "jsonrpsee-proc-macros", - "move-bytecode-utils", - "move-core-types", "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=94d7da89f6a52d7f60a9802b0a03147a9c89c3e4)", - "once_cell", "prometheus", - "schemars", "serde 1.0.137", - "serde_json", - "serde_with", - "strum", - "strum_macros", "sui-config", "sui-core", + "sui-framework", "sui-json", + "sui-json-rpc", "sui-json-rpc-api", - "sui-open-rpc", + "sui-node", "sui-types", + "telemetry-subscribers", + "test-utils", "tokio", - "tokio-stream", "tracing", "workspace-hack 0.1.0", ] @@ -6757,6 +6941,7 @@ dependencies = [ "anyhow", "async-trait", "colored", + "ed25519-dalek", "either", "itertools", "jsonrpsee", @@ -6954,11 +7139,11 @@ dependencies = [ "base64ct", "bcs", "bincode", - "crypto", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "curve25519-dalek", "digest 0.10.3", "ed25519-dalek", - "executor", + "executor 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "hex", "hkdf", "itertools", @@ -7230,7 +7415,7 @@ dependencies = [ "async-trait", "bcs", "bytes", - "config 0.1.0", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "futures", "jsonrpsee-http-client", "jsonrpsee-http-server", @@ -7885,15 +8070,15 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "types" version = "0.1.0" -source = "git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d#3cf68183b22acfe014118ef2713d5094159f2f4d" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" dependencies = [ "base64", "bincode", "blake2", "bytes", - "config 0.1.0", - "crypto", - "dag", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "dag 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", "derive_builder", "ed25519-dalek", "proptest", @@ -7906,22 +8091,49 @@ dependencies = [ "tokio-util", "tonic", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", ] [[package]] -name = "ucd-trie" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" - -[[package]] -name = "uncased" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +name = "types" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d#3cf68183b22acfe014118ef2713d5094159f2f4d" dependencies = [ - "version_check", + "base64", + "bincode", + "blake2", + "bytes", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "dag 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "derive_builder", + "ed25519-dalek", + "proptest", + "proptest-derive", + "prost", + "rand 0.7.3", + "serde 1.0.137", + "thiserror", + "tokio", + "tokio-util", + "tonic", + "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", +] + +[[package]] +name = "ucd-trie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" + +[[package]] +name = "uncased" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" +dependencies = [ + "version_check", ] [[package]] @@ -8443,6 +8655,36 @@ dependencies = [ "winapi", ] +[[package]] +name = "worker" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "blake2", + "bytes", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "ed25519-dalek", + "futures", + "multiaddr", + "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "network 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "primary 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "serde 1.0.137", + "tokio", + "tokio-stream", + "tokio-util", + "tonic", + "tower", + "tracing", + "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", + "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900)", +] + [[package]] name = "worker" version = "0.1.0" @@ -8453,14 +8695,14 @@ dependencies = [ "bincode", "blake2", "bytes", - "config 0.1.0", - "crypto", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "ed25519-dalek", "futures", "multiaddr", "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "network", - "primary", + "network 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", + "primary 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "serde 1.0.137", "tokio", "tokio-stream", @@ -8469,7 +8711,7 @@ dependencies = [ "tower", "tracing", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", - "types", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", ] @@ -8566,9 +8808,9 @@ dependencies = [ "colored", "colored-diff", "combine", - "config 0.1.0", + "config 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "config 0.11.0", - "consensus", + "consensus 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "console-api", "console-subscriber", "constant_time_eq", @@ -8588,14 +8830,14 @@ dependencies = [ "crossbeam-utils 0.8.8", "crossterm 0.21.0", "crossterm 0.22.1", - "crypto", + "crypto 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "crypto-common", "crypto-mac", "csv", "csv-core", "curve25519-dalek", "curve25519-dalek-fiat", - "dag", + "dag 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "darling 0.13.4", "darling 0.14.1", "darling_core 0.13.4", @@ -8637,7 +8879,7 @@ dependencies = [ "env_logger", "ethnum", "event-listener", - "executor", + "executor 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "eyre", "fail", "fastrand", @@ -8804,11 +9046,11 @@ dependencies = [ "name-variant", "named-lock", "nested", - "network", + "network 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "nexlint", "nexlint-lints", "nibble_vec", - "node", + "node 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "nom 5.1.2", "nom 7.1.1", "normalize-line-endings", @@ -8872,7 +9114,7 @@ dependencies = [ "pretty", "pretty_assertions", "prettyplease", - "primary", + "primary 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "proc-macro-crate", "proc-macro-error", "proc-macro-error-attr", @@ -9059,7 +9301,7 @@ dependencies = [ "typed-arena", "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=94d7da89f6a52d7f60a9802b0a03147a9c89c3e4)", "typenum", - "types", + "types 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "ucd-trie", "uncased", "unescape", @@ -9104,7 +9346,7 @@ dependencies = [ "webpki-roots 0.21.1", "webpki-roots 0.22.3", "which", - "worker", + "worker 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "workspace-hack 0.1.0 (git+https://github.com/MystenLabs/narwhal?rev=3cf68183b22acfe014118ef2713d5094159f2f4d)", "yaml-rust", "zeroize", @@ -9112,6 +9354,340 @@ dependencies = [ "zstd-sys", ] +[[package]] +name = "workspace-hack" +version = "0.1.0" +source = "git+https://github.com/MystenLabs/narwhal?rev=05fa85552c49f0775a47d72c37074c9ca1754900#05fa85552c49f0775a47d72c37074c9ca1754900" +dependencies = [ + "adler", + "ahash", + "aho-corasick", + "ansi_term", + "anyhow", + "arc-swap", + "ark-bls12-377", + "ark-crypto-primitives", + "ark-ec", + "ark-ed-on-bw6-761", + "ark-ed-on-cp6-782", + "ark-ff", + "ark-ff-asm", + "ark-ff-macros", + "ark-relations", + "ark-serialize", + "ark-serialize-derive", + "ark-snark", + "ark-std", + "arrayref", + "arrayvec 0.7.2", + "async-recursion", + "async-stream", + "async-stream-impl", + "async-trait", + "atty", + "autocfg", + "axum", + "axum-core", + "backoff", + "base64", + "base64ct", + "bincode", + "bindgen 0.59.2", + "bit-set", + "bit-vec", + "bitflags", + "blake2", + "blake2s_simd", + "block-buffer 0.9.0", + "bls-crypto", + "blst", + "bs58", + "bstr", + "byteorder", + "bytes", + "bzip2-sys", + "cast", + "cc", + "cexpr", + "cfg-if 1.0.0", + "clang-sys", + "clap 2.34.0", + "clap 3.1.18", + "clap_lex", + "cmake", + "collectable", + "constant_time_eq", + "core2", + "crc32fast", + "criterion", + "criterion-plot", + "crossbeam-channel 0.5.4", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-utils 0.8.8", + "crypto-mac", + "csv", + "csv-core", + "curve25519-dalek", + "darling 0.13.4", + "darling 0.14.1", + "darling_core 0.13.4", + "darling_core 0.14.1", + "darling_macro 0.13.4", + "darling_macro 0.14.1", + "dashmap", + "data-encoding", + "derivative", + "derive_builder", + "derive_builder_core", + "derive_builder_macro", + "diff", + "difflib", + "digest 0.9.0", + "downcast", + "ed25519", + "ed25519-dalek", + "either", + "env_logger", + "eyre", + "fastrand", + "fixedbitset 0.4.1", + "flate2", + "float-cmp", + "fnv", + "form_urlencoded", + "fragile", + "futures", + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "futures-util", + "generic-array 0.14.5", + "getrandom 0.1.16", + "getrandom 0.2.6", + "glob", + "h2", + "half", + "hashbrown 0.11.2", + "hashbrown 0.12.1", + "hdrhistogram", + "heck 0.3.3", + "heck 0.4.0", + "hex", + "http", + "http-body", + "http-range-header", + "httparse", + "httpdate", + "humantime", + "hyper", + "hyper-timeout", + "ident_case", + "idna", + "indenter", + "indexmap", + "instant", + "itertools", + "itoa 0.4.8", + "itoa 1.0.2", + "jobserver", + "keccak", + "lazy_static 1.4.0", + "lazycell", + "libc", + "libloading", + "librocksdb-sys", + "libz-sys", + "linked-hash-map", + "lock_api 0.4.7", + "log", + "lru", + "match_opt", + "matchers", + "matches", + "matchit", + "memchr", + "memoffset", + "merlin", + "mime", + "minimal-lexical", + "miniz_oxide", + "mio 0.8.3", + "mockall", + "mockall_derive", + "multiaddr", + "multihash", + "multihash-derive", + "multimap", + "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "nom 7.1.1", + "normalize-line-endings", + "num-bigint", + "num-integer", + "num-traits 0.2.15", + "num_cpus", + "once_cell", + "oorandom", + "opaque-debug 0.3.0", + "os_str_bytes", + "parking_lot 0.12.1", + "parking_lot_core 0.9.3", + "paste", + "peeking_take_while", + "percent-encoding", + "pest", + "petgraph 0.6.2", + "pin-project", + "pin-project-internal", + "pin-project-lite", + "pin-utils", + "pkg-config", + "plotters", + "plotters-backend", + "plotters-svg", + "ppv-lite86", + "predicates", + "predicates-core", + "predicates-tree", + "pretty_assertions", + "prettyplease", + "proc-macro-crate", + "proc-macro-error", + "proc-macro-error-attr", + "proc-macro2 0.4.30", + "proc-macro2 1.0.39", + "proptest", + "proptest-derive", + "prost", + "prost-build", + "prost-derive", + "prost-types", + "quick-error 1.2.3", + "quick-error 2.0.1", + "quote 0.6.13", + "quote 1.0.18", + "rand 0.7.3", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.5.1", + "rand_core 0.6.3", + "rand_pcg", + "rand_xorshift", + "rayon", + "rayon-core", + "readonly", + "regex", + "regex-automata", + "regex-syntax", + "remove_dir_all", + "ring", + "rocksdb", + "rustc-hash", + "rustc_version 0.3.3", + "rustc_version 0.4.0", + "rustls 0.20.6", + "rustls-pemfile", + "rusty-fork", + "ryu", + "same-file", + "scopeguard", + "sct 0.7.0", + "semver 0.11.0", + "semver 1.0.9", + "semver-parser", + "serde 1.0.137", + "serde-reflection", + "serde_bytes", + "serde_cbor", + "serde_derive", + "serde_json", + "serde_test", + "serde_with", + "serde_with_macros", + "serde_yaml", + "sha2 0.9.9", + "sharded-slab", + "shlex", + "signature", + "slab", + "smallvec", + "socket2", + "static_assertions", + "strsim 0.10.0", + "strsim 0.8.0", + "structopt", + "structopt-derive", + "subtle", + "syn 0.15.44", + "syn 1.0.96", + "sync_wrapper", + "synstructure", + "tempfile", + "termcolor", + "termtree", + "textwrap 0.11.0", + "textwrap 0.15.0", + "thiserror", + "thiserror-impl", + "thread_local", + "time 0.3.9", + "tinytemplate", + "tinyvec", + "tinyvec_macros", + "tokio", + "tokio-io-timeout", + "tokio-macros", + "tokio-rustls 0.23.4", + "tokio-stream", + "tokio-util", + "toml", + "tonic", + "tonic-build 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tonic-health", + "tower", + "tower-http", + "tower-layer", + "tower-service", + "tracing", + "tracing-attributes", + "tracing-core", + "tracing-futures", + "tracing-log", + "tracing-subscriber 0.2.25", + "tracing-subscriber 0.3.11", + "tracing-test", + "tracing-test-macro", + "try-lock", + "typed-store 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=af52637e73332eba7c8844e9bcdeb5b48854eabf)", + "typenum", + "ucd-trie", + "unicode-bidi", + "unicode-ident", + "unicode-normalization", + "unicode-segmentation", + "unicode-width", + "unicode-xid 0.1.0", + "unicode-xid 0.2.3", + "unsigned-varint", + "untrusted", + "url", + "vec_map", + "version_check", + "wait-timeout", + "walkdir", + "want", + "webpki 0.22.0", + "which", + "yaml-rust", + "zeroize", + "zeroize_derive", + "zstd-sys", +] + [[package]] name = "workspace-hack" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 21d4bfe0619..ce8d59a6465 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "crates/sui", "crates/sui-adapter", "crates/sui-adapter-transactional-tests", + "crates/sui-benchmark", "crates/sui-cluster-test", "crates/sui-config", "crates/sui-core", diff --git a/README.md b/README.md index e11b27e4f4d..736d8cdc0ee 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ * To learn how to use Sui, take our [end-to-end tutorial](doc/src/explore/tutorials.md). * To jump right into building smart contract applications on top of Sui, start at the [Move Smart Contract Quick Start](doc/src/build/move.md). -* To experiment with a sample Sui wallet, check out [Wallet Quick Start](doc/src/build/wallet.md). +* To experiment with the Sui CLI client, check out [Sui CLI client Quick Start](doc/src/build/cli-client.md). * To understand what's possible by browsing Move code built on top of Sui, review the [examples](doc/src/explore/examples.md). * To start coding against Sui's REST APIs, start at the [API reference](https://app.swaggerhub.com/apis/arun-koshy/sui-api). * To learn what distinguishes Sui from other blockchain systems, see [How Sui Differs?](doc/src/learn/sui-compared.md). diff --git a/crates/generate-json-rpc-spec/src/main.rs b/crates/generate-json-rpc-spec/src/main.rs index fbd14081790..8a524e0b8b1 100644 --- a/crates/generate-json-rpc-spec/src/main.rs +++ b/crates/generate-json-rpc-spec/src/main.rs @@ -13,10 +13,10 @@ use pretty_assertions::assert_str_eq; use serde::Serialize; use serde_json::{json, Map, Value}; -use sui::wallet_commands::{WalletCommandResult, WalletCommands, WalletContext}; -use sui::wallet_commands::{EXAMPLE_NFT_DESCRIPTION, EXAMPLE_NFT_NAME, EXAMPLE_NFT_URL}; +use sui::client_commands::{SuiClientCommandResult, SuiClientCommands, WalletContext}; +use sui::client_commands::{EXAMPLE_NFT_DESCRIPTION, EXAMPLE_NFT_NAME, EXAMPLE_NFT_URL}; use sui_config::genesis_config::GenesisConfig; -use sui_config::SUI_WALLET_CONFIG; +use sui_config::SUI_CLIENT_CONFIG; use sui_json::SuiJsonValue; use sui_json_rpc::bcs_api::BcsApiImpl; use sui_json_rpc::gateway_api::{GatewayWalletSyncApiImpl, RpcGatewayImpl, TransactionBuilderImpl}; @@ -130,7 +130,7 @@ async fn create_response_sample() -> Result< > { let network = start_rpc_test_network(Some(GenesisConfig::custom_genesis(1, 4, 30))).await?; let working_dir = network.network.dir(); - let config = working_dir.join(SUI_WALLET_CONFIG); + let config = working_dir.join(SUI_CLIENT_CONFIG); let mut context = WalletContext::new(&config)?; let address = context.config.accounts.first().cloned().unwrap(); @@ -186,14 +186,14 @@ async fn create_response_sample() -> Result< async fn create_package_object_response( context: &mut WalletContext, ) -> Result<(GetObjectDataResponse, TransactionResponse), anyhow::Error> { - let result = WalletCommands::Publish { + let result = SuiClientCommands::Publish { path: "sui_programmability/examples/move_tutorial".to_string(), gas: None, gas_budget: 10000, } .execute(context) .await?; - if let WalletCommandResult::Publish(response) = result { + if let SuiClientCommandResult::Publish(response) = result { Ok(( context .gateway @@ -211,7 +211,7 @@ async fn create_transfer_response( address: SuiAddress, coins: &[SuiObjectInfo], ) -> Result { - let response = WalletCommands::Transfer { + let response = SuiClientCommands::Transfer { to: address, coin_object_id: coins.first().unwrap().object_id, gas: None, @@ -219,7 +219,7 @@ async fn create_transfer_response( } .execute(context) .await?; - if let WalletCommandResult::Transfer(_, certificate, effects) = response { + if let SuiClientCommandResult::Transfer(_, certificate, effects) = response { Ok(TransactionResponse::EffectResponse( TransactionEffectsResponse { certificate, @@ -237,14 +237,14 @@ async fn create_hero_response( coins: &[SuiObjectInfo], ) -> Result<(ObjectID, GetObjectDataResponse), anyhow::Error> { // Create hero response - let result = WalletCommands::Publish { + let result = SuiClientCommands::Publish { path: "sui_programmability/examples/games".to_string(), gas: None, gas_budget: 10000, } .execute(context) .await?; - if let WalletCommandResult::Publish(response) = result { + if let SuiClientCommandResult::Publish(response) = result { let package_id = response.package.object_id; let game_info = response .created_objects @@ -254,7 +254,7 @@ async fn create_hero_response( let game_info = SuiJsonValue::new(json!(game_info.reference.object_id.to_hex_literal()))?; let coin = SuiJsonValue::new(json!(coins.first().unwrap().object_id.to_hex_literal()))?; - let result = WalletCommands::Call { + let result = SuiClientCommands::Call { package: package_id, module: "hero".to_string(), function: "acquire_hero".to_string(), @@ -266,7 +266,7 @@ async fn create_hero_response( .execute(context) .await?; - if let WalletCommandResult::Call(_, effect) = result { + if let SuiClientCommandResult::Call(_, effect) = result { let hero = effect.created.first().unwrap(); Ok(( package_id, @@ -332,7 +332,7 @@ async fn create_coin_split_response( coins: &[SuiObjectInfo], ) -> Result { // create coin_split response - let result = WalletCommands::SplitCoin { + let result = SuiClientCommands::SplitCoin { coin_id: coins.first().unwrap().object_id, amounts: vec![20, 20, 20, 20, 20], gas: None, @@ -341,7 +341,7 @@ async fn create_coin_split_response( .execute(context) .await?; - if let WalletCommandResult::SplitCoin(resp) = result { + if let SuiClientCommandResult::SplitCoin(resp) = result { Ok(TransactionResponse::SplitCoinResponse(resp)) } else { panic!() @@ -361,7 +361,7 @@ async fn get_nft_response( .map(SuiJsonValue::new) .collect::>()?; - let result = WalletCommands::Call { + let result = SuiClientCommands::Call { package: ObjectID::from(SUI_FRAMEWORK_ADDRESS), module: "devnet_nft".to_string(), function: "mint".to_string(), @@ -373,7 +373,7 @@ async fn get_nft_response( .execute(context) .await?; - if let WalletCommandResult::Call(certificate, effects) = result { + if let SuiClientCommandResult::Call(certificate, effects) = result { let object = context .gateway .get_object(effects.created.first().unwrap().reference.object_id) diff --git a/crates/sui-benchmark/Cargo.toml b/crates/sui-benchmark/Cargo.toml new file mode 100644 index 00000000000..2362e2e1368 --- /dev/null +++ b/crates/sui-benchmark/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "sui-benchmark" +version = "0.0.0" +authors = ["Mysten Labs "] +license = "Apache-2.0" +publish = false +edition = "2021" + +[dependencies] +rayon = "1.5.3" +anyhow = { version = "1.0.57", features = ["backtrace"] } +futures = "0.3.21" +serde = { version = "1.0.137", features = ["derive"] } +serde_json = "1.0.80" +tempfile = "3.3.0" +tokio = { version = "1.18.2", features = ["full"] } +strum = "0.24.0" +strum_macros = "0.24.0" +num_cpus = "1.13.1" +rocksdb = "0.18.0" +serde_with = { version = "1.14.0", features = ["hex"] } +tracing = "0.1.34" +tracing-subscriber = { version = "0.3.11", features = ["time", "registry", "env-filter"] } +clap = { version = "3.1.17", features = ["derive"] } +prometheus = "0.13.1" +multiaddr = "0.14.0" + +bcs = "0.1.3" +sui-core = { path = "../sui-core" } +sui-config = { path = "../sui-config" } +sui-types = { path = "../sui-types" } + +move-core-types = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae", features = ["address20"] } +narwhal-node = { git = "https://github.com/MystenLabs/narwhal", rev = "05fa85552c49f0775a47d72c37074c9ca1754900", package = "node" } + +workspace-hack = { path = "../workspace-hack"} + +[features] +benchmark = ["narwhal-node/benchmark"] diff --git a/crates/sui/src/benchmark.rs b/crates/sui-benchmark/src/benchmark.rs similarity index 100% rename from crates/sui/src/benchmark.rs rename to crates/sui-benchmark/src/benchmark.rs diff --git a/crates/sui/src/benchmark/bench_types.rs b/crates/sui-benchmark/src/benchmark/bench_types.rs similarity index 99% rename from crates/sui/src/benchmark/bench_types.rs rename to crates/sui-benchmark/src/benchmark/bench_types.rs index 6ce9cc16394..9cd89fd0271 100644 --- a/crates/sui/src/benchmark/bench_types.rs +++ b/crates/sui-benchmark/src/benchmark/bench_types.rs @@ -1,8 +1,7 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::config::Config; -use sui_config::NetworkConfig; +use sui_config::{Config, NetworkConfig}; use super::load_generator::calculate_throughput; use clap::*; diff --git a/crates/sui/src/benchmark/load_generator.rs b/crates/sui-benchmark/src/benchmark/load_generator.rs similarity index 100% rename from crates/sui/src/benchmark/load_generator.rs rename to crates/sui-benchmark/src/benchmark/load_generator.rs diff --git a/crates/sui/src/benchmark/transaction_creator.rs b/crates/sui-benchmark/src/benchmark/transaction_creator.rs similarity index 100% rename from crates/sui/src/benchmark/transaction_creator.rs rename to crates/sui-benchmark/src/benchmark/transaction_creator.rs diff --git a/crates/sui/src/benchmark/validator_preparer.rs b/crates/sui-benchmark/src/benchmark/validator_preparer.rs similarity index 100% rename from crates/sui/src/benchmark/validator_preparer.rs rename to crates/sui-benchmark/src/benchmark/validator_preparer.rs diff --git a/crates/sui/src/bin/bench.rs b/crates/sui-benchmark/src/bin/bench.rs similarity index 95% rename from crates/sui/src/bin/bench.rs rename to crates/sui-benchmark/src/bin/bench.rs index 6b07fa04881..196aefb6ad9 100644 --- a/crates/sui/src/bin/bench.rs +++ b/crates/sui-benchmark/src/bin/bench.rs @@ -18,7 +18,9 @@ // ./bench microbench local-single-validator-thread latency use clap::*; -use sui::benchmark::{bench_types, run_benchmark, validator_preparer::VALIDATOR_BINARY_NAME}; +use sui_benchmark::benchmark::{ + bench_types, run_benchmark, validator_preparer::VALIDATOR_BINARY_NAME, +}; use tracing::subscriber::set_global_default; use tracing_subscriber::EnvFilter; diff --git a/crates/sui/src/bin/bench_configure.rs b/crates/sui-benchmark/src/bin/bench_configure.rs similarity index 100% rename from crates/sui/src/bin/bench_configure.rs rename to crates/sui-benchmark/src/bin/bench_configure.rs diff --git a/crates/sui/src/bin/remote_load_generator.rs b/crates/sui-benchmark/src/bin/remote_load_generator.rs similarity index 92% rename from crates/sui/src/bin/remote_load_generator.rs rename to crates/sui-benchmark/src/bin/remote_load_generator.rs index 4196f9d3129..188ceb80e16 100644 --- a/crates/sui/src/bin/remote_load_generator.rs +++ b/crates/sui-benchmark/src/bin/remote_load_generator.rs @@ -3,15 +3,14 @@ use clap::*; use futures::join; -use sui::benchmark::bench_types::{MicroBenchmarkResult, RemoteLoadGenConfig}; -use sui::benchmark::load_generator::MultiFixedRateLoadGenerator; +use sui_benchmark::benchmark::bench_types::{MicroBenchmarkResult, RemoteLoadGenConfig}; +use sui_benchmark::benchmark::load_generator::MultiFixedRateLoadGenerator; use std::panic; use std::path::PathBuf; -use sui::benchmark::transaction_creator::TransactionCreator; -use sui::benchmark::validator_preparer::ValidatorPreparer; -use sui::config::PersistedConfig; -use sui_config::NetworkConfig; +use sui_benchmark::benchmark::transaction_creator::TransactionCreator; +use sui_benchmark::benchmark::validator_preparer::ValidatorPreparer; +use sui_config::{NetworkConfig, PersistedConfig}; use sui_types::base_types::ObjectID; use sui_types::crypto::KeyPair; use tokio::runtime::Builder; diff --git a/crates/sui-benchmark/src/lib.rs b/crates/sui-benchmark/src/lib.rs new file mode 100644 index 00000000000..77216f1c788 --- /dev/null +++ b/crates/sui-benchmark/src/lib.rs @@ -0,0 +1,4 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +pub mod benchmark; diff --git a/crates/sui-cluster-test/Cargo.toml b/crates/sui-cluster-test/Cargo.toml index 354e66c1a20..b7492c65d6f 100644 --- a/crates/sui-cluster-test/Cargo.toml +++ b/crates/sui-cluster-test/Cargo.toml @@ -24,4 +24,5 @@ sui-json-rpc-api = { path = "../sui-json-rpc-api" } sui-core = { path = "../sui-core" } sui-types = { path = "../sui-types" } sui-json = { path = "../sui-json" } +sui-config = { path = "../sui-config" } workspace-hack = { path = "../workspace-hack"} \ No newline at end of file diff --git a/crates/sui-cluster-test/src/main.rs b/crates/sui-cluster-test/src/main.rs index 71e564ac35f..80cf2aee90c 100644 --- a/crates/sui-cluster-test/src/main.rs +++ b/crates/sui-cluster-test/src/main.rs @@ -4,15 +4,14 @@ use clap::*; use serde_json::json; use std::collections::HashMap; -use sui::config::{Config, GatewayType, WalletConfig}; -use sui::{ - keystore::KeystoreType, - wallet_commands::{ - call_move, WalletContext, EXAMPLE_NFT_DESCRIPTION, EXAMPLE_NFT_NAME, EXAMPLE_NFT_URL, - }, +use sui::client_commands::{ + call_move, WalletContext, EXAMPLE_NFT_DESCRIPTION, EXAMPLE_NFT_NAME, EXAMPLE_NFT_URL, }; +use sui::config::{Config, GatewayType, SuiClientConfig}; +use sui_config::SUI_KEYSTORE_FILENAME; use sui_faucet::FaucetResponse; use sui_json::SuiJsonValue; +use sui_json_rpc_api::keystore::KeystoreType; use sui_json_rpc_api::rpc_types::{GetObjectDataResponse, SuiExecutionStatus, TransactionResponse}; use sui_types::{ base_types::{encode_bytes_hex, ObjectID, SuiAddress}, @@ -368,11 +367,11 @@ impl ClusterTest { }; info!("Use gateway: {}", &gateway_addr); - info!("Use facuet: {}", &faucet_addr); - let keystore_path = temp_dir.path().join("wallet.key"); + info!("Use facet: {}", &faucet_addr); + let keystore_path = temp_dir.path().join(SUI_KEYSTORE_FILENAME); let keystore = KeystoreType::File(keystore_path); let new_address = keystore.init().unwrap().add_random_key().unwrap(); - WalletConfig { + SuiClientConfig { accounts: vec![new_address], keystore, gateway: GatewayType::RPC(gateway_addr), diff --git a/crates/sui-config/src/lib.rs b/crates/sui-config/src/lib.rs index b339980e270..389e6ab28ac 100644 --- a/crates/sui-config/src/lib.rs +++ b/crates/sui-config/src/lib.rs @@ -24,7 +24,8 @@ const SUI_DIR: &str = ".sui"; const SUI_CONFIG_DIR: &str = "sui_config"; pub const SUI_NETWORK_CONFIG: &str = "network.yaml"; pub const SUI_FULLNODE_CONFIG: &str = "fullnode.yaml"; -pub const SUI_WALLET_CONFIG: &str = "wallet.yaml"; +pub const SUI_CLIENT_CONFIG: &str = "client.yaml"; +pub const SUI_KEYSTORE_FILENAME: &str = "sui.keystore"; pub const SUI_GATEWAY_CONFIG: &str = "gateway.yaml"; pub const SUI_GENESIS_FILENAME: &str = "genesis.blob"; pub const SUI_DEV_NET_URL: &str = "https://gateway.devnet.sui.io:443"; diff --git a/crates/sui-faucet/src/faucet/simple_faucet.rs b/crates/sui-faucet/src/faucet/simple_faucet.rs index 357eb1d7087..3d461a42428 100644 --- a/crates/sui-faucet/src/faucet/simple_faucet.rs +++ b/crates/sui-faucet/src/faucet/simple_faucet.rs @@ -3,7 +3,7 @@ use anyhow::anyhow; use async_trait::async_trait; -use sui::wallet_commands::WalletContext; +use sui::client_commands::WalletContext; use sui_json_rpc_api::rpc_types::{SuiExecutionStatus, SuiParsedObject}; use sui_types::{ base_types::{ObjectID, SuiAddress}, diff --git a/crates/sui-faucet/src/main.rs b/crates/sui-faucet/src/main.rs index 6a46f424add..ab66de03349 100644 --- a/crates/sui-faucet/src/main.rs +++ b/crates/sui-faucet/src/main.rs @@ -16,8 +16,8 @@ use std::{ sync::Arc, time::Duration, }; -use sui::wallet_commands::{WalletCommands, WalletContext}; -use sui_config::{sui_config_dir, SUI_WALLET_CONFIG}; +use sui::client_commands::{SuiClientCommands, WalletContext}; +use sui_config::{sui_config_dir, SUI_CLIENT_CONFIG}; use sui_faucet::{Faucet, FaucetRequest, FaucetResponse, SimpleFaucet}; use tower::ServiceBuilder; use tower_http::cors::{Any, CorsLayer}; @@ -145,7 +145,7 @@ async fn request_gas( async fn create_wallet_context() -> Result { // Create Wallet context. - let wallet_conf = sui_config_dir()?.join(SUI_WALLET_CONFIG); + let wallet_conf = sui_config_dir()?.join(SUI_CLIENT_CONFIG); info!("Initialize wallet from config path: {:?}", wallet_conf); let mut context = WalletContext::new(&wallet_conf)?; let address = context @@ -156,7 +156,7 @@ async fn create_wallet_context() -> Result { .ok_or_else(|| anyhow::anyhow!("Empty wallet context!"))?; // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(&mut context) diff --git a/crates/sui-gateway/Cargo.toml b/crates/sui-gateway/Cargo.toml index 12a06625257..39e0f8e7c4b 100644 --- a/crates/sui-gateway/Cargo.toml +++ b/crates/sui-gateway/Cargo.toml @@ -10,30 +10,28 @@ edition = "2021" anyhow = { version = "1.0.58", features = ["backtrace"] } async-trait = "0.1.53" serde = { version = "1.0.137", features = ["derive"] } -serde_json = "1.0.80" -serde_with = { version = "1.14.0", features = ["hex"] } -schemars = "0.8.8" -jsonrpsee = { version = "0.13.1", features = ["full"] } -jsonrpsee-proc-macros = "0.13.1" -jsonrpsee-core = "0.13.1" tracing = "0.1.34" tokio = { version = "1.18.2", features = ["full"] } -tokio-stream = "0.1.8" futures = "0.3.21" -ed25519-dalek = { version = "1.0.1", features = ["batch", "serde"] } prometheus = "0.13.1" -strum = "0.24.0" -strum_macros = "0.24.0" -once_cell = "1.11.0" +clap = { version = "3.1.17", features = ["derive"] } +telemetry-subscribers = { git = "https://github.com/MystenLabs/mysten-infra", rev = "94d7da89f6a52d7f60a9802b0a03147a9c89c3e4" } sui-core = { path = "../sui-core" } sui-config = { path = "../sui-config" } sui-types = { path = "../sui-types" } sui-json = { path = "../sui-json" } +sui-json-rpc = { path = "../sui-json-rpc" } sui-json-rpc-api = { path = "../sui-json-rpc-api" } -sui-open-rpc = { path = "../sui-open-rpc" } +sui-node = { path = "../sui-node" } -move-core-types = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae", features = ["address20"] } -move-bytecode-utils = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae" } mysten-network = { git = "https://github.com/MystenLabs/mysten-infra", rev = "94d7da89f6a52d7f60a9802b0a03147a9c89c3e4" } workspace-hack = { path = "../workspace-hack"} + +[dev-dependencies] +test-utils = { path = "../test-utils" } +sui-framework = { path = "../sui-framework" } + +[[bin]] +name = "rpc-server" +path = "src/main.rs" \ No newline at end of file diff --git a/crates/sui/src/bin/rpc-server.rs b/crates/sui-gateway/src/main.rs similarity index 98% rename from crates/sui/src/bin/rpc-server.rs rename to crates/sui-gateway/src/main.rs index 94adf65dc0f..d3bfc6e820e 100644 --- a/crates/sui/src/bin/rpc-server.rs +++ b/crates/sui-gateway/src/main.rs @@ -21,7 +21,7 @@ const DEFAULT_RPC_SERVER_ADDR_IPV4: &str = "127.0.0.1"; const PROM_PORT_ADDR: &str = "0.0.0.0:9184"; #[cfg(test)] -#[path = "../unit_tests/rpc_server_tests.rs"] +#[path = "unit_tests/rpc_server_tests.rs"] mod rpc_server_tests; #[derive(Parser)] diff --git a/crates/sui/src/unit_tests/rpc_server_tests.rs b/crates/sui-gateway/src/unit_tests/rpc_server_tests.rs similarity index 93% rename from crates/sui/src/unit_tests/rpc_server_tests.rs rename to crates/sui-gateway/src/unit_tests/rpc_server_tests.rs index 6e160dc3b61..b07c4af8443 100644 --- a/crates/sui/src/unit_tests/rpc_server_tests.rs +++ b/crates/sui-gateway/src/unit_tests/rpc_server_tests.rs @@ -2,10 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use std::{path::Path, str::FromStr}; -use sui::keystore::{Keystore, SuiKeystore}; +use sui_config::SUI_KEYSTORE_FILENAME; use sui_core::gateway_state::GatewayTxSeqNumber; use sui_framework::build_move_package_to_bytes; use sui_json::SuiJsonValue; +use sui_json_rpc_api::keystore::{Keystore, SuiKeystore}; use sui_json_rpc_api::rpc_types::{ GetObjectDataResponse, TransactionEffectsResponse, TransactionResponse, }; @@ -51,7 +52,8 @@ async fn test_public_transfer_object() -> Result<(), anyhow::Error> { ) .await?; - let keystore = SuiKeystore::load_or_create(&test_network.network.dir().join("wallet.key"))?; + let keystore = + SuiKeystore::load_or_create(&test_network.network.dir().join(SUI_KEYSTORE_FILENAME))?; let tx_bytes = tx_data.tx_bytes.to_vec()?; let signature = keystore.sign(address, &tx_bytes)?; @@ -90,7 +92,8 @@ async fn test_publish() -> Result<(), anyhow::Error> { .publish(*address, compiled_modules, Some(gas.object_id), 10000) .await?; - let keystore = SuiKeystore::load_or_create(&test_network.network.dir().join("wallet.key"))?; + let keystore = + SuiKeystore::load_or_create(&test_network.network.dir().join(SUI_KEYSTORE_FILENAME))?; let tx_bytes = tx_data.tx_bytes.to_vec()?; let signature = keystore.sign(address, &tx_bytes)?; @@ -138,7 +141,8 @@ async fn test_move_call() -> Result<(), anyhow::Error> { ) .await?; - let keystore = SuiKeystore::load_or_create(&test_network.network.dir().join("wallet.key"))?; + let keystore = + SuiKeystore::load_or_create(&test_network.network.dir().join(SUI_KEYSTORE_FILENAME))?; let tx_bytes = tx_data.tx_bytes.to_vec()?; let signature = keystore.sign(address, &tx_bytes)?; @@ -190,7 +194,8 @@ async fn test_get_transaction() -> Result<(), anyhow::Error> { .public_transfer_object(*address, oref.object_id, Some(gas_id), 1000, *address) .await?; - let keystore = SuiKeystore::load_or_create(&test_network.network.dir().join("wallet.key"))?; + let keystore = + SuiKeystore::load_or_create(&test_network.network.dir().join(SUI_KEYSTORE_FILENAME))?; let tx_bytes = tx_data.tx_bytes.to_vec()?; let signature = keystore.sign(address, &tx_bytes)?; diff --git a/crates/sui-json-rpc-api/Cargo.toml b/crates/sui-json-rpc-api/Cargo.toml index 418604531a6..b25440f020f 100644 --- a/crates/sui-json-rpc-api/Cargo.toml +++ b/crates/sui-json-rpc-api/Cargo.toml @@ -23,6 +23,7 @@ either = "1.6.1" move-core-types = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae", features = ["address20"] } move-bytecode-utils = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae" } itertools = "0.10.3" +ed25519-dalek = { version = "1.0.1", features = ["batch", "serde"] } sui-types = { path = "../sui-types" } sui-json = { path = "../sui-json" } diff --git a/crates/sui-json-rpc-api/src/client.rs b/crates/sui-json-rpc-api/src/client.rs index 180200f8f65..347cfae08a8 100644 --- a/crates/sui-json-rpc-api/src/client.rs +++ b/crates/sui-json-rpc-api/src/client.rs @@ -3,10 +3,10 @@ use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; -use crate::QuorumDriverApiClient; -use crate::RpcFullNodeReadApiClient; -use crate::RpcReadApiClient; -use crate::RpcTransactionBuilderClient; +pub use crate::QuorumDriverApiClient; +pub use crate::RpcFullNodeReadApiClient; +pub use crate::RpcReadApiClient; +pub use crate::RpcTransactionBuilderClient; use crate::WalletSyncApiClient; pub struct SuiRpcClient { diff --git a/crates/sui/src/keystore.rs b/crates/sui-json-rpc-api/src/keystore.rs similarity index 100% rename from crates/sui/src/keystore.rs rename to crates/sui-json-rpc-api/src/keystore.rs diff --git a/crates/sui-json-rpc-api/src/lib.rs b/crates/sui-json-rpc-api/src/lib.rs index 6e9e73dff24..66fd12523e5 100644 --- a/crates/sui-json-rpc-api/src/lib.rs +++ b/crates/sui-json-rpc-api/src/lib.rs @@ -24,6 +24,7 @@ use sui_types::{ }; pub mod client; +pub mod keystore; pub mod rpc_types; type GatewayTxSeqNumber = u64; diff --git a/crates/sui/Cargo.toml b/crates/sui/Cargo.toml index d36da9854fc..9b0203822e4 100644 --- a/crates/sui/Cargo.toml +++ b/crates/sui/Cargo.toml @@ -7,84 +7,44 @@ publish = false edition = "2021" [dependencies] -rayon = "1.5.3" anyhow = { version = "1.0.58", features = ["backtrace"] } -bytes = "1.1.0" -futures = "0.3.21" serde = { version = "1.0.137", features = ["derive"] } serde_json = "1.0.80" -tempfile = "3.3.0" tokio = { version = "1.18.2", features = ["full"] } -parking_lot = "0.12.1" -rand = "0.7.3" -toml = "0.5.9" -strum = "0.24.0" -strum_macros = "0.24.0" -num_cpus = "1.13.1" -base64ct = { version = "1.5.1", features = ["alloc"] } -ed25519-dalek = { version = "1.0.1", features = ["batch", "serde"] } -rocksdb = "0.18.0" -hex = "0.4.3" async-trait = "0.1.53" serde_with = { version = "1.14.0", features = ["hex"] } tracing = "0.1.34" -tracing-subscriber = { version = "0.3.11", features = ["time", "registry", "env-filter"] } -serde-value = "0.7.0" -serde-name = "0.2.1" -dirs = "4.0.0" clap = { version = "3.1.17", features = ["derive"] } telemetry-subscribers = { git = "https://github.com/MystenLabs/mysten-infra", rev = "94d7da89f6a52d7f60a9802b0a03147a9c89c3e4" } -prometheus = "0.13.1" -multiaddr = "0.14.0" -mysten-network = { git = "https://github.com/MystenLabs/mysten-infra", rev = "94d7da89f6a52d7f60a9802b0a03147a9c89c3e4" } -bcs = "0.1.3" sui-core = { path = "../sui-core" } -sui-storage = { path = "../sui-storage" } -sui-adapter = { path = "../sui-adapter" } sui-framework = { path = "../sui-framework" } -sui-network = { path = "../sui-network" } sui-config = { path = "../sui-config" } sui-types = { path = "../sui-types" } -sui-verifier = { path = "../sui-verifier" } -sui-open-rpc = { path = "../sui-open-rpc" } -sui-open-rpc-macros = { path = "../sui-open-rpc-macros" } sui-json = { path = "../sui-json" } sui-gateway = { path = "../sui-gateway" } -sui-node = { path = "../sui-node" } sui-swarm = { path = "../sui-swarm" } -sui-json-rpc = { path = "../sui-json-rpc" } sui-json-rpc-api = { path = "../sui-json-rpc-api" } rustyline = "9.1.2" rustyline-derive = "0.6.0" colored = "2.0.0" unescape = "0.1.0" +shell-words = "1.1.0" -move-package = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae" } move-core-types = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae", features = ["address20"] } -move-bytecode-verifier = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae" } -move-binary-format = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae" } -move-bytecode-utils = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae" } move-unit-test = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae" } -narwhal-node = { git = "https://github.com/MystenLabs/narwhal", rev = "3cf68183b22acfe014118ef2713d5094159f2f4d", package = "node" } - -once_cell = "1.11.0" - -jsonrpsee = { version = "0.13.1", features = ["full"] } -jsonrpsee-proc-macros = "0.13.1" -jsonrpsee-core = "0.13.1" -schemars = "0.8.10" -shell-words = "1.1.0" workspace-hack = { path = "../workspace-hack"} [dev-dependencies] -pretty_assertions = "1.2.0" -tokio-util = { version = "0.7.2", features = ["codec"] } +tempfile = "3.3.0" +futures = "0.3.21" +jsonrpsee = { version = "0.13.1", features = ["full"] } typed-store = { git = "https://github.com/MystenLabs/mysten-infra", rev = "94d7da89f6a52d7f60a9802b0a03147a9c89c3e4"} test-utils = { path = "../test-utils" } sui-quorum-driver = { path = "../sui-quorum-driver" } - -[features] -benchmark = ["narwhal-node/benchmark"] +rand = "0.7.3" +move-package = { git = "https://github.com/move-language/move", rev = "ae62d5f1955a9b92c3ddd31d3cc4467f9aff76ae" } +sui-core = { path = "../sui-core" } +sui-node = { path = "../sui-node" } diff --git a/crates/sui/src/bin/key_tool.rs b/crates/sui/src/bin/key_tool.rs deleted file mode 100644 index 7e6581eecef..00000000000 --- a/crates/sui/src/bin/key_tool.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2022, Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use clap::*; -use std::{fs, path::Path}; -use sui_types::{ - base_types::SuiAddress, - crypto::{get_key_pair, KeyPair}, -}; - -#[allow(clippy::large_enum_variant)] -#[derive(Parser)] -#[clap( - name = "Sui Key Tool", - about = "Utility For Generating Keys and Addresses Encoded as Base64 Bytes", - rename_all = "kebab-case" -)] -enum KeyToolOpt { - /// Generate a keypair - Generate {}, - - /// Extract components - Unpack { keypair: KeyPair }, -} - -fn main() { - let res = match KeyToolOpt::parse() { - KeyToolOpt::Generate {} => get_key_pair(), - KeyToolOpt::Unpack { keypair } => (SuiAddress::from(keypair.public_key_bytes()), keypair), - }; - let path_str = format!("{}.key", res.0).to_lowercase(); - let path = Path::new(&path_str); - let address = format!("{}", res.0); - let kp = serde_json::to_string(&res.1).unwrap(); - let kp = &kp[1..kp.len() - 1]; - let out_str = format!("address: {}\nkeypair: {}", address, kp); - fs::write(path, out_str).unwrap(); - println!("Address and keypair written to {}", path.to_str().unwrap()); -} diff --git a/crates/sui/src/bin/sui.rs b/crates/sui/src/bin/sui.rs deleted file mode 100644 index 964eadb28e0..00000000000 --- a/crates/sui/src/bin/sui.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2022, Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 -extern crate core; - -use clap::*; -use sui::sui_commands::SuiCommand; - -#[cfg(test)] -#[path = "../unit_tests/cli_tests.rs"] -mod cli_tests; - -#[derive(Parser)] -#[clap( - name = "Sui Local", - about = "A Byzantine fault tolerant chain with low-latency finality and high throughput", - rename_all = "kebab-case" -)] -struct SuiOpt { - #[clap(subcommand)] - command: SuiCommand, -} - -#[tokio::main] -async fn main() -> Result<(), anyhow::Error> { - let _guard = telemetry_subscribers::TelemetryConfig::new(env!("CARGO_BIN_NAME")) - .with_env() - .init(); - - let options: SuiOpt = SuiOpt::parse(); - options.command.execute().await -} diff --git a/crates/sui/src/bin/wallet.rs b/crates/sui/src/bin/wallet.rs deleted file mode 100644 index bb72b2255db..00000000000 --- a/crates/sui/src/bin/wallet.rs +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (c) 2022, Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use std::{ - io, - io::{stderr, stdout, Write}, - ops::Deref, - path::PathBuf, -}; - -use async_trait::async_trait; -use clap::*; -use jsonrpsee::http_client::HttpClientBuilder; -use tracing::debug; - -use colored::Colorize; -use sui::{ - config::{GatewayType, WalletConfig}, - keystore::KeystoreType, - shell::{ - install_shell_plugins, AsyncHandler, CacheKey, CommandStructure, CompletionCache, Shell, - }, - wallet_commands::*, -}; -use sui_config::{sui_config_dir, Config, SUI_DEV_NET_URL, SUI_WALLET_CONFIG}; -use sui_types::exit_main; - -const SUI: &str = " _____ _ _ __ ____ __ - / ___/__ __(_) | | / /___ _/ / /__ / /_ - \\__ \\/ / / / / | | /| / / __ `/ / / _ \\/ __/ - ___/ / /_/ / / | |/ |/ / /_/ / / / __/ /_ -/____/\\__,_/_/ |__/|__/\\__,_/_/_/\\___/\\__/"; - -#[derive(Parser)] -#[clap( - name = "sui-cli", - about = "A Byzantine fault tolerant chain with low-latency finality and high throughput", - rename_all = "kebab-case" -)] -struct ClientOpt { - #[clap(short, global = true)] - /// Start interactive wallet - interactive: bool, - /// Sets the file storing the state of our user accounts (an empty one will be created if missing) - #[clap(long)] - config: Option, - /// Subcommands. Acceptable values are transfer, query_objects, benchmark, and create_accounts. - #[clap(subcommand)] - cmd: Option, - /// Return command outputs in json format. - #[clap(long, global = true)] - json: bool, -} - -async fn try_main() -> Result<(), anyhow::Error> { - let _guard = telemetry_subscribers::TelemetryConfig::new(env!("CARGO_BIN_NAME")) - .with_log_file("wallet.log") - .with_env() - .init(); - - if let Some(git_rev) = std::option_env!("GIT_REVISION") { - debug!("Wallet built at git revision {git_rev}"); - } - - let mut app: Command = ClientOpt::command(); - app = app.no_binary_name(false); - let options: ClientOpt = ClientOpt::from_arg_matches(&app.get_matches())?; - - let wallet_conf_path = options - .config - .clone() - .unwrap_or(sui_config_dir()?.join(SUI_WALLET_CONFIG)); - - // Prompt user for connect to gateway if config not exists. - if !wallet_conf_path.exists() { - print!( - "Config file [{:?}] doesn't exist, do you want to connect to a Sui Gateway [yN]?", - wallet_conf_path - ); - if matches!(read_line(), Ok(line) if line.trim().to_lowercase() == "y") { - print!("Sui Gateway Url (Default to Sui DevNet if not specified) : "); - let url = read_line()?; - let url = if url.trim().is_empty() { - SUI_DEV_NET_URL - } else { - &url - }; - - // Check url is valid - HttpClientBuilder::default().build(url)?; - let keystore_path = wallet_conf_path - .parent() - .unwrap_or(&sui_config_dir()?) - .join("wallet.key"); - let keystore = KeystoreType::File(keystore_path); - let new_address = keystore.init()?.add_random_key()?; - WalletConfig { - accounts: vec![new_address], - keystore, - gateway: GatewayType::RPC(url.to_string()), - active_address: Some(new_address), - } - .persisted(&wallet_conf_path) - .save()?; - } - } - - let mut context = WalletContext::new(&wallet_conf_path)?; - - // Sync all accounts on start up. - // Do not sync if command is a gateway switch, as the current gateway might be unreachable and causes sync to panic. - if !matches!( - options.cmd, - Some(WalletCommands::Switch { - gateway: Some(_), - .. - }) - ) { - for address in context.config.accounts.clone() { - WalletCommands::SyncClientState { - address: Some(address), - } - .execute(&mut context) - .await?; - } - } - - let mut out = stdout(); - - if options.interactive { - let app: Command = WalletCommands::command(); - writeln!(out, "{}", SUI.cyan().bold())?; - let mut version = app - .get_long_version() - .unwrap_or_else(|| app.get_version().unwrap_or("unknown")) - .to_owned(); - if let Some(git_rev) = std::option_env!("GIT_REVISION") { - version.push('-'); - version.push_str(git_rev); - } - writeln!(out, "--- Sui CLI {version} ---")?; - writeln!(out)?; - writeln!(out, "{}", context.config.deref())?; - writeln!(out, "Welcome to the Sui interactive shell.")?; - writeln!(out)?; - - let mut shell = Shell::new( - "sui>-$ ".bold().green(), - context, - ClientCommandHandler, - CommandStructure::from_clap(&install_shell_plugins(app)), - ); - - shell.run_async(&mut out, &mut stderr()).await?; - } else if let Some(cmd) = options.cmd { - cmd.execute(&mut context).await?.print(!options.json); - } else { - ClientOpt::command().print_long_help()? - } - Ok(()) -} - -fn read_line() -> Result { - let mut s = String::new(); - let _ = stdout().flush(); - io::stdin().read_line(&mut s)?; - Ok(s.trim_end().to_string()) -} - -#[tokio::main] -async fn main() { - exit_main!(try_main().await) -} - -struct ClientCommandHandler; - -#[async_trait] -impl AsyncHandler for ClientCommandHandler { - async fn handle_async( - &self, - args: Vec, - context: &mut WalletContext, - completion_cache: CompletionCache, - ) -> bool { - match handle_command(get_command(args), context, completion_cache).await { - Err(e) => { - let _err = writeln!(stderr(), "{}", e.to_string().red()); - false - } - Ok(return_value) => return_value, - } - } -} - -fn get_command(args: Vec) -> Result { - let app: Command = install_shell_plugins(WalletOpts::command()); - Ok(WalletOpts::from_arg_matches( - &app.try_get_matches_from(args)?, - )?) -} - -async fn handle_command( - wallet_opts: Result, - context: &mut WalletContext, - completion_cache: CompletionCache, -) -> Result { - let wallet_opts = wallet_opts?; - let result = wallet_opts.command.execute(context).await?; - - // Update completion cache - // TODO: Completion data are keyed by strings, are there ways to make it more error proof? - if let Ok(mut cache) = completion_cache.write() { - match result { - WalletCommandResult::Addresses(ref addresses) => { - let addresses = addresses - .iter() - .map(|addr| format!("{addr}")) - .collect::>(); - cache.insert(CacheKey::flag("--address"), addresses.clone()); - cache.insert(CacheKey::flag("--to"), addresses); - } - WalletCommandResult::Objects(ref objects) => { - let objects = objects - .iter() - .map(|oref| format!("{}", oref.object_id)) - .collect::>(); - cache.insert(CacheKey::new("object", "--id"), objects.clone()); - cache.insert(CacheKey::flag("--gas"), objects.clone()); - cache.insert(CacheKey::flag("--coin-object-id"), objects); - } - _ => {} - } - } - result.print(!wallet_opts.json); - - // Quit shell after gateway switch - if matches!( - result, - WalletCommandResult::Switch(SwitchResponse { - gateway: Some(_), - .. - }) - ) { - println!("Gateway switch completed, please restart wallet."); - return Ok(true); - } - Ok(false) -} diff --git a/crates/sui/src/wallet_commands.rs b/crates/sui/src/client_commands.rs similarity index 88% rename from crates/sui/src/wallet_commands.rs rename to crates/sui/src/client_commands.rs index bfc42ae0d66..cf3d9a3b4f8 100644 --- a/crates/sui/src/wallet_commands.rs +++ b/crates/sui/src/client_commands.rs @@ -24,6 +24,7 @@ use tracing::info; use sui_core::gateway_state::GatewayClient; use sui_framework::build_move_package_to_bytes; use sui_json::SuiJsonValue; +use sui_json_rpc_api::keystore::Keystore; use sui_json_rpc_api::rpc_types::{ SuiCertifiedTransaction, SuiExecutionStatus, SuiTransactionEffects, }; @@ -36,29 +37,16 @@ use sui_types::{ SUI_FRAMEWORK_ADDRESS, }; -use crate::{ - config::{Config, GatewayType, PersistedConfig, WalletConfig}, - keystore::Keystore, -}; +use crate::config::{Config, GatewayType, PersistedConfig, SuiClientConfig}; pub const EXAMPLE_NFT_NAME: &str = "Example NFT"; -pub const EXAMPLE_NFT_DESCRIPTION: &str = "An NFT created by the wallet Command Line Tool"; +pub const EXAMPLE_NFT_DESCRIPTION: &str = "An NFT created by the Sui Command Line Tool"; pub const EXAMPLE_NFT_URL: &str = "ipfs://bafkreibngqhl3gaa7daob4i2vccziay2jjlp435cf66vhono7nrvww53ty"; #[derive(Parser)] -#[clap(name = "", rename_all = "kebab-case", no_binary_name = true)] -pub struct WalletOpts { - #[clap(subcommand)] - pub command: WalletCommands, - /// Returns command outputs in JSON format. - #[clap(long, global = true)] - pub json: bool, -} - -#[derive(StructOpt, Debug)] -#[clap(rename_all = "kebab-case", no_binary_name = true)] -pub enum WalletCommands { +#[clap(rename_all = "kebab-case")] +pub enum SuiClientCommands { /// Switch active address and network(e.g., devnet, local rpc server) #[clap(name = "switch")] Switch { @@ -74,9 +62,9 @@ pub enum WalletCommands { /// Default address used for commands when none specified #[clap(name = "active-address")] - ActiveAddress {}, + ActiveAddress, - /// Get obj info + /// Get object info #[clap(name = "object")] Object { /// Object ID of the object to fetch @@ -183,7 +171,7 @@ pub enum WalletCommands { address: Option, }, - /// Obtain the Addresses managed by the wallet. + /// Obtain the Addresses managed by the client. #[clap(name = "addresses")] Addresses, @@ -272,13 +260,13 @@ pub enum WalletCommands { }, } -impl WalletCommands { +impl SuiClientCommands { pub async fn execute( self, context: &mut WalletContext, - ) -> Result { + ) -> Result { let ret = Ok(match self { - WalletCommands::Publish { + SuiClientCommands::Publish { path, gas, gas_budget, @@ -298,15 +286,15 @@ impl WalletCommands { .await? .to_publish_response()?; - WalletCommandResult::Publish(response) + SuiClientCommandResult::Publish(response) } - WalletCommands::Object { id } => { + SuiClientCommands::Object { id } => { // Fetch the object ref let object_read = context.gateway.get_object(id).await?; - WalletCommandResult::Object(object_read) + SuiClientCommandResult::Object(object_read) } - WalletCommands::Call { + SuiClientCommands::Call { package, module, function, @@ -319,10 +307,10 @@ impl WalletCommands { package, &module, &function, type_args, gas, gas_budget, args, context, ) .await?; - WalletCommandResult::Call(cert, effects) + SuiClientCommandResult::Call(cert, effects) } - WalletCommands::Transfer { + SuiClientCommands::Transfer { to, coin_object_id: object_id, gas, @@ -348,10 +336,10 @@ impl WalletCommands { if matches!(effects.status, SuiExecutionStatus::Failure { .. }) { return Err(anyhow!("Error transferring object: {:#?}", effects.status)); } - WalletCommandResult::Transfer(time_total, cert, effects) + SuiClientCommandResult::Transfer(time_total, cert, effects) } - WalletCommands::TransferSui { + SuiClientCommands::TransferSui { to, sui_coin_object_id: object_id, gas_budget, @@ -375,14 +363,14 @@ impl WalletCommands { if matches!(effects.status, SuiExecutionStatus::Failure { .. }) { return Err(anyhow!("Error transferring SUI: {:#?}", effects.status)); } - WalletCommandResult::TransferSui(cert, effects) + SuiClientCommandResult::TransferSui(cert, effects) } - WalletCommands::Addresses => { - WalletCommandResult::Addresses(context.config.accounts.clone()) + SuiClientCommands::Addresses => { + SuiClientCommandResult::Addresses(context.config.accounts.clone()) } - WalletCommands::Objects { address } => { + SuiClientCommands::Objects { address } => { let address = address.unwrap_or(context.active_address()?); let mut address_object = context .gateway @@ -394,21 +382,21 @@ impl WalletCommands { .await?; address_object.extend(object_objects); - WalletCommandResult::Objects(address_object) + SuiClientCommandResult::Objects(address_object) } - WalletCommands::SyncClientState { address } => { + SuiClientCommands::SyncClientState { address } => { let address = address.unwrap_or(context.active_address()?); context.gateway.sync_account_state(address).await?; - WalletCommandResult::SyncClientState + SuiClientCommandResult::SyncClientState } - WalletCommands::NewAddress => { + SuiClientCommands::NewAddress => { let address = context.keystore.add_random_key()?; context.config.accounts.push(address); context.config.save()?; - WalletCommandResult::NewAddress(address) + SuiClientCommandResult::NewAddress(address) } - WalletCommands::Gas { address } => { + SuiClientCommands::Gas { address } => { let address = address.unwrap_or(context.active_address()?); let coins = context .gas_objects(address) @@ -417,9 +405,9 @@ impl WalletCommands { // Ok to unwrap() since `get_gas_objects` guarantees gas .map(|(_, object)| GasCoin::try_from(object).unwrap()) .collect(); - WalletCommandResult::Gas(coins) + SuiClientCommandResult::Gas(coins) } - WalletCommands::SplitCoin { + SuiClientCommands::SplitCoin { coin_id, amounts, gas, @@ -436,9 +424,9 @@ impl WalletCommands { .execute_transaction(Transaction::new(data, signature)) .await? .to_split_coin_response()?; - WalletCommandResult::SplitCoin(response) + SuiClientCommandResult::SplitCoin(response) } - WalletCommands::MergeCoin { + SuiClientCommands::MergeCoin { primary_coin, coin_to_merge, gas, @@ -456,9 +444,9 @@ impl WalletCommands { .await? .to_merge_coin_response()?; - WalletCommandResult::MergeCoin(response) + SuiClientCommandResult::MergeCoin(response) } - WalletCommands::Switch { address, gateway } => { + SuiClientCommands::Switch { address, gateway } => { if let Some(addr) = address { if !context.config.accounts.contains(&addr) { return Err(anyhow!("Address {} not managed by wallet", addr)); @@ -479,12 +467,12 @@ impl WalletCommands { )); } - WalletCommandResult::Switch(SwitchResponse { address, gateway }) + SuiClientCommandResult::Switch(SwitchResponse { address, gateway }) } - WalletCommands::ActiveAddress {} => { - WalletCommandResult::ActiveAddress(context.active_address().ok()) + SuiClientCommands::ActiveAddress => { + SuiClientCommandResult::ActiveAddress(context.active_address().ok()) } - WalletCommands::CreateExampleNFT { + SuiClientCommands::CreateExampleNFT { name, description, url, @@ -518,7 +506,7 @@ impl WalletCommands { .reference .object_id; let object_read = context.gateway.get_object(nft_id).await?; - WalletCommandResult::CreateExampleNFT(object_read) + SuiClientCommandResult::CreateExampleNFT(object_read) } }); ret @@ -526,14 +514,14 @@ impl WalletCommands { } pub struct WalletContext { - pub config: PersistedConfig, + pub config: PersistedConfig, pub keystore: Box, pub gateway: GatewayClient, } impl WalletContext { pub fn new(config_path: &Path) -> Result { - let config: WalletConfig = PersistedConfig::read(config_path).map_err(|err| { + let config: SuiClientConfig = PersistedConfig::read(config_path).map_err(|err| { err.context(format!( "Cannot open wallet config file at {:?}", config_path @@ -626,34 +614,34 @@ impl WalletContext { } } -impl Display for WalletCommandResult { +impl Display for SuiClientCommandResult { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut writer = String::new(); match self { - WalletCommandResult::Publish(response) => { + SuiClientCommandResult::Publish(response) => { write!(writer, "{}", response)?; } - WalletCommandResult::Object(object_read) => { + SuiClientCommandResult::Object(object_read) => { let object = unwrap_err_to_string(|| Ok(object_read.object()?)); writeln!(writer, "{}", object)?; } - WalletCommandResult::Call(cert, effects) => { + SuiClientCommandResult::Call(cert, effects) => { write!(writer, "{}", write_cert_and_effects(cert, effects)?)?; } - WalletCommandResult::Transfer(time_elapsed, cert, effects) => { + SuiClientCommandResult::Transfer(time_elapsed, cert, effects) => { writeln!(writer, "Transfer confirmed after {} us", time_elapsed)?; write!(writer, "{}", write_cert_and_effects(cert, effects)?)?; } - WalletCommandResult::TransferSui(cert, effects) => { + SuiClientCommandResult::TransferSui(cert, effects) => { write!(writer, "{}", write_cert_and_effects(cert, effects)?)?; } - WalletCommandResult::Addresses(addresses) => { + SuiClientCommandResult::Addresses(addresses) => { writeln!(writer, "Showing {} results.", addresses.len())?; for address in addresses { writeln!(writer, "{}", address)?; } } - WalletCommandResult::Objects(object_refs) => { + SuiClientCommandResult::Objects(object_refs) => { writeln!( writer, " {0: ^42} | {1: ^10} | {2: ^44} | {3: ^15} | {4: ^40}", @@ -679,13 +667,13 @@ impl Display for WalletCommandResult { } writeln!(writer, "Showing {} results.", object_refs.len())?; } - WalletCommandResult::SyncClientState => { + SuiClientCommandResult::SyncClientState => { writeln!(writer, "Client state sync complete.")?; } - WalletCommandResult::NewAddress(address) => { + SuiClientCommandResult::NewAddress(address) => { writeln!(writer, "Created new keypair for address : {}", &address)?; } - WalletCommandResult::Gas(gases) => { + SuiClientCommandResult::Gas(gases) => { // TODO: generalize formatting of CLI writeln!( writer, @@ -706,22 +694,22 @@ impl Display for WalletCommandResult { )?; } } - WalletCommandResult::SplitCoin(response) => { + SuiClientCommandResult::SplitCoin(response) => { write!(writer, "{}", response)?; } - WalletCommandResult::MergeCoin(response) => { + SuiClientCommandResult::MergeCoin(response) => { write!(writer, "{}", response)?; } - WalletCommandResult::Switch(response) => { + SuiClientCommandResult::Switch(response) => { write!(writer, "{}", response)?; } - WalletCommandResult::ActiveAddress(response) => { + SuiClientCommandResult::ActiveAddress(response) => { match response { Some(r) => write!(writer, "{}", r)?, None => write!(writer, "None")?, }; } - WalletCommandResult::CreateExampleNFT(object_read) => { + SuiClientCommandResult::CreateExampleNFT(object_read) => { // TODO: display the content of the object let object = unwrap_err_to_string(|| Ok(object_read.object()?)); writeln!(writer, "{}\n", "Successfully created an ExampleNFT:".bold())?; @@ -796,10 +784,10 @@ fn write_cert_and_effects( Ok(writer) } -impl Debug for WalletCommandResult { +impl Debug for SuiClientCommandResult { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let s = unwrap_err_to_string(|| match self { - WalletCommandResult::Object(object_read) => { + SuiClientCommandResult::Object(object_read) => { let object = object_read.object()?; Ok(serde_json::to_string_pretty(&object)?) } @@ -816,7 +804,7 @@ fn unwrap_err_to_string Result>(fun } } -impl WalletCommandResult { +impl SuiClientCommandResult { pub fn print(&self, pretty: bool) { let line = if pretty { format!("{self}") @@ -834,7 +822,7 @@ impl WalletCommandResult { #[derive(Serialize)] #[serde(untagged)] -pub enum WalletCommandResult { +pub enum SuiClientCommandResult { Publish(PublishResponse), Object(GetObjectDataResponse), Call(SuiCertifiedTransaction, SuiTransactionEffects), diff --git a/crates/sui/src/config/mod.rs b/crates/sui/src/config/mod.rs index 690f7f4bd86..563ddbba56c 100644 --- a/crates/sui/src/config/mod.rs +++ b/crates/sui/src/config/mod.rs @@ -2,10 +2,10 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::keystore::KeystoreType; use serde::{Deserialize, Serialize}; use serde_with::{hex::Hex, serde_as}; use std::fmt::{Display, Formatter, Write}; +use sui_json_rpc_api::keystore::KeystoreType; use sui_types::base_types::*; pub use sui_config::Config; @@ -17,7 +17,7 @@ pub use sui_gateway::config::{GatewayConfig, GatewayType}; #[serde_as] #[derive(Serialize, Deserialize)] -pub struct WalletConfig { +pub struct SuiClientConfig { #[serde_as(as = "Vec")] pub accounts: Vec, pub keystore: KeystoreType, @@ -25,9 +25,9 @@ pub struct WalletConfig { pub active_address: Option, } -impl Config for WalletConfig {} +impl Config for SuiClientConfig {} -impl Display for WalletConfig { +impl Display for SuiClientConfig { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let mut writer = String::new(); diff --git a/crates/sui/src/console.rs b/crates/sui/src/console.rs new file mode 100644 index 00000000000..f3b46656b0f --- /dev/null +++ b/crates/sui/src/console.rs @@ -0,0 +1,137 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::client_commands::SwitchResponse; +use crate::client_commands::{SuiClientCommandResult, SuiClientCommands, WalletContext}; +use crate::shell::{ + install_shell_plugins, AsyncHandler, CacheKey, CommandStructure, CompletionCache, Shell, +}; +use async_trait::async_trait; +use clap::Command; +use clap::CommandFactory; +use clap::FromArgMatches; +use clap::Parser; +use colored::Colorize; +use std::io::{stderr, Write}; +use std::ops::Deref; +const SUI: &str = " _____ _ ______ __ + / ___/__ __(_) / ____/___ ____ _________ / /__ + \\__ \\/ / / / / / / / __ \\/ __ \\/ ___/ __ \\/ / _ \\ + ___/ / /_/ / / / /___/ /_/ / / / (__ ) /_/ / / __/ +/____/\\__,_/_/ \\____/\\____/_/ /_/____/\\____/_/\\___/"; + +#[derive(Parser)] +#[clap(name = "", rename_all = "kebab-case", no_binary_name = true)] +pub struct ConsoleOpts { + #[clap(subcommand)] + pub command: SuiClientCommands, + /// Returns command outputs in JSON format. + #[clap(long, global = true)] + pub json: bool, +} + +pub async fn start_console( + context: WalletContext, + out: &mut dyn Write, + err: &mut dyn Write, +) -> Result<(), anyhow::Error> { + let app: Command = SuiClientCommands::command(); + writeln!(out, "{}", SUI.cyan().bold())?; + let mut version = app + .get_long_version() + .unwrap_or_else(|| app.get_version().unwrap_or("unknown")) + .to_owned(); + if let Some(git_rev) = std::option_env!("GIT_REVISION") { + version.push('-'); + version.push_str(git_rev); + } + writeln!(out, "--- Sui Console {version} ---")?; + writeln!(out)?; + writeln!(out, "{}", context.config.deref())?; + writeln!(out, "Welcome to the Sui interactive console.")?; + writeln!(out)?; + + let mut shell = Shell::new( + "sui>-$ ".bold().green(), + context, + ClientCommandHandler, + CommandStructure::from_clap(&install_shell_plugins(app)), + ); + + shell.run_async(out, err).await +} + +struct ClientCommandHandler; + +#[async_trait] +impl AsyncHandler for ClientCommandHandler { + async fn handle_async( + &self, + args: Vec, + context: &mut WalletContext, + completion_cache: CompletionCache, + ) -> bool { + match handle_command(get_command(args), context, completion_cache).await { + Err(e) => { + let _err = writeln!(stderr(), "{}", e.to_string().red()); + false + } + Ok(return_value) => return_value, + } + } +} + +fn get_command(args: Vec) -> Result { + let app: Command = install_shell_plugins(ConsoleOpts::command()); + Ok(ConsoleOpts::from_arg_matches( + &app.try_get_matches_from(args)?, + )?) +} + +async fn handle_command( + wallet_opts: Result, + context: &mut WalletContext, + completion_cache: CompletionCache, +) -> Result { + let wallet_opts = wallet_opts?; + let result = wallet_opts.command.execute(context).await?; + + // Update completion cache + // TODO: Completion data are keyed by strings, are there ways to make it more error proof? + if let Ok(mut cache) = completion_cache.write() { + match result { + SuiClientCommandResult::Addresses(ref addresses) => { + let addresses = addresses + .iter() + .map(|addr| format!("{addr}")) + .collect::>(); + cache.insert(CacheKey::flag("--address"), addresses.clone()); + cache.insert(CacheKey::flag("--to"), addresses); + } + SuiClientCommandResult::Objects(ref objects) => { + let objects = objects + .iter() + .map(|oref| format!("{}", oref.object_id)) + .collect::>(); + cache.insert(CacheKey::new("object", "--id"), objects.clone()); + cache.insert(CacheKey::flag("--gas"), objects.clone()); + cache.insert(CacheKey::flag("--coin-object-id"), objects); + } + _ => {} + } + } + result.print(!wallet_opts.json); + + // Quit shell after gateway switch + if matches!( + result, + SuiClientCommandResult::Switch(SwitchResponse { + gateway: Some(_), + .. + }) + ) { + println!("Gateway switch completed, please restart Sui console."); + return Ok(true); + } + Ok(false) +} diff --git a/crates/sui/src/keytool.rs b/crates/sui/src/keytool.rs new file mode 100644 index 00000000000..5ba835a9d04 --- /dev/null +++ b/crates/sui/src/keytool.rs @@ -0,0 +1,92 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::anyhow; +use clap::*; +use std::fs; +use std::path::Path; +use sui_json_rpc_api::keystore::{Keystore, SuiKeystore}; +use sui_types::base_types::decode_bytes_hex; +use sui_types::sui_serde::{Base64, Encoding}; +use sui_types::{ + base_types::SuiAddress, + crypto::{get_key_pair, KeyPair}, +}; +use tracing::info; + +#[allow(clippy::large_enum_variant)] +#[derive(Subcommand)] +#[clap(rename_all = "kebab-case")] +pub enum KeyToolCommand { + /// Generate a new keypair + Generate, + /// Extract components + Unpack { keypair: KeyPair }, + /// List all keys in the keystore + List, + /// Create signature using the sui keystore and provided data. + Sign { + #[clap(long, parse(try_from_str = decode_bytes_hex))] + address: SuiAddress, + #[clap(long)] + data: String, + }, +} + +impl KeyToolCommand { + pub fn execute(self, keystore: SuiKeystore) -> Result<(), anyhow::Error> { + match self { + KeyToolCommand::Generate => { + let (address, keypair) = get_key_pair(); + store_and_print_keypair(address, keypair) + } + KeyToolCommand::Unpack { keypair } => { + store_and_print_keypair(SuiAddress::from(keypair.public_key_bytes()), keypair) + } + KeyToolCommand::List => { + println!( + " {0: ^42} | {1: ^45} ", + "Sui Address", "Public Key (Base64)" + ); + println!("{}", ["-"; 91].join("")); + for keypair in keystore.key_pairs() { + println!( + " {0: ^42} | {1: ^45} ", + SuiAddress::from(keypair.public_key_bytes()), + Base64::encode(keypair.public_key_bytes().to_vec()), + ); + } + } + KeyToolCommand::Sign { address, data } => { + info!("Data to sign : {}", data); + info!("Address : {}", address); + let message = Base64::decode(&data).map_err(|e| anyhow!(e))?; + let signature = keystore.sign(&address, &message)?; + // Separate pub key and signature string, signature and pub key are concatenated with an '@' symbol. + let signature_string = format!("{:?}", signature); + let sig_split = signature_string.split('@').collect::>(); + let signature = sig_split + .first() + .ok_or_else(|| anyhow!("Error creating signature."))?; + let pub_key = sig_split + .last() + .ok_or_else(|| anyhow!("Error creating signature."))?; + info!("Public Key Base64: {}", pub_key); + info!("Signature : {}", signature); + } + } + + Ok(()) + } +} + +fn store_and_print_keypair(address: SuiAddress, keypair: KeyPair) { + let path_str = format!("{}.key", address).to_lowercase(); + let path = Path::new(&path_str); + let address = format!("{}", address); + let kp = serde_json::to_string(&keypair).unwrap(); + let kp = &kp[1..kp.len() - 1]; + let out_str = format!("address: {}\nkeypair: {}", address, kp); + fs::write(path, out_str).unwrap(); + println!("Address and keypair written to {}", path.to_str().unwrap()); +} diff --git a/crates/sui/src/lib.rs b/crates/sui/src/lib.rs index dbdb34261ea..c56d139177b 100644 --- a/crates/sui/src/lib.rs +++ b/crates/sui/src/lib.rs @@ -2,9 +2,10 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -pub mod benchmark; +pub mod client_commands; pub mod config; -pub mod keystore; +pub mod console; +pub mod keytool; pub mod shell; pub mod sui_commands; -pub mod wallet_commands; +pub mod sui_move; diff --git a/crates/sui/src/main.rs b/crates/sui/src/main.rs new file mode 100644 index 00000000000..a00524f36de --- /dev/null +++ b/crates/sui/src/main.rs @@ -0,0 +1,34 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 +extern crate core; + +use clap::*; +use colored::Colorize; +use sui::sui_commands::SuiCommand; +use sui_types::exit_main; +use tracing::debug; +#[cfg(test)] +#[path = "unit_tests/cli_tests.rs"] +mod cli_tests; + +#[tokio::main] +async fn main() { + let bin_name = env!("CARGO_BIN_NAME"); + let cmd: SuiCommand = SuiCommand::parse(); + let _guard = match cmd { + SuiCommand::Console { .. } | SuiCommand::Client { .. } => { + telemetry_subscribers::TelemetryConfig::new(bin_name) + .with_log_file(&format!("{bin_name}.log")) + .with_env() + .init() + } + _ => telemetry_subscribers::TelemetryConfig::new(bin_name) + .with_env() + .init(), + }; + + if let Some(git_rev) = option_env!("GIT_REVISION") { + debug!("Sui CLI built at git revision {git_rev}"); + } + exit_main!(cmd.execute().await); +} diff --git a/crates/sui/src/sui_commands.rs b/crates/sui/src/sui_commands.rs index c17d18ac325..1b2b55a33e1 100644 --- a/crates/sui/src/sui_commands.rs +++ b/crates/sui/src/sui_commands.rs @@ -1,42 +1,52 @@ // Copyright (c) 2022, Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -use crate::{ - config::{GatewayConfig, GatewayType, WalletConfig}, - keystore::{Keystore, KeystoreType, SuiKeystore}, -}; + +use crate::client_commands::{SuiClientCommands, WalletContext}; +use crate::config::{GatewayConfig, GatewayType, SuiClientConfig}; +use crate::console::start_console; +use crate::keytool::KeyToolCommand; +use crate::sui_move::MoveCommands; use anyhow::{anyhow, bail}; -use base64ct::{Base64, Encoding}; use clap::*; -use std::fs; +use std::io::{stderr, stdout, Write}; use std::num::NonZeroUsize; -use std::path::PathBuf; -use sui_config::{builder::ConfigBuilder, NetworkConfig}; +use std::path::{Path, PathBuf}; +use std::{fs, io}; +use sui_config::{builder::ConfigBuilder, NetworkConfig, SUI_DEV_NET_URL, SUI_KEYSTORE_FILENAME}; use sui_config::{genesis_config::GenesisConfig, SUI_GENESIS_FILENAME}; use sui_config::{ - sui_config_dir, Config, PersistedConfig, SUI_FULLNODE_CONFIG, SUI_GATEWAY_CONFIG, - SUI_NETWORK_CONFIG, SUI_WALLET_CONFIG, + sui_config_dir, Config, PersistedConfig, SUI_CLIENT_CONFIG, SUI_FULLNODE_CONFIG, + SUI_GATEWAY_CONFIG, SUI_NETWORK_CONFIG, }; +use sui_json_rpc_api::client::SuiRpcClient; +use sui_json_rpc_api::keystore::{KeystoreType, SuiKeystore}; use sui_swarm::memory::Swarm; -use sui_types::base_types::decode_bytes_hex; use sui_types::base_types::SuiAddress; use tracing::info; #[derive(Parser)] -#[clap(rename_all = "kebab-case")] +#[clap( + name = "sui", + about = "A Byzantine fault tolerant chain with low-latency finality and high throughput", + rename_all = "kebab-case", + author, + version +)] pub enum SuiCommand { /// Start sui network. #[clap(name = "start")] Start { - #[clap(long)] + #[clap(long = "network.config")] config: Option, }, #[clap(name = "network")] Network { - #[clap(long)] + #[clap(long = "network.config")] config: Option, #[clap(short, long, help = "Dump the public keys of all authorities")] dump_addresses: bool, }, + /// Bootstrap and initialize a new sui network #[clap(name = "genesis")] Genesis { #[clap(long, help = "Start genesis with a given config file")] @@ -51,19 +61,52 @@ pub enum SuiCommand { #[clap(short, long, help = "Forces overwriting existing configuration")] force: bool, }, - #[clap(name = "signtool")] - SignTool { + /// Sui keystore tool. + #[clap(name = "keytool")] + KeyTool { #[clap(long)] keystore_path: Option, - #[clap(long, parse(try_from_str = decode_bytes_hex))] - address: SuiAddress, + /// Subcommands. + #[clap(subcommand)] + cmd: KeyToolCommand, + }, + /// Start Sui interactive console. + #[clap(name = "console")] + Console { + /// Sets the file storing the state of our user accounts (an empty one will be created if missing) + #[clap(long = "client.config")] + config: Option, + }, + /// Client for interacting with the Sui network. + #[clap(name = "client")] + Client { + /// Sets the file storing the state of our user accounts (an empty one will be created if missing) + #[clap(long = "client.config")] + config: Option, + #[clap(subcommand)] + cmd: Option, + /// Return command outputs in json format. + #[clap(long, global = true)] + json: bool, + }, + + /// Tool to build and test Move applications. + #[clap(name = "move")] + Move { + /// Path to the Move project root. + #[clap(long, default_value = "./")] + path: String, + /// Whether we are building/testing the std/framework code. #[clap(long)] - data: String, + std: bool, + /// Subcommands. + #[clap(subcommand)] + cmd: MoveCommands, }, } impl SuiCommand { - pub async fn execute(&self) -> Result<(), anyhow::Error> { + pub async fn execute(self) -> Result<(), anyhow::Error> { match self { SuiCommand::Start { config } => { // Load the config of the Sui authority. @@ -95,9 +138,7 @@ impl SuiCommand { config, dump_addresses, } => { - let config_path = config - .clone() - .unwrap_or(sui_config_dir()?.join(SUI_NETWORK_CONFIG)); + let config_path = config.unwrap_or(sui_config_dir()?.join(SUI_NETWORK_CONFIG)); let config: NetworkConfig = PersistedConfig::read(&config_path).map_err(|err| { err.context(format!( "Cannot open Sui network config file at {:?}", @@ -105,7 +146,7 @@ impl SuiCommand { )) })?; - if *dump_addresses { + if dump_addresses { for validator in config.validator_configs() { println!( "{} - {}", @@ -125,7 +166,7 @@ impl SuiCommand { let sui_config_dir = &match working_dir { // if a directory is specified, it must exist (it // will not be created) - Some(v) => v.clone(), + Some(v) => v, // create default Sui config dir if not specified // on the command line and if it does not exist // yet @@ -149,7 +190,7 @@ impl SuiCommand { .next() .is_some() { - if *force { + if force { fs::remove_dir_all(sui_config_dir).map_err(|err| { anyhow!(err).context(format!( "Cannot remove Sui config dir {:?}", @@ -169,19 +210,19 @@ impl SuiCommand { let network_path = sui_config_dir.join(SUI_NETWORK_CONFIG); let genesis_path = sui_config_dir.join(SUI_GENESIS_FILENAME); - let wallet_path = sui_config_dir.join(SUI_WALLET_CONFIG); + let client_path = sui_config_dir.join(SUI_CLIENT_CONFIG); let gateway_path = sui_config_dir.join(SUI_GATEWAY_CONFIG); - let keystore_path = sui_config_dir.join("wallet.key"); + let keystore_path = sui_config_dir.join(SUI_KEYSTORE_FILENAME); let db_folder_path = sui_config_dir.join("client_db"); let gateway_db_folder_path = sui_config_dir.join("gateway_client_db"); let mut genesis_conf = match from_config { - Some(q) => PersistedConfig::read(q)?, + Some(path) => PersistedConfig::read(&path)?, None => GenesisConfig::for_local_testing(), }; if let Some(path) = write_config { - let persisted = genesis_conf.persisted(path); + let persisted = genesis_conf.persisted(&path); persisted.save()?; return Ok(()); } @@ -218,7 +259,7 @@ impl SuiCommand { keystore.set_path(&keystore_path); keystore.save()?; - info!("Wallet keystore is stored in {:?}.", keystore_path); + info!("Client keystore is stored in {:?}.", keystore_path); // Use the first address if any let active_address = accounts.get(0).copied(); @@ -239,15 +280,15 @@ impl SuiCommand { ..Default::default() }; - let wallet_config = WalletConfig { + let wallet_config = SuiClientConfig { accounts, keystore: KeystoreType::File(keystore_path), gateway: GatewayType::Embedded(wallet_gateway_config), active_address, }; - wallet_config.save(&wallet_path)?; - info!("Wallet config file is stored in {:?}.", wallet_path); + wallet_config.save(&client_path)?; + info!("Client config file is stored in {:?}.", client_path); let mut fullnode_config = network_config.generate_fullnode_config(); fullnode_config.json_rpc_address = sui_config::node::default_json_rpc_address(); @@ -265,32 +306,101 @@ impl SuiCommand { Ok(()) } - SuiCommand::SignTool { - keystore_path, - address, - data, - } => { - let keystore_path = keystore_path - .clone() - .unwrap_or(sui_config_dir()?.join("wallet.key")); + SuiCommand::KeyTool { keystore_path, cmd } => { + let keystore_path = + keystore_path.unwrap_or(sui_config_dir()?.join(SUI_KEYSTORE_FILENAME)); let keystore = SuiKeystore::load_or_create(&keystore_path)?; - info!("Data to sign : {}", data); - info!("Address : {}", address); - let message = Base64::decode_vec(data).map_err(|e| anyhow!(e))?; - let signature = keystore.sign(address, &message)?; - // Separate pub key and signature string, signature and pub key are concatenated with an '@' symbol. - let signature_string = format!("{:?}", signature); - let sig_split = signature_string.split('@').collect::>(); - let signature = sig_split - .first() - .ok_or_else(|| anyhow!("Error creating signature."))?; - let pub_key = sig_split - .last() - .ok_or_else(|| anyhow!("Error creating signature."))?; - info!("Public Key Base64: {}", pub_key); - info!("Signature : {}", signature); + cmd.execute(keystore) + } + SuiCommand::Console { config } => { + let config = config.unwrap_or(sui_config_dir()?.join(SUI_CLIENT_CONFIG)); + prompt_if_no_config(&config)?; + let mut context = WalletContext::new(&config)?; + sync_accounts(&mut context).await?; + start_console(context, &mut stdout(), &mut stderr()).await + } + SuiCommand::Client { config, cmd, json } => { + let config = config.unwrap_or(sui_config_dir()?.join(SUI_CLIENT_CONFIG)); + prompt_if_no_config(&config)?; + let mut context = WalletContext::new(&config)?; + + if let Some(cmd) = cmd { + // Do not sync if command is a gateway switch, as the current gateway might be unreachable and causes sync to panic. + if !matches!( + cmd, + SuiClientCommands::Switch { + gateway: Some(_), + .. + } + ) { + sync_accounts(&mut context).await?; + } + cmd.execute(&mut context).await?.print(!json); + } else { + // Print help + let mut app: Command = SuiCommand::command(); + app.build(); + app.find_subcommand_mut("client").unwrap().print_help()?; + } Ok(()) } + SuiCommand::Move { path, std, cmd } => cmd.execute(path.as_ref(), std), + } + } +} + +// Sync all accounts on start up. +async fn sync_accounts(context: &mut WalletContext) -> Result<(), anyhow::Error> { + for address in context.config.accounts.clone() { + SuiClientCommands::SyncClientState { + address: Some(address), + } + .execute(context) + .await?; + } + Ok(()) +} + +fn prompt_if_no_config(wallet_conf_path: &Path) -> Result<(), anyhow::Error> { + // Prompt user for connect to gateway if config not exists. + if !wallet_conf_path.exists() { + print!( + "Config file [{:?}] doesn't exist, do you want to connect to a Sui RPC server [yN]?", + wallet_conf_path + ); + if matches!(read_line(), Ok(line) if line.trim().to_lowercase() == "y") { + print!("Sui RPC server Url (Default to Sui DevNet if not specified) : "); + let url = read_line()?; + let url = if url.trim().is_empty() { + SUI_DEV_NET_URL + } else { + &url + }; + + // Check url is valid + SuiRpcClient::new(url)?; + let keystore_path = wallet_conf_path + .parent() + .unwrap_or(&sui_config_dir()?) + .join(SUI_KEYSTORE_FILENAME); + let keystore = KeystoreType::File(keystore_path); + let new_address = keystore.init()?.add_random_key()?; + SuiClientConfig { + accounts: vec![new_address], + keystore, + gateway: GatewayType::RPC(url.to_string()), + active_address: Some(new_address), + } + .persisted(wallet_conf_path) + .save()?; } } + Ok(()) +} + +fn read_line() -> Result { + let mut s = String::new(); + let _ = stdout().flush(); + io::stdin().read_line(&mut s)?; + Ok(s.trim_end().to_string()) } diff --git a/crates/sui/src/bin/sui-move.rs b/crates/sui/src/sui_move.rs similarity index 73% rename from crates/sui/src/bin/sui-move.rs rename to crates/sui/src/sui_move.rs index fd7f59a9ebc..3dbb889e91c 100644 --- a/crates/sui/src/bin/sui-move.rs +++ b/crates/sui/src/sui_move.rs @@ -5,9 +5,8 @@ use clap::*; use colored::Colorize; use move_unit_test::UnitTestingConfig; use std::path::Path; -use sui_types::exit_main; -#[derive(Parser)] +#[derive(Subcommand)] #[clap(rename_all = "kebab-case")] pub enum MoveCommands { /// Build and verify Move project @@ -56,27 +55,3 @@ impl MoveCommands { Ok(()) } } - -#[derive(Parser)] -#[clap( - name = "Sui Move Development Tool", - about = "Tool to build and test Move applications", - rename_all = "kebab-case" -)] -struct MoveOpt { - /// Path to the Move project root. - #[clap(long, default_value = "./")] - path: String, - /// Whether we are building/testing the std/framework code. - #[clap(long)] - std: bool, - /// Subcommands. - #[clap(subcommand)] - cmd: MoveCommands, -} - -fn main() { - let options = MoveOpt::parse(); - let path = options.path; - exit_main!(options.cmd.execute(path.as_ref(), options.std)) -} diff --git a/crates/sui/src/unit_tests/cli_tests.rs b/crates/sui/src/unit_tests/cli_tests.rs index be8636dddb4..144c6f9ef1b 100644 --- a/crates/sui/src/unit_tests/cli_tests.rs +++ b/crates/sui/src/unit_tests/cli_tests.rs @@ -6,19 +6,19 @@ use std::{fmt::Write, fs::read_dir, path::PathBuf, str, time::Duration}; use anyhow::anyhow; use serde_json::{json, Value}; -use sui::wallet_commands::SwitchResponse; +use sui::client_commands::SwitchResponse; use sui::{ - config::{GatewayConfig, GatewayType, WalletConfig}, - keystore::KeystoreType, + client_commands::{SuiClientCommandResult, SuiClientCommands, WalletContext}, + config::{GatewayConfig, GatewayType, SuiClientConfig}, sui_commands::SuiCommand, - wallet_commands::{WalletCommandResult, WalletCommands, WalletContext}, }; use sui_config::genesis_config::{AccountConfig, GenesisConfig, ObjectConfig}; use sui_config::{ - Config, NetworkConfig, PersistedConfig, ValidatorInfo, SUI_FULLNODE_CONFIG, SUI_GATEWAY_CONFIG, - SUI_GENESIS_FILENAME, SUI_NETWORK_CONFIG, SUI_WALLET_CONFIG, + Config, NetworkConfig, PersistedConfig, ValidatorInfo, SUI_CLIENT_CONFIG, SUI_FULLNODE_CONFIG, + SUI_GATEWAY_CONFIG, SUI_GENESIS_FILENAME, SUI_KEYSTORE_FILENAME, SUI_NETWORK_CONFIG, }; use sui_json::SuiJsonValue; +use sui_json_rpc_api::keystore::KeystoreType; use sui_json_rpc_api::rpc_types::{GetObjectDataResponse, SuiParsedObject, SuiTransactionEffects}; use sui_types::{ base_types::{ObjectID, SuiAddress}, @@ -59,13 +59,13 @@ async fn test_genesis() -> Result<(), anyhow::Error> { .collect::>(); assert_eq!(10, files.len()); - assert!(files.contains(&SUI_WALLET_CONFIG.to_string())); + assert!(files.contains(&SUI_CLIENT_CONFIG.to_string())); assert!(files.contains(&SUI_GATEWAY_CONFIG.to_string())); assert!(files.contains(&SUI_NETWORK_CONFIG.to_string())); assert!(files.contains(&SUI_FULLNODE_CONFIG.to_string())); assert!(files.contains(&SUI_GENESIS_FILENAME.to_string())); - assert!(files.contains(&"wallet.key".to_string())); + assert!(files.contains(&SUI_KEYSTORE_FILENAME.to_string())); // Check network config let network_conf = @@ -73,7 +73,8 @@ async fn test_genesis() -> Result<(), anyhow::Error> { assert_eq!(4, network_conf.validator_configs().len()); // Check wallet config - let wallet_conf = PersistedConfig::::read(&working_dir.join(SUI_WALLET_CONFIG))?; + let wallet_conf = + PersistedConfig::::read(&working_dir.join(SUI_CLIENT_CONFIG))?; if let GatewayType::Embedded(config) = &wallet_conf.gateway { assert_eq!(4, config.validator_set.len()); @@ -104,9 +105,9 @@ async fn test_addresses_command() -> Result<(), anyhow::Error> { let temp_dir = tempfile::tempdir().unwrap(); let working_dir = temp_dir.path(); - let wallet_config = WalletConfig { + let wallet_config = SuiClientConfig { accounts: vec![], - keystore: KeystoreType::File(working_dir.join("wallet.key")), + keystore: KeystoreType::File(working_dir.join(SUI_KEYSTORE_FILENAME)), gateway: GatewayType::Embedded(GatewayConfig { db_folder_path: working_dir.join("client_db"), validator_set: vec![ValidatorInfo { @@ -118,7 +119,7 @@ async fn test_addresses_command() -> Result<(), anyhow::Error> { }), active_address: None, }; - let wallet_conf_path = working_dir.join(SUI_WALLET_CONFIG); + let wallet_conf_path = working_dir.join(SUI_CLIENT_CONFIG); let mut wallet_config = wallet_config.persisted(&wallet_conf_path); // Add 3 accounts @@ -133,7 +134,7 @@ async fn test_addresses_command() -> Result<(), anyhow::Error> { let mut context = WalletContext::new(&wallet_conf_path).unwrap(); // Print all addresses - WalletCommands::Addresses + SuiClientCommands::Addresses .execute(&mut context) .await .unwrap() @@ -147,7 +148,7 @@ async fn test_objects_command() -> Result<(), anyhow::Error> { let (_network, mut context, address) = setup_network_and_wallet().await?; // Print objects owned by `address` - WalletCommands::Objects { + SuiClientCommands::Objects { address: Some(address), } .execute(&mut context) @@ -166,7 +167,7 @@ async fn test_objects_command() -> Result<(), anyhow::Error> { async fn test_create_example_nft_command() -> Result<(), anyhow::Error> { let (_network, mut context, address) = setup_network_and_wallet().await?; - let result = WalletCommands::CreateExampleNFT { + let result = SuiClientCommands::CreateExampleNFT { name: None, description: None, url: None, @@ -177,7 +178,7 @@ async fn test_create_example_nft_command() -> Result<(), anyhow::Error> { .await?; match result { - WalletCommandResult::CreateExampleNFT(GetObjectDataResponse::Exists(obj)) => { + SuiClientCommandResult::CreateExampleNFT(GetObjectDataResponse::Exists(obj)) => { assert_eq!(obj.owner, address); assert_eq!(obj.data.type_().unwrap(), "0x2::devnet_nft::DevNetNFT"); Ok(obj) @@ -210,12 +211,12 @@ async fn test_custom_genesis() -> Result<(), anyhow::Error> { let network = start_test_network(Some(config)).await?; // Wallet config - let mut context = WalletContext::new(&network.dir().join(SUI_WALLET_CONFIG))?; + let mut context = WalletContext::new(&network.dir().join(SUI_CLIENT_CONFIG))?; assert_eq!(1, context.config.accounts.len()); let address = context.config.accounts.first().cloned().unwrap(); // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(&mut context) @@ -223,7 +224,7 @@ async fn test_custom_genesis() -> Result<(), anyhow::Error> { .print(true); // Print objects owned by `address` - WalletCommands::Objects { + SuiClientCommands::Objects { address: Some(address), } .execute(&mut context) @@ -254,7 +255,7 @@ async fn test_custom_genesis_with_custom_move_package() -> Result<(), anyhow::Er PersistedConfig::::read(&network.dir().join(SUI_NETWORK_CONFIG))?; // Create Wallet context. - let wallet_conf_path = network.dir().join(SUI_WALLET_CONFIG); + let wallet_conf_path = network.dir().join(SUI_CLIENT_CONFIG); let mut context = WalletContext::new(&wallet_conf_path)?; // Make sure init() is executed correctly for custom_genesis_package_2::M1 @@ -276,7 +277,7 @@ async fn test_object_info_get_command() -> Result<(), anyhow::Error> { // Check log output contains all object ids. let object_id = object_refs.first().unwrap().object_id; - WalletCommands::Object { id: object_id } + SuiClientCommands::Object { id: object_id } .execute(&mut context) .await? .print(true); @@ -297,7 +298,7 @@ async fn test_gas_command() -> Result<(), anyhow::Error> { let object_id = object_refs.first().unwrap().object_id; let object_to_send = object_refs.get(1).unwrap().object_id; - WalletCommands::Gas { + SuiClientCommands::Gas { address: Some(address), } .execute(&mut context) @@ -307,7 +308,7 @@ async fn test_gas_command() -> Result<(), anyhow::Error> { tokio::time::sleep(Duration::from_millis(100)).await; // Send an object - WalletCommands::Transfer { + SuiClientCommands::Transfer { to: recipient, coin_object_id: object_to_send, gas: Some(object_id), @@ -317,7 +318,7 @@ async fn test_gas_command() -> Result<(), anyhow::Error> { .await?; // Fetch gas again - WalletCommands::Gas { + SuiClientCommands::Gas { address: Some(address), } .execute(&mut context) @@ -344,7 +345,7 @@ async fn get_move_objects( address: SuiAddress, ) -> Result, anyhow::Error> { // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(context) @@ -352,14 +353,14 @@ async fn get_move_objects( .print(true); // Fetch objects owned by `address` - let objects_result = WalletCommands::Objects { + let objects_result = SuiClientCommands::Objects { address: Some(address), } .execute(context) .await?; match objects_result { - WalletCommandResult::Objects(object_refs) => { + SuiClientCommandResult::Objects(object_refs) => { let mut objs = vec![]; for oref in object_refs { objs.push(( @@ -380,10 +381,10 @@ async fn get_move_object( context: &mut WalletContext, id: ObjectID, ) -> Result { - let obj = WalletCommands::Object { id }.execute(context).await?; + let obj = SuiClientCommands::Object { id }.execute(context).await?; match obj { - WalletCommandResult::Object(obj) => match obj { + SuiClientCommandResult::Object(obj) => match obj { GetObjectDataResponse::Exists(obj) => Ok(serde_json::to_value(obj)?), _ => panic!("WalletCommands::Object returns wrong type"), }, @@ -398,7 +399,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { let address2 = context.config.accounts.get(1).cloned().unwrap(); // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address2), } .execute(&mut context) @@ -406,7 +407,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { .print(true); // Print objects owned by `address1` - WalletCommands::Objects { + SuiClientCommands::Objects { address: Some(address1), } .execute(&mut context) @@ -436,7 +437,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { } // Test case with no gas specified - let resp = WalletCommands::Call { + let resp = SuiClientCommands::Call { package: ObjectID::from_hex_literal("0x2").unwrap(), module: "object_basics".to_string(), function: "create".to_string(), @@ -450,7 +451,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { resp.print(true); // Get the created object - let created_obj: ObjectID = if let WalletCommandResult::Call( + let created_obj: ObjectID = if let SuiClientCommandResult::Call( _, SuiTransactionEffects { created: new_objs, .. @@ -476,7 +477,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { args.push(SuiJsonValue::new(a.clone()).unwrap()); } - let resp = WalletCommands::Call { + let resp = SuiClientCommands::Call { package: ObjectID::from_hex_literal("0x2").unwrap(), module: "object_basics".to_string(), function: "create".to_string(), @@ -504,7 +505,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { args.push(SuiJsonValue::new(a.clone()).unwrap()); } - let resp = WalletCommands::Call { + let resp = SuiClientCommands::Call { package: ObjectID::from_hex_literal("0x2").unwrap(), module: "object_basics".to_string(), function: "transfer".to_string(), @@ -531,7 +532,7 @@ async fn test_move_call_args_linter_command() -> Result<(), anyhow::Error> { args.push(SuiJsonValue::new(a.clone()).unwrap()); } - WalletCommands::Call { + SuiClientCommands::Call { package: ObjectID::from_hex_literal("0x2").unwrap(), module: "object_basics".to_string(), function: "transfer".to_string(), @@ -563,7 +564,7 @@ async fn test_package_publish_command() -> Result<(), anyhow::Error> { let mut path = TEST_DATA_DIR.to_owned(); path.push_str("dummy_modules_publish"); - let resp = WalletCommands::Publish { + let resp = SuiClientCommands::Publish { path, gas: Some(gas_obj_id), gas_budget: 1000, @@ -574,7 +575,7 @@ async fn test_package_publish_command() -> Result<(), anyhow::Error> { // Print it out to CLI/logs resp.print(true); - let (package, created_obj) = if let WalletCommandResult::Publish(response) = resp { + let (package, created_obj) = if let SuiClientCommandResult::Publish(response) = resp { ( response.package, response.created_objects[0].reference.clone(), @@ -584,24 +585,24 @@ async fn test_package_publish_command() -> Result<(), anyhow::Error> { }; // Check the objects - let resp = WalletCommands::Object { + let resp = SuiClientCommands::Object { id: package.object_id, } .execute(&mut context) .await?; assert!(matches!( resp, - WalletCommandResult::Object(GetObjectDataResponse::Exists(..)) + SuiClientCommandResult::Object(GetObjectDataResponse::Exists(..)) )); - let resp = WalletCommands::Object { + let resp = SuiClientCommands::Object { id: created_obj.object_id, } .execute(&mut context) .await?; assert!(matches!( resp, - WalletCommandResult::Object(GetObjectDataResponse::Exists(..)) + SuiClientCommandResult::Object(GetObjectDataResponse::Exists(..)) )); Ok(()) @@ -622,7 +623,7 @@ async fn test_native_transfer() -> Result<(), anyhow::Error> { let gas_obj_id = object_refs.first().unwrap().object_id; let obj_id = object_refs.get(1).unwrap().object_id; - let resp = WalletCommands::Transfer { + let resp = SuiClientCommands::Transfer { gas: Some(gas_obj_id), to: recipient, coin_object_id: obj_id, @@ -636,7 +637,8 @@ async fn test_native_transfer() -> Result<(), anyhow::Error> { // Get the mutated objects let (mut_obj1, mut_obj2) = - if let WalletCommandResult::Transfer(_, _, SuiTransactionEffects { mutated, .. }) = resp { + if let SuiClientCommandResult::Transfer(_, _, SuiTransactionEffects { mutated, .. }) = resp + { ( mutated.get(0).unwrap().reference.object_id, mutated.get(1).unwrap().reference.object_id, @@ -647,13 +649,13 @@ async fn test_native_transfer() -> Result<(), anyhow::Error> { }; // Sync both to fetch objects - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(&mut context) .await? .print(true); - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(recipient), } .execute(&mut context) @@ -661,29 +663,29 @@ async fn test_native_transfer() -> Result<(), anyhow::Error> { .print(true); // Check the objects - let resp = WalletCommands::Object { id: mut_obj1 } + let resp = SuiClientCommands::Object { id: mut_obj1 } .execute(&mut context) .await?; - let mut_obj1 = if let WalletCommandResult::Object(GetObjectDataResponse::Exists(object)) = resp - { - object - } else { - // Fail this way because Panic! causes test issues - assert!(false); - panic!() - }; + let mut_obj1 = + if let SuiClientCommandResult::Object(GetObjectDataResponse::Exists(object)) = resp { + object + } else { + // Fail this way because Panic! causes test issues + assert!(false); + panic!() + }; - let resp = WalletCommands::Object { id: mut_obj2 } + let resp = SuiClientCommands::Object { id: mut_obj2 } .execute(&mut context) .await?; - let mut_obj2 = if let WalletCommandResult::Object(GetObjectDataResponse::Exists(object)) = resp - { - object - } else { - // Fail this way because Panic! causes test issues - assert!(false); - panic!() - }; + let mut_obj2 = + if let SuiClientCommandResult::Object(GetObjectDataResponse::Exists(object)) = resp { + object + } else { + // Fail this way because Panic! causes test issues + assert!(false); + panic!() + }; let (gas, obj) = if mut_obj1.owner.get_owner_address().unwrap() == address { (mut_obj1, mut_obj2) @@ -695,7 +697,7 @@ async fn test_native_transfer() -> Result<(), anyhow::Error> { assert_eq!(obj.owner.get_owner_address().unwrap(), recipient); // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(&mut context) @@ -710,7 +712,7 @@ async fn test_native_transfer() -> Result<(), anyhow::Error> { // Check log output contains all object ids. let obj_id = object_refs.get(1).unwrap().object_id; - let resp = WalletCommands::Transfer { + let resp = SuiClientCommands::Transfer { gas: None, to: recipient, coin_object_id: obj_id, @@ -724,7 +726,8 @@ async fn test_native_transfer() -> Result<(), anyhow::Error> { // Get the mutated objects let (_mut_obj1, _mut_obj2) = - if let WalletCommandResult::Transfer(_, _, SuiTransactionEffects { mutated, .. }) = resp { + if let SuiClientCommandResult::Transfer(_, _, SuiTransactionEffects { mutated, .. }) = resp + { ( mutated.get(0).unwrap().reference.object_id, mutated.get(1).unwrap().reference.object_id, @@ -740,7 +743,7 @@ async fn test_native_transfer() -> Result<(), anyhow::Error> { #[test] // Test for issue https://github.com/MystenLabs/sui/issues/1078 fn test_bug_1078() { - let read = WalletCommandResult::Object(GetObjectDataResponse::NotExists(ObjectID::random())); + let read = SuiClientCommandResult::Object(GetObjectDataResponse::NotExists(ObjectID::random())); let mut writer = String::new(); // fmt ObjectRead should not fail. write!(writer, "{}", read).unwrap(); @@ -753,7 +756,7 @@ async fn test_switch_command() -> Result<(), anyhow::Error> { let network = start_test_network(None).await?; // Create Wallet context. - let wallet_conf = network.dir().join(SUI_WALLET_CONFIG); + let wallet_conf = network.dir().join(SUI_CLIENT_CONFIG); let mut context = WalletContext::new(&wallet_conf)?; @@ -761,18 +764,18 @@ async fn test_switch_command() -> Result<(), anyhow::Error> { let addr1 = context.active_address()?; // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(addr1), } .execute(&mut context) .await?; // Run a command with address omitted - let os = WalletCommands::Objects { address: None } + let os = SuiClientCommands::Objects { address: None } .execute(&mut context) .await?; - let mut cmd_objs = if let WalletCommandResult::Objects(v) = os { + let mut cmd_objs = if let SuiClientCommandResult::Objects(v) = os { v } else { panic!("Command failed") @@ -790,7 +793,7 @@ async fn test_switch_command() -> Result<(), anyhow::Error> { // Switch the address let addr2 = context.config.accounts.get(1).cloned().unwrap(); - let resp = WalletCommands::Switch { + let resp = SuiClientCommands::Switch { address: Some(addr2), gateway: None, } @@ -802,7 +805,7 @@ async fn test_switch_command() -> Result<(), anyhow::Error> { format!("{resp}"), format!( "{}", - WalletCommandResult::Switch(SwitchResponse { + SuiClientCommandResult::Switch(SwitchResponse { address: Some(addr2), gateway: None }) @@ -814,8 +817,10 @@ async fn test_switch_command() -> Result<(), anyhow::Error> { context.config.active_address = None; // Create a new address - let os = WalletCommands::NewAddress {}.execute(&mut context).await?; - let new_addr = if let WalletCommandResult::NewAddress(a) = os { + let os = SuiClientCommands::NewAddress {} + .execute(&mut context) + .await?; + let new_addr = if let SuiClientCommandResult::NewAddress(a) = os { a } else { panic!("Command failed") @@ -823,7 +828,7 @@ async fn test_switch_command() -> Result<(), anyhow::Error> { // Check that we can switch to this address // Switch the address - let resp = WalletCommands::Switch { + let resp = SuiClientCommands::Switch { address: Some(new_addr), gateway: None, } @@ -834,7 +839,7 @@ async fn test_switch_command() -> Result<(), anyhow::Error> { format!("{resp}"), format!( "{}", - WalletCommandResult::Switch(SwitchResponse { + SuiClientCommandResult::Switch(SwitchResponse { address: Some(new_addr), gateway: None }) @@ -849,7 +854,7 @@ async fn test_active_address_command() -> Result<(), anyhow::Error> { let network = start_test_network(None).await?; // Create Wallet context. - let wallet_conf = network.dir().join(SUI_WALLET_CONFIG); + let wallet_conf = network.dir().join(SUI_CLIENT_CONFIG); let mut context = WalletContext::new(&wallet_conf)?; @@ -857,18 +862,18 @@ async fn test_active_address_command() -> Result<(), anyhow::Error> { let addr1 = context.active_address()?; // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(addr1), } .execute(&mut context) .await?; // Run a command with address omitted - let os = WalletCommands::ActiveAddress {} + let os = SuiClientCommands::ActiveAddress {} .execute(&mut context) .await?; - let a = if let WalletCommandResult::ActiveAddress(Some(v)) = os { + let a = if let SuiClientCommandResult::ActiveAddress(Some(v)) = os { v } else { panic!("Command failed") @@ -876,7 +881,7 @@ async fn test_active_address_command() -> Result<(), anyhow::Error> { assert_eq!(a, addr1); let addr2 = context.config.accounts.get(1).cloned().unwrap(); - let resp = WalletCommands::Switch { + let resp = SuiClientCommands::Switch { address: Some(addr2), gateway: None, } @@ -886,7 +891,7 @@ async fn test_active_address_command() -> Result<(), anyhow::Error> { format!("{resp}"), format!( "{}", - WalletCommandResult::Switch(SwitchResponse { + SuiClientCommandResult::Switch(SwitchResponse { address: Some(addr2), gateway: None }) @@ -926,7 +931,7 @@ async fn test_merge_coin() -> Result<(), anyhow::Error> { + get_gas_value(&get_object(coin_to_merge, &mut context).await.unwrap()); // Test with gas specified - let resp = WalletCommands::MergeCoin { + let resp = SuiClientCommands::MergeCoin { primary_coin, coin_to_merge, gas: Some(gas), @@ -935,7 +940,7 @@ async fn test_merge_coin() -> Result<(), anyhow::Error> { .execute(&mut context) .await?; - let g = if let WalletCommandResult::MergeCoin(r) = resp { + let g = if let SuiClientCommandResult::MergeCoin(r) = resp { r } else { panic!("Command failed") @@ -948,7 +953,7 @@ async fn test_merge_coin() -> Result<(), anyhow::Error> { assert_eq!(get_object(coin_to_merge, &mut context).await, None); // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(&mut context) @@ -965,7 +970,7 @@ async fn test_merge_coin() -> Result<(), anyhow::Error> { + get_gas_value(&get_object(coin_to_merge, &mut context).await.unwrap()); // Test with no gas specified - let resp = WalletCommands::MergeCoin { + let resp = SuiClientCommands::MergeCoin { primary_coin, coin_to_merge, gas: None, @@ -974,7 +979,7 @@ async fn test_merge_coin() -> Result<(), anyhow::Error> { .execute(&mut context) .await?; - let g = if let WalletCommandResult::MergeCoin(r) = resp { + let g = if let SuiClientCommandResult::MergeCoin(r) = resp { r } else { panic!("Command failed") @@ -1005,7 +1010,7 @@ async fn test_split_coin() -> Result<(), anyhow::Error> { let orig_value = get_gas_value(&get_object(coin, &mut context).await.unwrap()); // Test with gas specified - let resp = WalletCommands::SplitCoin { + let resp = SuiClientCommands::SplitCoin { gas: Some(gas), gas_budget: 1000, coin_id: coin, @@ -1014,7 +1019,7 @@ async fn test_split_coin() -> Result<(), anyhow::Error> { .execute(&mut context) .await?; - let g = if let WalletCommandResult::SplitCoin(r) = resp { + let g = if let SuiClientCommandResult::SplitCoin(r) = resp { r } else { panic!("Command failed") @@ -1025,7 +1030,7 @@ async fn test_split_coin() -> Result<(), anyhow::Error> { assert!((get_gas_value(&g.new_coins[0]) == 1000) || (get_gas_value(&g.new_coins[0]) == 10)); assert!((get_gas_value(&g.new_coins[1]) == 1000) || (get_gas_value(&g.new_coins[1]) == 10)); - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(&mut context) @@ -1046,7 +1051,7 @@ async fn test_split_coin() -> Result<(), anyhow::Error> { let orig_value = get_gas_value(&get_object(coin, &mut context).await.unwrap()); // Test with no gas specified - let resp = WalletCommands::SplitCoin { + let resp = SuiClientCommands::SplitCoin { gas: None, gas_budget: 1000, coin_id: coin, @@ -1055,7 +1060,7 @@ async fn test_split_coin() -> Result<(), anyhow::Error> { .execute(&mut context) .await?; - let g = if let WalletCommandResult::SplitCoin(r) = resp { + let g = if let SuiClientCommandResult::SplitCoin(r) = resp { r } else { panic!("Command failed") diff --git a/crates/sui/tests/full_node_tests.rs b/crates/sui/tests/full_node_tests.rs index fed6a165fa8..f8e3ffedc14 100644 --- a/crates/sui/tests/full_node_tests.rs +++ b/crates/sui/tests/full_node_tests.rs @@ -7,11 +7,10 @@ use std::path::PathBuf; use std::{collections::BTreeMap, sync::Arc}; use futures::{future, StreamExt}; -use jsonrpsee::core::client::{Client, Subscription, SubscriptionClientT}; +use jsonrpsee::core::client::{Client, ClientT, Subscription, SubscriptionClientT}; use jsonrpsee::http_client::{HttpClient, HttpClientBuilder}; use jsonrpsee::rpc_params; use jsonrpsee::ws_client::WsClientBuilder; -use jsonrpsee_core::client::ClientT; use move_package::BuildConfig; use serde_json::json; use tokio::sync::Mutex; @@ -19,7 +18,7 @@ use tokio::time::timeout; use tokio::time::{sleep, Duration}; use tracing::info; -use sui::wallet_commands::{WalletCommandResult, WalletCommands, WalletContext}; +use sui::client_commands::{SuiClientCommandResult, SuiClientCommands, WalletContext}; use sui_core::authority::AuthorityState; use sui_json::SuiJsonValue; use sui_json_rpc_api::rpc_types::{ @@ -51,7 +50,7 @@ async fn transfer_coin( "transferring coin {:?} from {:?} -> {:?}", object_to_send, sender, receiver ); - let res = WalletCommands::Transfer { + let res = SuiClientCommands::Transfer { to: receiver, coin_object_id: object_to_send, gas: None, @@ -60,7 +59,7 @@ async fn transfer_coin( .execute(context) .await?; - let digest = if let WalletCommandResult::Transfer(_, cert, _) = res { + let digest = if let SuiClientCommandResult::Transfer(_, cert, _) = res { cert.transaction_digest } else { panic!("transfer command did not return WalletCommandResult::Transfer"); @@ -83,7 +82,7 @@ async fn emit_move_events( let (sender, object_refs) = get_account_and_objects(context).await.unwrap(); let gas_object = object_refs.get(0).unwrap().object_id; - let res = WalletCommands::CreateExampleNFT { + let res = SuiClientCommands::CreateExampleNFT { name: Some("example_nft_name".into()), description: Some("example_nft_desc".into()), url: Some("https://sui.io/_nuxt/img/sui-logo.8d3c44e.svg".into()), @@ -93,9 +92,9 @@ async fn emit_move_events( .execute(context) .await?; - let (object_id, digest) = if let WalletCommandResult::CreateExampleNFT(SuiObjectRead::Exists( - obj, - )) = res + let (object_id, digest) = if let SuiClientCommandResult::CreateExampleNFT( + SuiObjectRead::Exists(obj), + ) = res { (obj.reference.object_id, obj.previous_transaction) } else { @@ -514,7 +513,7 @@ async fn test_full_node_sync_flood() -> Result<(), anyhow::Error> { let (sender, object_to_split) = { let context = &mut context.lock().await; let address = context.config.accounts[i]; - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(context) @@ -534,7 +533,7 @@ async fn test_full_node_sync_flood() -> Result<(), anyhow::Error> { for _ in 0..10 { let res = { let context = &mut context.lock().await; - WalletCommands::SplitCoin { + SuiClientCommands::SplitCoin { amounts: vec![1], coin_id: object_to_split.0, gas: gas_object, @@ -545,7 +544,7 @@ async fn test_full_node_sync_flood() -> Result<(), anyhow::Error> { .unwrap() }; - owned_tx_digest = if let WalletCommandResult::SplitCoin(SplitCoinResponse { + owned_tx_digest = if let SuiClientCommandResult::SplitCoin(SplitCoinResponse { certificate, updated_gas, .. diff --git a/crates/test-utils/src/network.rs b/crates/test-utils/src/network.rs index 5c3f4268684..637fafe142f 100644 --- a/crates/test-utils/src/network.rs +++ b/crates/test-utils/src/network.rs @@ -7,18 +7,18 @@ use std::net::SocketAddr; use std::num::NonZeroUsize; use std::path::Path; use sui::{ - config::{GatewayConfig, GatewayType, WalletConfig}, - keystore::{KeystoreType, SuiKeystore}, - wallet_commands::{WalletCommands, WalletContext}, + client_commands::{SuiClientCommands, WalletContext}, + config::{GatewayConfig, GatewayType, SuiClientConfig}, }; use sui_config::genesis_config::GenesisConfig; -use sui_config::PersistedConfig; -use sui_config::{Config, SUI_GATEWAY_CONFIG, SUI_NETWORK_CONFIG, SUI_WALLET_CONFIG}; +use sui_config::{Config, SUI_CLIENT_CONFIG, SUI_GATEWAY_CONFIG, SUI_NETWORK_CONFIG}; +use sui_config::{PersistedConfig, SUI_KEYSTORE_FILENAME}; use sui_core::gateway_state::GatewayMetrics; use sui_gateway::create_client; use sui_json_rpc::gateway_api::{ GatewayReadApiImpl, GatewayWalletSyncApiImpl, RpcGatewayImpl, TransactionBuilderImpl, }; +use sui_json_rpc_api::keystore::{KeystoreType, SuiKeystore}; use sui_json_rpc_api::QuorumDriverApiServer; use sui_json_rpc_api::RpcReadApiServer; use sui_json_rpc_api::RpcTransactionBuilderServer; @@ -48,8 +48,8 @@ pub async fn start_test_network( let dir = swarm.dir(); let network_path = dir.join(SUI_NETWORK_CONFIG); - let wallet_path = dir.join(SUI_WALLET_CONFIG); - let keystore_path = dir.join("wallet.key"); + let wallet_path = dir.join(SUI_CLIENT_CONFIG); + let keystore_path = dir.join(SUI_KEYSTORE_FILENAME); let db_folder_path = dir.join("client_db"); let gateway_path = dir.join(SUI_GATEWAY_CONFIG); @@ -72,7 +72,7 @@ pub async fn start_test_network( .save(gateway_path)?; // Create wallet config with stated authorities port - WalletConfig { + SuiClientConfig { accounts, keystore: KeystoreType::File(keystore_path), gateway: GatewayType::Embedded(GatewayConfig { @@ -93,12 +93,12 @@ pub async fn setup_network_and_wallet() -> Result<(Swarm, WalletContext, SuiAddr let swarm = start_test_network(None).await?; // Create Wallet context. - let wallet_conf = swarm.dir().join(SUI_WALLET_CONFIG); + let wallet_conf = swarm.dir().join(SUI_CLIENT_CONFIG); let mut context = WalletContext::new(&wallet_conf)?; let address = context.config.accounts.first().cloned().unwrap(); // Sync client to retrieve objects from the network. - WalletCommands::SyncClientState { + SuiClientCommands::SyncClientState { address: Some(address), } .execute(&mut context) @@ -130,13 +130,13 @@ pub async fn start_rpc_test_network( let working_dir = network.dir(); let (server_addr, rpc_server_handle) = start_rpc_gateway(&working_dir.join(SUI_GATEWAY_CONFIG)).await?; - let mut wallet_conf: WalletConfig = - PersistedConfig::read(&working_dir.join(SUI_WALLET_CONFIG))?; + let mut wallet_conf: SuiClientConfig = + PersistedConfig::read(&working_dir.join(SUI_CLIENT_CONFIG))?; let rpc_url = format!("http://{}", server_addr); let accounts = wallet_conf.accounts.clone(); wallet_conf.gateway = GatewayType::RPC(rpc_url.clone()); wallet_conf - .persisted(&working_dir.join(SUI_WALLET_CONFIG)) + .persisted(&working_dir.join(SUI_CLIENT_CONFIG)) .save()?; let http_client = HttpClientBuilder::default().build(rpc_url.clone())?; diff --git a/doc/src/build/cli-client.md b/doc/src/build/cli-client.md new file mode 100644 index 00000000000..cf97a581c8f --- /dev/null +++ b/doc/src/build/cli-client.md @@ -0,0 +1,1126 @@ +--- +title: Sui CLI Quick Start +--- + +Welcome to the Sui tutorial on the Sui CLI developed +to facilitate experimentation with Sui features using a +command line interface. In this document, we describe how to set up +the Sui client and execute commands through its command line +interface, *Sui CLI*. + +## Set up + +Follow the instructions to [install Sui binaries](install.md#binaries). + +## Connect to DevNet +We are hosting a public [DevNet](../explore/devnet.md) for the community to +experiment with our tech and help to shape the future of the Sui network. To +connect the Sui client to the DevNet, run the following command: +```shell +$ sui client +``` +The Sui CLI will print the following line if the client is starting up the +first time. +```shell +Config file ["/Users/dir/.sui/sui_config/client.yaml"] doesn't exist, do you want to connect to a Sui RPC server [y/n]? +``` +Type 'y' and then press 'Enter'. You should see the following output: +```shell +Sui RPC server Url (Default to Sui DevNet if not specified) : +``` +The Sui client will prompt for the RPC server URL; press 'Enter' and it will default to DevNet. +Or enter a custom URL if you want to connect to a server hosted elsewhere. + +If you have used the Sui client before with a local network, follow the next section to +[manually change the RPC server URL](#manually-change-the-rpc-server-url) to DevNet. + +### Manually change the RPC server URL +If you have used the Sui client before, you will have an existing `client.yaml` configuration +file. Change the configured RPC server URL to DevNet by using: +```shell +$ sui client switch --gateway https://gateway.devnet.sui.io:443 +``` + +## Genesis + +The `genesis` command creates four validators and five user accounts +each with five gas objects. These are Sui [objects](objects.md) used +to pay for Sui [transactions](transactions.md#transaction-metadata), +such other object transfers or smart contract (Move) calls. These +numbers represent a sample configuration and have been chosen somewhat +arbitrarily; the process of generating the genesis state can be +customized with additional accounts, objects, code, etc. as described +in [Genesis customization](#customize-genesis). + +1. Optionally, set `RUST_LOG=debug` for verbose logging. +1. Initiate `genesis`: + ```shell + $ sui genesis + ``` + +All of this is contained in configuration and keystore files and an `authorities_db` +database directory. A `client_db` directory is also created upon running the +`sui client new-address` command covered later. + +The network configuration is stored in `network.yaml` and can be used +subsequently to start the network. The `client.yaml` and `sui.keystore` +are also created to be used by the Sui client to manage the newly +created accounts. + +By default, these files are placed in your home directory at +`~/.sui/sui_config` (created automatically if it does not yet exist). But you +can override this location by providing an alternative path to the `--working-dir` +argument. Run the command like so to place the files in the `dir` directory: + +```shell +$ sui genesis --working-dir /path/to/sui/config/dir +``` + +> **Note:** That path and directory must already exist and will not be created with the `--working-dir` argument. + +### Recreating genesis + +To recreate Sui genesis state in the same location, which will remove +existing configuration files, pass the `--force` option to the `sui +genesis` command and either run it in the default directory (`~/.sui/sui_config`) or specify +it once again, using the `--working-dir` argument: + +```shell +$ sui genesis --force --working-dir /path/to/sui/config/dir +``` + +## Client configuration + +The genesis process creates a configuration file `client.yaml`, and a keystore file `sui.keystore` for the +Sui client. The config file contains information of the accounts and +the Sui Network server. The keystore file contains all the public-private key pairs of the created accounts. +Sui client uses the network information in `client.yaml` to communicate +with the Sui network validators and create transactions using the key +pairs residing in the keystore file. + +Here is an example of `client.yaml` showing the accounts and key pairs +in the client configuration (with some values omitted): + +```yaml +--- +accounts: + - b02b5e57fe3572f94ad5ac2a17392bfb3261f7a0 + - b4f5ed3cbe78c7969e6ac073f9a0c525fd07f05a + - 48ff0a932b12976caec91d521265b009ad5b2225 + - 08da15bee6a3f5b01edbbd402654a75421d81397 + - 3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75 +keystore: + File: /Users/user/.sui/sui_config/sui.keystore +gateway: + embedded: + epoch: 0 + validator_set: + - public-key: Ot3ov659M4tl59E9Tq1rUj5SccoXstXrMhQSJX7pFKQ= + stake: 1 + network-address: /dns/localhost/tcp/57468/http + - public-key: UGfB4wzJ2Lntn+WJvv+83RSigpuf7Vv2AmCPQR28TVY= + stake: 1 + network-address: /dns/localhost/tcp/57480/http + - public-key: 5bO8DUgmA9i1SiUka5BT6VjIclMNQBRnbVww2IXxFqw= + stake: 1 + network-address: /dns/localhost/tcp/57492/http + - public-key: 8uV0ml/DPUXG9UbrnlP6v08XaBum9pcIDelRT04NanU= + stake: 1 + network-address: /dns/localhost/tcp/57504/http + send_timeout: + secs: 4 + nanos: 0 + recv_timeout: + secs: 4 + nanos: 0 + buffer_size: 650000 + db_folder_path: /Users/user/.sui/sui_config/client_db +active_address: "0xb02b5e57fe3572f94ad5ac2a17392bfb3261f7a0" +``` + +The `accounts` variable contains the account's address that the client manages. The +`gateway` variable contains the information of the Sui network that the client will +be connecting to. + +The `authorities` variable is part of the embedded gateway configuration. It contains +the Sui network validator's name, host and port information. It is used to establish connections +to the Sui network. + +Note `send_timeout`, `recv_timeout` and `buffer_size` are the network +parameters, and `db_folder_path` is the path to the account's client state +database. This database stores all the transaction data, certificates +and object data belonging to the account. + +### Sui Network Gateway + +The Sui Network Gateway (or simply, Sui Gateway) is an abstraction layer that acts as the entry +point to the Sui network. Different gateway implementations can be used by the application layer +based on their use cases. + +#### Embedded gateway + +As the name suggests, embedded gateway embeds the gateway logic into the application; +all data will be stored locally and the application will make direct +connection to the validators. + +#### RPC gateway +You can also connect the client to the Sui network via an [RPC Gateway](json-rpc.md#start-local-rpc-server); +To use the RPC gateway, update `client.yaml`'s `gateway` section to: +```yaml +... +gateway: + rpc: "http://localhost:5001" +... +``` + +### Key management + +The key pairs are stored in `sui.keystore`. However, this is not secure +and shouldn't be used in a production environment. We have plans to +implement more secure key management and support hardware signing in a future release. + +:warning: **Do not use in production**: Keys are stored in file! + +## Starting the network + +Run the following command to start the local Sui network, assuming you +accepted the default location for configuration: + +```shell +$ sui start +``` + +This command will look for the Sui network configuration file +`network.yaml` in the `~/.sui/sui_config` directory. But you can +override this setting by providing a path to the directory where +this file is stored: + +```shell +$ sui start --config /path/to/sui/network/config/file +``` + +For example: + +```shell +$ sui start --config /Users/name/tmp/network.yaml +``` + +Executing any of these two commands in a terminal window will result +in no output but the terminal will be "blocked" by the running Sui +instance (it will not return the command prompt). The command can +also be run in background. + +NOTE: For logs, set `RUST_LOG=debug` before invoking `sui start`. + +If you see errors when trying to start Sui network, particularly if you made some custom changes + (e.g, +[customized client configuration](#client-configuration)), you should [recreate Sui genesis state](#recreating-genesis). + +## Using the Sui client + +Now start a new terminal since you have the Sui network running in the first terminal. + +The following commands are supported by the Sui client: + + active-address Default address used for commands when none specified + addresses Obtain the Addresses managed by the client + call Call Move function + clear Clear screen + create-example-nft Create an example NFT + echo Write arguments to the console output + env Print environment + exit Exit the interactive shell + gas Obtain all gas objects owned by the address + help Print this message or the help of the given subcommand(s) + history Print history + merge-coin Merge two coin objects into one coin + new-address Generate new address and keypair + object Get obj info + objects Obtain all objects owned by the address + publish Publish Move modules + split-coin Split a coin object into multiple coins + switch Switch active address and network(e.g., devnet, local rpc server) + sync Synchronize client state with authorities + transfer-coin Transfer coin object + transfer-sui Transfer SUI, and pay gas with the same SUI coin object. If amount is + specified, only the amount is transferred; otherwise the entire object + is transferred + +> **Note:** The `clear`, `echo`, `env` and `exit` commands exist only in the interactive shell. + +Use `sui client -h` to see the most up-to-date list of commands. + +Use `help ` to see more information on each command. + +You can start the client in two modes: interactive shell or command line interface. + +### Interactive shell + +To start the interactive shell, execute the following (in a different +terminal window than one used to execute `sui start`). Assuming you +accepted the default location for configuration: + +```shell +$ sui console +``` + +This command will look for the client configuration file +`client.yaml` in the `~/.sui/sui_config` directory. But you can +override this setting by providing a path to the directory where this +file is stored: + +```shell +$ sui console --config /path/to/client/config/file +``` + +The Sui interactive client console supports the following shell functionality: + +* *Command history* - + The `history` command can be used to print the interactive shell's command history; + you can also use Up, Down or Ctrl-P, Ctrl-N to navigate previous or next matches from history. + History search is also supported using Ctrl-R. +* *Tab completion* - + Tab completion is supported for all commands using Tab and Ctrl-I keys. +* *Environment variable substitution* - + The Sui console will substitute inputs prefixed with `$` with environment variables, + you can use the `env` command to print out the entire list of variables and + use `echo` to preview the substitution without invoking any commands. + +### Command line mode + +The client can also be used without the interactive shell, which can be useful if +you want to pipe the output of the client to another application or invoke client +commands using scripts. + +```shell +USAGE: + sui client [SUBCOMMAND] +``` + +For example, we can use the following command to see the list of +accounts available on the platform: + +```shell +$ sui client addresses +``` + +The result of running this command should resemble the following output: + +```shell +Showing 5 results. +0x66af3898e7558b79e115ab61184a958497d1905a +0xae6fb6036570fec1df71599740c132cdf5b45b9d +0x45cda12e3bafe3017b4b3cd62c493e5fbaad7fb0 +0xef999dbdb19ccca504eef5432cec69ea8a1d4a1b +0x4489ab46a230c1876578441d68f25bf968e6f2b0 +``` + +But the actual address values will most likely differ +in your case (as will other values, such as object IDs, in the latter +parts of this tutorial). Consequently, **do not copy and paste +the actual command from this tutorial as they are unlikely to work for +you verbatim**. Each time you create a config for the client, addresses +and object IDs will be assigned randomly. Consequently, you cannot rely +on copy-pasting commands that include these values, as they will be different +between different users/configs. + +### Active address + +Since a Sui CLI client manages multiple disjointed addresses, one might need to specify +which address they want to call a command on. + +For convenience, one can choose to set a default, or active address that will be +used for commands that require an address to operate on. A default address is picked +at the start, but this can be changed later. + +In order to see what the current active address is, use the command `active-address` + +```shell +$ sui client active-address +``` + +Which will reveal an address resembling: + +```shell +0x562f07cf6369e8d22dbf226a5bfedc6300014837 +``` + +Changing the default address is as easy as calling the `switch` command: + +```shell +$ sui client switch --address 0x913cf36f370613ed131868ac6f9da2420166062e +``` + +You will see output like: + +```shell +Active address switched to 0x913cf36f370613ed131868ac6f9da2420166062e +``` + +One can call, for example, the `objects` command with or without an address specified. +When not specified, the active address is used. + +```shell +$ sui client objects + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +``` +```shell +$ sui client objects --address 0x913cf36f370613ed131868ac6f9da2420166062e + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +``` + +All commands where `address` is omitted will now use the newly specified active address: +0x913cf36f370613ed131868ac6f9da2420166062e + +Note that if one calls a command that uses a gas object not owned by the active address, +the address owned by the gas object is temporarily used for the transaction. + +### Paying For transactions with gas objects + +All Sui transactions require a gas object for payment, as well as a budget. However, specifying +the gas object can be cumbersome; so in the CLI, one is allowed to omit the gas object and leave +the client to pick an object that meets the specified budget. This gas selection logic is currently +rudimentary as it does not combine/split gas as needed but currently picks the first object it finds +that meets the budget. Note that one can always specify their own gas if they want to manage the gas +themselves. + +:warning: A gas object cannot be part of the transaction while also being used to +pay for the transaction. For example, one cannot try to transfer gas object X while paying for the +transaction with gas object X. The gas selection logic checks for this and rejects such cases. + +To see how much gas is in an account, use the `gas` command. Note that this command uses the +`active-address`, unless otherwise specified. + +```shell +$ sui client gas +``` + +You will see output like: + +```shell + Object ID | Version | Gas Value +------------------------------------------------------------------------ + 0x0b8a4620426e526fa42995cf26eb610bfe6bf063 | 0 | 100000 + 0x3c0763ccdea4ff5a4557505a62ab5e1daf91f4a2 | 0 | 100000 + 0x45a589a9e760d7f75d399327ac0fcba21495c22e | 0 | 100000 + 0x4c377a3a9d4b1b9c92189dd12bb1dcd0302a954b | 0 | 100000 + 0xf2961464ac6860a05d21b48c020b7e121399965c | 0 | 100000 +``` + +If one does not want to use the active address, the addresses can be specified: + +```shell +$ sui client gas --address 0x562f07cf6369e8d22dbf226a5bfedc6300014837 + Object ID | Version | Gas Value +------------------------------------------------------------------------ + 0xa8ddc2661a19010e5f85cbf6d905ddfbe4dd0320 | 0 | 100000 + 0xb2683d0b592e5b002d110989a52943bc9da19158 | 0 | 100000 + 0xb41bf45b01c9befce3a0a371e2b98e062691438d | 0 | 100000 + 0xba9e10f319182f3bd584edb92c7899cc6d018723 | 0 | 100000 + 0xf8bfe77a5b21e7abfa3bc285991f9da4e5cc2d7b | 0 | 100000 + +``` + +## Adding accounts to the client + +Sui's genesis process will create five accounts by default; if that's +not enough, there are two ways to add accounts to the Sui CLI client if needed. + +### Generating a new account + +To create a new account, execute the `new-address` command: + +```shell +$ sui client new-address +``` + +The output shows a confirmation after the account has been created: + +``` +Created new keypair for address : 0xc72cf3adcc4d11c03079cef2c8992aea5268677a +``` + +### Add existing accounts to `client.yaml` manually + +If you have an existing key pair from an old client config, you can copy the account +address manually to the new `client.yaml`'s accounts section, and add the key pair to the keystore file; +you won't be able to mutate objects if the account key is missing from the keystore. + +Restart the Sui console after the modification; the new accounts will appear in the client if you query the addresses. + +## View objects owned by the address + +You can use the `objects` command to view the objects owned by the address. + +`objects` command usage: + +```shell +sui-client-objects +Obtain all objects owned by the address + +USAGE: + sui client objects [OPTIONS] + +OPTIONS: + --address
Address owning the objects + -h, --help Print help information + --json Return command outputs in json format +``` + +To view the objects owned by the addresses created in genesis, run the following command (substituting the address with one of the genesis addresses in your client): + +```shell +$ sui client objects --address 0x66af3898e7558b79e115ab61184a958497d1905a +``` + +The result should resemble the following. + +```shell + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 0 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xc8add7b4073900ffb0a8b4fe7d70a7db454c2e19 | 0 | uCZNPmDWOksKhCKwEaMtST5T4HbTjcgXGHRXP4qTLC8= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xd1949864f94d87cf25e1fd7b1c8ab4bf685f7801 | 0 | OsTryyECAPW9mnSbWlYWELX+QlRg5er7s/DlkgqhDww= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xddb6119c320f52f3fef9fbc272af305d985b6883 | 0 | gBCDdel7iJZnXpuf4g9dqIPT4XjaAY/4knNcDxbTons= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xe1fe79ac8d900342e617e0986f54ff64e4e323de | 0 | qjsWIzAaomo0eqFwQt99EkARsiC/aw2hPDH8quM6pYg= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +Showing 5 results. +``` + +If you want to view more information about the objects, you can use the `object` command. + +Usage of `object` command : + +```shell +sui-client-object +Get object info + +USAGE: + sui client object [OPTIONS] --id + +OPTIONS: + -h, --help Print help information + --id Object ID of the object to fetch + --json Return command outputs in json format +``` + +To view the object, use the following command: + +```bash +$ sui client object --id 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 +``` + +This should give you output similar to the following: + +```shell +----- Move Object (0x66eaa38c8ea99673a92a076a00101ab9b3a06b55[0]) ----- +Owner: Account Address ( 0xb02b5e57fe3572f94ad5ac2a17392bfb3261f7a0 ) +Version: 0 +Storage Rebate: 0 +Previous Transaction: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +----- Data ----- +type: 0x2::coin::Coin<0x2::sui::SUI> +balance: 100000 +id: 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55[0] +``` + +The result shows some basic information about the object, the owner, +version, ID, if the object is immutable and the type of the object. + +> **Important:** To gain a deeper view into the object, include the +> `--json` flag in the `sui client` command to see the raw JSON representation +> of the object. + +Here is example `json` output: + +```json +{ + "data": { + "dataType": "moveObject", + "type": "0x2::coin::Coin<0x2::sui::SUI>", + "has_public_transfer": true, + "fields": { + "balance": 100000, + "id": { + "id": "0x66eaa38c8ea99673a92a076a00101ab9b3a06b55", + "version": 0 + } + } + }, + "owner": { + "AddressOwner": "0xb02b5e57fe3572f94ad5ac2a17392bfb3261f7a0" + }, + "previousTransaction": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + "storageRebate": 0, + "reference": { + "objectId": "0x66eaa38c8ea99673a92a076a00101ab9b3a06b55", + "version": 0, + "digest": "j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo=" + } +} +``` + +## Transferring coins + +Coins *are* objects yet have a specific use case that allow for native commands like transfer-coin/merge-coin/split-coin to be used. This is different from non-coin objects that can only be mutated via [Move calls](#calling-move-code). + +If you inspect a newly created account, you would expect the account does not own any object. Let us inspect the fresh account we create in the [Generating a new account](#generating-a-new-account) section (`C72CF3ADCC4D11C03079CEF2C8992AEA5268677A`): + +```shell +$ sui client objects --address 0xc72cf3adcc4d11c03079cef2c8992aea5268677a + Object ID | Version | Digest +------------------------------------------------------------------------------------------------------------------------------ +Showing 0 results. +``` + +To add objects to the account, you can [invoke a Move function](#calling-move-code), +or you can transfer one of the existing coins from the genesis account to the new account using a dedicated Sui client command. +We will explore how to transfer coins using the Sui CLI client in this section. + +`transfer-coin` command usage: + +```shell +sui-client-transfer-coin +Transfer coin object + +USAGE: + sui client transfer-coin [OPTIONS] --to --coin-object-id --gas-budget + +OPTIONS: + --coin-object-id + Coin to transfer, in 20 bytes Hex string + + --gas + ID of the gas object for gas payment, in 20 bytes Hex string If not provided, a gas + object with at least gas_budget value will be selected + + --gas-budget + Gas budget for this transfer + + -h, --help + Print help information + + --json + Return command outputs in json format + + --to + Recipient address +``` + +To transfer a coin object to a recipient, you will need the recipient's address, +the object ID of the coin that you want to transfer, +and optionally the coin object ID for the transaction fee payment. If a gas +coin is not specified, one that meets the budget is picked. Gas budget sets a +cap for how much gas you want to spend. We are still finalizing our gas metering +mechanisms. For now, just set something large enough. + +Here is an example transfer of an object to account `0xf456ebef195e4a231488df56b762ac90695be2dd`: + +```shell +$ sui client transfer-coin --to 0xf456ebef195e4a231488df56b762ac90695be2dd --coin-object-id 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 --gas-budget 100 +``` + +With output like: + +``` +Transfer confirmed after 16896 us +----- Certificate ---- +Transaction Hash: mjj1+0Wn+lER1oSD7fwXmoaxzoZW1pmMOqHQJgniy8U= +Transaction Signature: YLbToj+MjgQnaix24ObbE+BdXna6bB9gSSm+YMa/VHsX5g68T9+5vRnGbvDECGoioluUQP0k/zSPvQU5Y/uXCA==@BE/TaOYjyEtJUqF0Db4FEcVT4umrPmp760gFLQIGA1E= +Signed Authorities : [k#f2e5749a5fc33d45c6f546eb9e53fabf4f17681ba6f697080de9514f4e0d6a75, k#3adde8bfae7d338b65e7d13d4ead6b523e5271ca17b2d5eb321412257ee914a4, k#5067c1e30cc9d8b9ed9fe589beffbcdd14a2829b9fed5bf602608f411dbc4d56] +Transaction Kind : Public Transfer Object +Recipient : 0xf456ebef195e4a231488df56b762ac90695be2dd +Object ID : 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 +Version : SequenceNumber(1) +Object Digest : NFDitxwq+bXetYmBxsw9RYEFqq+NWIbRxVoyv3JJXSE= +----- Transaction Effects ---- +Status : Success +Mutated Objects: + - ID: 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 , Owner: Account Address ( 0xf456ebef195e4a231488df56b762ac90695be2dd ) + - ID: 0xc8add7b4073900ffb0a8b4fe7d70a7db454c2e19 , Owner: Account Address ( 0xb02b5e57fe3572f94ad5ac2a17392bfb3261f7a0 ) +``` + +The account will now have one object: + +```shell +$ sui client objects --address 0xc72cf3adcc4d11c03079cef2c8992aea5268677a + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x66eaa38c8ea99673a92a076a00101ab9b3a06b55 | 1 | j8qLxVk/Bm9iMdhPf9b7HcIMQIAM+qCd8LfPAwKYrFo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +``` + +## Creating example NFTs + +You may create an [NFT-like object](https://github.com/MystenLabs/sui/blob/main/crates/sui-framework/sources/devnet_nft.move#L16) on Sui using the following command: + +```shell +$ sui client create-example-nft +``` + +You will see output resembling: + +```shell +Successfully created an ExampleNFT: + +----- Move Object (0x524f9fae3ca4554e01354415daf58a05e5bf26ac[1]) ----- +Owner: Account Address ( 0xb02b5e57fe3572f94ad5ac2a17392bfb3261f7a0 ) +Version: 1 +Storage Rebate: 25 +Previous Transaction: 98HbDxEwEUknQiJzyWM8AiYIM479BEKuGwxrZOGtAwk= +----- Data ----- +type: 0x2::devnet_nft::DevNetNFT +description: An NFT created by the Sui Command Line Tool +id: 0x524f9fae3ca4554e01354415daf58a05e5bf26ac[1] +name: Example NFT +url: ipfs://bafkreibngqhl3gaa7daob4i2vccziay2jjlp435cf66vhono7nrvww53ty +``` + +The command will invoke the `mint` function in the `devnet_nft` module, which mints a Sui object with three attributes: name, description, and image URL with [default values](https://github.com/MystenLabs/sui/blob/27dff728a4c9cb65cd5d92a574105df20cb51887/sui/src/wallet_commands.rs#L39) and transfers the object to your address. You can also provide custom values using the following instructions: + + +`create-example-nft` command usage: + +```shell +sui-client-create-example-nft +Create an example NFT + +USAGE: + sui client create-example-nft [OPTIONS] + +OPTIONS: + --description Description of the NFT + --gas ID of the gas object for gas payment, in 20 bytes Hex string + If not provided, a gas object with at least gas_budget value + will be selected + --gas-budget Gas budget for this transfer + -h, --help Print help information + --json Return command outputs in json format + --name Name of the NFT + --url Display url(e.g., an image url) of the NFT + +``` + + +## Merging and splitting coin objects + +Overtime, the account might receive coins from other accounts and will become unmanageable when +the number of coins grows; contrarily, the account might need to split the coins for payment or +for transfer to another account. + +We can use the `merge-coin` command and `split-coin` command to consolidate or split coins, respectively. + +### Merge coins + +Usage of `merge-coin`: + +```shell +sui-client-merge-coin +Merge two coin objects into one coin + +USAGE: + sui client merge-coin [OPTIONS] --primary-coin --coin-to-merge --gas-budget + +OPTIONS: + --coin-to-merge + Coin to be merged, in 20 bytes Hex string + + --gas + ID of the gas object for gas payment, in 20 bytes Hex string If not provided, a gas + object with at least gas_budget value will be selected + + --gas-budget + Gas budget for this call + + -h, --help + Print help information + + --json + Return command outputs in json format + + --primary-coin + Coin to merge into, in 20 bytes Hex string +``` + +Here is an example of how to merge coins. To merge coins, you will need at lease three coin objects - +two coin objects for merging, and one for the gas payment. +You also need to specify the maximum gas budget that should be expanded for the coin merge operations. +Let us examine objects owned by address `0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75` +and use the first coin (gas) object as the one to be the result of the merge, the second one to be merged, and the third one to be used as payment: + +```shell +$ sui client objects --address 0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75 +``` + +And its output: + +``` + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x1e90389f5d70d7fa6ce973155460e1c04deae194 | 0 | BC5O8Bf6Uw8S1LV1y4RCI6+kz1KhZG/aOpeqq9kTAvs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x351f08f03709cebea85dcd20e24b00fbc1851c92 | 0 | 9aYvavAzY6chYbOUtMtJj0g/5GNc+KBsqptCX5pmQ2Y= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x3c720502f9eabb17a52a999859fbbaeb408b1d14 | 0 | WUPT6P40veMZ/C7GiQpv92I4EH+hvh5BbkBt+7p9yH0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x7438af4677b9cea2094848f611143346183c11d1 | 0 | 55B56RG/kCeHrN6GXdIq0IvnyYD/hng9J7I7FNRykQ4= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x9d5f2b2564ad2255c24a03556785bddc85381508 | 0 | rmyYjq/UEED0xR0hE3Da8OYgBAu3MYxKQ3v76pGTDek= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +Showing 5 results. +``` + +Then we merge: +```shell +$ sui client merge-coin --primary-coin 0x1e90389f5d70d7fa6ce973155460e1c04deae194 --coin-to-merge 0x351f08f03709cebea85dcd20e24b00fbc1851c92 --gas-budget 1000 +``` + +With results resembling: + +``` +----- Certificate ---- +Transaction Hash: kxxpeggKaMpiWTpSrCNYcu3EDBfNWBJiIPnqae99Znw= +Transaction Signature: /4jxUHC8iZRaHlgbgfOr962BqIRb7AavVJE8GUlY6EMehedF8iVxPf8URe5wFyrxD8IvEclN3Z1qJ4UweYCQAA==@cQeSjZ1xq4QC+7G5/MlAhnZuie6ZrukU/ps2LHmX3D8= +Signed Authorities : [k#3adde8bfae7d338b65e7d13d4ead6b523e5271ca17b2d5eb321412257ee914a4, k#e5b3bc0d482603d8b54a25246b9053e958c872530d4014676d5c30d885f116ac, k#5067c1e30cc9d8b9ed9fe589beffbcdd14a2829b9fed5bf602608f411dbc4d56] +Transaction Kind : Call +Package ID : 0x2 +Module : coin +Function : join +Arguments : ["0x1e90389f5d70d7fa6ce973155460e1c04deae194", "0x351f08f03709cebea85dcd20e24b00fbc1851c92"] +Type Arguments : ["0x2::sui::SUI"] +----- Merge Coin Results ---- +Updated Coin : Coin { id: 0x1e90389f5d70d7fa6ce973155460e1c04deae194, value: 200000 } +Updated Gas : Coin { id: 0x3c720502f9eabb17a52a999859fbbaeb408b1d14, value: 99444 } +``` + +### Split coins + +Usage of `split-coin`: + +```shell +sui-client-split-coin +Split a coin object into multiple coins + +USAGE: + sui client split-coin [OPTIONS] --coin-id --amounts ... --gas-budget + +OPTIONS: + --amounts ... Amount to split out from the coin + --coin-id Coin to Split, in 20 bytes Hex string + --gas ID of the gas object for gas payment, in 20 bytes Hex string If + not provided, a gas object with at least gas_budget value will + be selected + --gas-budget Gas budget for this call + -h, --help Print help information + --json Return command outputs in json format +``` + +For splitting coins, you will need at lease two coins to execute the `split-coin` command, +one coin to split, one for the gas payment. + +Let us examine objects owned by address `0x08da15bee6a3f5b01edbbd402654a75421d81397`: + +```shell +$ sui client objects --address 0x08da15bee6a3f5b01edbbd402654a75421d81397 +``` + +With output resembling: + +```shell + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x4a2853304fd2c243dae7d1ba58260bb7c40724e1 | 0 | uNcjv6KP8AXgQHTFmiEPV3tpWZcYHb1HmBR0B2pMsAo= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x692c179dc434ceb0eaa51cdd198bb905b5ab27c4 | 0 | /ug6IGGld90PqnmL9qijciCqn25V11nn5/PAsKjxMY0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x7f7b7c1589aceb073a7c8740b1d47d05e4d89e3c | 0 | N5+qKRenKWqb7Y6WKZuFD+fRDB6pj/OtIyri+FSQ3Q0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xe42558e82e315c9c81ee5b9f1ac3db819ece5c1d | 0 | toHeih0DeFrqxQhGzVUi9EkVwAZSbLx6hv2gpMgNBbs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xfa322fee6a7f4c266ad4840e85bf3d87689b6de0 | 0 | DxjnkJTSl0o6HlzeOX5K/If61bbFwvRDydjzd2bq8ho= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +Showing 5 results. +``` + +Here is an example of splitting coins. We are splitting out three new coins from the original coin (first one on the list above), +with values of 1000, 5000 and 3000, respectively; note the `--amounts` argument accepts list of values. +We use the second coin on the list to pay for this transaction. + +```shell +$ sui client split-coin --coin-id 0x4a2853304fd2c243dae7d1ba58260bb7c40724e1 --amounts 1000 5000 3000 --gas-budget 1000 +``` + +You will see output resembling: + +``` +----- Certificate ---- +Transaction Hash: qpxpv+EySl6tkz7OZ+/h/cpOlC/q1kBepr/qrDHsg7k= +Transaction Signature: BsuWPuG9iBnvc/cQBbpBvDsBnzLXrhxPpoblpZ7ZcTQ78X9AtPO7knOaPjEbLxEJMGpOCPTIWa0eMPpoqT/SDQ==@ZXB4tfniuC6Oir8aVtIR5C00Md/tG3WSZRNN7nDDZLs= +Signed Authorities : [k#3adde8bfae7d338b65e7d13d4ead6b523e5271ca17b2d5eb321412257ee914a4, k#5067c1e30cc9d8b9ed9fe589beffbcdd14a2829b9fed5bf602608f411dbc4d56, k#f2e5749a5fc33d45c6f546eb9e53fabf4f17681ba6f697080de9514f4e0d6a75] +Transaction Kind : Call +Package ID : 0x2 +Module : coin +Function : split_vec +Arguments : ["0x4a2853304fd2c243dae7d1ba58260bb7c40724e1", [1000,5000,3000]] +Type Arguments : ["0x2::sui::SUI"] +----- Split Coin Results ---- +Updated Coin : Coin { id: 0x4a2853304fd2c243dae7d1ba58260bb7c40724e1, value: 91000 } +New Coins : Coin { id: 0x1da8193ac29f94f8207b0222bd5941b7814c1668, value: 3000 }, + Coin { id: 0x3653bae7851c36e0e5e827b7c1a2978ef78efd7e, value: 5000 }, + Coin { id: 0xd5b694f67410d5b6cd293128cd48953aaa0a3dce, value: 1000 } +Updated Gas : Coin { id: 0x692c179dc434ceb0eaa51cdd198bb905b5ab27c4, value: 99385 } +``` + +``` +$ sui client objects --address 0x08da15bee6a3f5b01edbbd402654a75421d81397 + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x1da8193ac29f94f8207b0222bd5941b7814c1668 | 1 | nAMEV3NZ0zscjO10QQUt1drLvhNXTk4MVLAg1FXTQxw= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x3653bae7851c36e0e5e827b7c1a2978ef78efd7e | 1 | blMuVATrI89PRvqA4Kuv6rNkbuAb+bYhmkMocY7pavw= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x4a2853304fd2c243dae7d1ba58260bb7c40724e1 | 1 | uhfauig0guMidpxFyCO6FzhzDfucss+eA6xWzAVF3sU= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x692c179dc434ceb0eaa51cdd198bb905b5ab27c4 | 1 | sWTy2PUbt3UFEKx1Km32dEG7cQscSK+eVc3ChaZCkkA= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x7f7b7c1589aceb073a7c8740b1d47d05e4d89e3c | 0 | N5+qKRenKWqb7Y6WKZuFD+fRDB6pj/OtIyri+FSQ3Q0= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xd5b694f67410d5b6cd293128cd48953aaa0a3dce | 1 | 4V0BC6eopxkN6wIOdm2FVgwN3psNbPvLKQ9/zrYtsDM= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xe42558e82e315c9c81ee5b9f1ac3db819ece5c1d | 0 | toHeih0DeFrqxQhGzVUi9EkVwAZSbLx6hv2gpMgNBbs= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xfa322fee6a7f4c266ad4840e85bf3d87689b6de0 | 0 | DxjnkJTSl0o6HlzeOX5K/If61bbFwvRDydjzd2bq8ho= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +Showing 8 results. +``` + +From the result, we can see three new coins were created in the transaction. + +## Calling Move code + +The genesis state of the Sui platform includes Move code that is +immediately ready to be called from Sui CLI. Please see our +[Move developer documentation](move.md#first-look-at-move-source-code) +for the first look at Move source code and a description of the +following function we will be calling in this tutorial: + +```rust +public entry fun transfer(c: coin::Coin, recipient: address) { + coin::transfer(c, Address::new(recipient)) +} +``` + +Please note that there is no real need to use a Move call to transfer +coins as this can be accomplished with a built-in Sui client +[command](#transferring-coins) - we chose this example due to its +simplicity. + +Let us examine objects owned by address `0x48ff0a932b12976caec91d521265b009ad5b2225`: + +```shell +$ sui client objects --address 0x48ff0a932b12976caec91d521265b009ad5b2225 + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x471c8e241d0473c34753461529b70f9c4ed3151b | 0 | MCQIALghS9kQUWMclChmsd6jCuLiUxNjEn9VRV+AhSA= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 0 | VIbuA4fcsitOUmJLQ+FugZWIn7bg6LnVO8eTIAUDzkg= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +Showing 5 results. +``` + +Now that we know which objects are owned by that address, +we can transfer one of them to another address, say the fresh one +we created in the [Generating a new account](#generating-a-new-account) section +(`0xc72cf3adcc4d11c03079cef2c8992aea5268677a`). We can try any object, +but for the sake of this exercise, let's choose the last one on the +list. + +We will perform the transfer by calling the `transfer` function from +the sui module using the following Sui client command: + +```shell +$ sui client call --function transfer --module sui --package 0x2 --args 0x471c8e241d0473c34753461529b70f9c4ed3151b 0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75 --gas-budget 1000 +``` + +This is a pretty complicated command so let's explain all of its +parameters one-by-one: + +* `--function` - name of the function to be called +* `--module` - name of the module containing the function +* `--package` - ID of the package object where the module containing + the function is located. (Remember + that the ID of the genesis Sui package containing the GAS module is + defined in its manifest file, and is equal to `0x2`.) +* `--args` - a list of function arguments formatted as + [SuiJSON](sui-json.md) values (hence the preceding `0x` in address + and object ID): + * ID of the gas object representing the `c` parameter of the `transfer` + function + * address of the new gas object owner +* `--gas` - an optional object containing gas used to pay for this + function call +* `--gas-budget` - a decimal value expressing how much gas we are + willing to pay for the `transfer` call to be completed to avoid + accidental drain of all gas in the gas pay) + +Note the third argument to the `transfer` function representing +`TxContext` does not have to be specified explicitly - it +is a required argument for all functions callable from Sui and is +auto-injected by the platform at the point of a function call. + +The output of the call command is a bit verbose, but the important +information that should be printed at the end indicates objects +changes as a result of the function call: + +```shell +----- Certificate ---- +Transaction Hash: KT7sEHzxavRFkLijfKGDqj6kM5bVl1QA1IawJPV2+Go= +Transaction Signature: GIUaa8yAPgy/eSVypVz+fmbjC2mL5kHuYNodUyNcIUMvlUN5XxyPYdL8C25vvH6rYt/ZUDY2ntZU1NHUp4yPCg==@iocJzkLCMJMh1VGZ6sUsw0okqoDP71ed9a4Vf2vWlx4= +Signed Authorities : [k#5067c1e30cc9d8b9ed9fe589beffbcdd14a2829b9fed5bf602608f411dbc4d56, k#e5b3bc0d482603d8b54a25246b9053e958c872530d4014676d5c30d885f116ac, k#3adde8bfae7d338b65e7d13d4ead6b523e5271ca17b2d5eb321412257ee914a4] +Transaction Kind : Call +Package ID : 0x2 +Module : sui +Function : transfer +Arguments : ["0x471c8e241d0473c34753461529b70f9c4ed3151b", "0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75"] +Type Arguments : [] +----- Transaction Effects ---- +Status : Success +Mutated Objects: + - ID: 0x471c8e241d0473c34753461529b70f9c4ed3151b , Owner: Account Address ( 0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75 ) + - ID: 0x53b50e3020a01e1fd6acf832a871feee240183f0 , Owner: Account Address ( 0x48ff0a932b12976caec91d521265b009ad5b2225 ) +``` + +This output indicates the gas object +was updated to collect gas payment for the function call, and the +transferred object was updated as its owner had been +modified. We can confirm the latter (and thus a successful execution +of the `transfer` function) by querying objects that are now owned by +the sender: + +```shell +$ sui client objects --address 0x48ff0a932b12976caec91d521265b009ad5b2225 + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 1 | st6KVE+nTPsQgtEtxSbgJZCzSSuSB2ZsJAMbXFNLw/k= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +Showing 4 results. +``` + +We can now see this address no longer owns the transferred object. +And if we inspect this object, we can see it has the new +owner, different from the original one: + +```shell +$ sui client object --id 0x471c8e241d0473c34753461529b70f9c4ed3151b +``` + +Resulting in: + +``` +----- Move Object (0x471c8e241d0473c34753461529b70f9c4ed3151b[1]) ----- +Owner: Account Address ( 0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75 ) +Version: 1 +Storage Rebate: 15 +Previous Transaction: KT7sEHzxavRFkLijfKGDqj6kM5bVl1QA1IawJPV2+Go= +----- Data ----- +type: 0x2::coin::Coin<0x2::sui::SUI> +balance: 100000 +id: 0x471c8e241d0473c34753461529b70f9c4ed3151b[1] +``` + +## Publish packages + +In order for user-written code to be available in Sui, it must be +*published* to Sui's [distributed ledger](../learn/how-sui-works.md#architecture). +Please see the [Move developer documentation](move.md) for a +description on how to [write a simple Move code package](move.md#writing-a-package), +which we can publish using Sui client's `publish` command. + +The publish command +requires us to specify a directory where the user-defined package lives. +It's the path to the `my_move_package` as per the +[package creation description](move.md#writing-a-package), a gas +object that will be used to pay for publishing the package (we use the +same gas object we used to pay for the function call in the +[Calling Move code](#calling-move-code)) section, and gas budget to put +an upper limit we use 1000 as our gas budget. + +Let us use the same address for publishing that we used for calling Move code in the previous [section](#calling-move-code) (`0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75`) which now has 4 objects left: + +```shell +$ sui client objects --address 0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75 +``` + +Outputting: + +``` + Object ID | Version | Digest | Owner Type | Object Type +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 0x53b50e3020a01e1fd6acf832a871feee240183f0 | 1 | st6KVE+nTPsQgtEtxSbgJZCzSSuSB2ZsJAMbXFNLw/k= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x5c846224b8704683a1c576aec7c8d9c3413d87c1 | 0 | KO0Fr9uCPnT3KxOEishyzas33le4J9fAGg7iEOOzo7A= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0x6fe4cf8d2c21f23f2aacf60f30c98ff9e2c78226 | 0 | p2evKbTirwEoF1PxGIu5USAsSdkxzh1sUD/OxBfpdNE= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> + 0xa28dd252ab5b984a8c1da699bbe10e7f09947a12 | 0 | 6VT+8479aijA8tYmab7YatVgjXm1TWy5jItooC416YQ= | AddressOwner | 0x2::coin::Coin<0x2::sui::SUI> +Showing 4 results. +``` + +The whole command to publish a package for address +`0x3cbf06e9997b3864e3baad6bc0f0ef8ec423cd75` resembles the following (assuming +that the location of the package's sources is in the `PATH_TO_PACKAGE` +environment variable): + +```shell +$ sui client publish --path $PATH_TO_PACKAGE/my_move_package --gas-budget 30000 +``` + +The result of running this command should look as follows: + +```shell +----- Certificate ---- +Transaction Hash: evmJUz0+a2oFMbsTza2U+vC9q2KHeDVVV9XUma8OXv8= +Transaction Signature: 7Lqy/KQW86Tq81cUxLMW07AQw1S+D4QLFC9/jMNKrau81eABHpxG2lgaVaAh0c+d5ldYhp75SmpY0pxq0FSLBA==@BE/TaOYjyEtJUqF0Db4FEcVT4umrPmp760gFLQIGA1E= +Signed Authorities : [k#5067c1e30cc9d8b9ed9fe589beffbcdd14a2829b9fed5bf602608f411dbc4d56, k#f2e5749a5fc33d45c6f546eb9e53fabf4f17681ba6f697080de9514f4e0d6a75, k#e5b3bc0d482603d8b54a25246b9053e958c872530d4014676d5c30d885f116ac] +Transaction Kind : Publish +----- Publish Results ---- +The newly published package object ID: 0xdbcee02bd4eb326122ced0a8540f15a057d82850 + +List of objects created by running module initializers: +----- Move Object (0x4ac2df49c3698baaef11ae23b3d8417d7e5ed65f[1]) ----- +Owner: Account Address ( 0xb02b5e57fe3572f94ad5ac2a17392bfb3261f7a0 ) +Version: 1 +Storage Rebate: 12 +Previous Transaction: evmJUz0+a2oFMbsTza2U+vC9q2KHeDVVV9XUma8OXv8= +----- Data ----- +type: 0xdbcee02bd4eb326122ced0a8540f15a057d82850::m1::Forge +id: 0x4ac2df49c3698baaef11ae23b3d8417d7e5ed65f[1] +swords_created: 0 + +Updated Gas : Coin { id: 0xc8add7b4073900ffb0a8b4fe7d70a7db454c2e19, value: 96929 } +``` + +Please note that running this command resulted in creating an object representing the published package. +From now on, we can use the package object ID (`0xdbcee02bd4eb326122ced0a8540f15a057d82850`) in the Sui client's call +command just like we used `0x2` for built-in packages in the +[Calling Move code](#calling-move-code) section. + +Another object created as a result of package publishing is a +user-defined object (of type `Forge`) crated inside initializer +function of the (only) module included in the published package - see +the part of Move developer documentation concerning [module +initializers](move.md#module-initializers) for more details on module +initializers. + +Finally, we see that the gas object that was used to pay for +publishing was updated as well. + +## Customize genesis + +The genesis process can be customized by providing a genesis configuration +file using the `--config` flag. + +```shell +$ sui genesis --config +``` + +Example `genesis.yaml`: + +```yaml +--- +validator_genesis_info: ~ +committee_size: 4 +accounts: + - gas_objects: + - object_id: "0xdbac75c4e5a5064875cb8566a533547957092f93" + gas_value: 100000 + gas_object_ranges: [] +move_packages: [""] +sui_framework_lib_path: ~ +move_framework_lib_path: ~ + +``` diff --git a/doc/src/build/index.md b/doc/src/build/index.md index ac425f5f51b..647f9b01bff 100644 --- a/doc/src/build/index.md +++ b/doc/src/build/index.md @@ -14,9 +14,9 @@ Here is our recommended workflow to interact with Sui: 1. [Test](../build/move.md#testing-a-package) a package. 1. [Debug](../build/move.md#debugging-a-package) a package. 1. [Publish](../build/move.md#publishing-a-package) a package. -1. [Create](../build/wallet.md#genesis) and [Start](../build/wallet.md#starting-the-network) a *local Sui network*. +1. [Create](../build/cli-client.md#genesis) and [Start](../build/cli-client.md#starting-the-network) a *local Sui network*. 1. [Start](../build/json-rpc.md#start-local-rpc-server) a *local JSON-RPC Gateway server*. -1. [Connect](../build/wallet.md#rpc-gateway) to the Sui network Gateway service with the *Sui Wallet*. +1. [Connect](../build/cli-client.md#rpc-gateway) to the Sui network Gateway service with the *Sui CLI client*. 1. Build dApps: 1. [Use](../build/json-rpc.md) *Sui RPC Server and JSON-RPC API* to interact with a local Sui network. 1. [Employ](../build/sui-json.md) *SuiJSON format* to align JSON inputs more closely with Move call arguments. diff --git a/doc/src/build/install.md b/doc/src/build/install.md index 14986031cd1..9ba301ec0e8 100644 --- a/doc/src/build/install.md +++ b/doc/src/build/install.md @@ -60,20 +60,14 @@ In addition, to conduct advanced work such as altering Sui itself, also obtain: To develop in Sui, you will need the Sui binaries. After installing `cargo`, run: ```shell -$ cargo install --locked --git https://github.com/MystenLabs/sui.git --branch "devnet" sui +$ cargo install --locked --git https://github.com/MystenLabs/sui.git --branch "devnet" sui sui-json-rpc ``` This will put the following binaries in your `PATH` (ex. under `~/.cargo/bin`) that provide these command line interfaces (CLIs): -* bench - local test and benchmark of the Sui authorities. -* bench_configure - creates the config files for distributed benchmarking. -* key_tool - utility for generating keys and addresses encoded as Base64 bytes. -* remote_load_generator - enables distributed benchmark of the Sui authorities on remote machines. -* [`rpc-server`](json-rpc.md) - run a local Sui network and gateway service accessible via an RPC interface. -* sui - enables `genesis` of validators and accounts, as well as starting the Sui network. -* [`sui-move`](move.md) - build and test Move packages. -* [`wallet`](wallet.md) - run a local Sui network and gateway service accessible via the wallet CLI. The wallet CLI manage keypairs to sign/send transactions +* sui - The Sui CLI tool contains subcommands for enabling `genesis` of validators and accounts, starting the Sui network, and [building and testing Move packages](move.md), as well as a [client](cli-client.md) for interacting with the Sui network. +* [`rpc-server`](json-rpc.md) - run a local Sui gateway service accessible via an RPC interface. -Confirm the install with: +Confirm the installation with: ``` $ echo $PATH @@ -101,7 +95,7 @@ $ git clone https://github.com/MystenLabs/sui.git --branch devnet ``` You can start exploring Sui's source code by looking into the following primary directories: -* [sui](https://github.com/MystenLabs/sui/tree/main/crates/sui) - the Sui binaries (`wallet`, `sui-move`, and more) +* [sui](https://github.com/MystenLabs/sui/tree/main/crates/sui) - the Sui CLI binary * [sui_programmability](https://github.com/MystenLabs/sui/tree/main/sui_programmability) - Sui's Move language integration also including games and other Move code examples for testing and reuse * [sui_core](https://github.com/MystenLabs/sui/tree/main/crates/sui-core) - authority server and Sui Gateway * [sui-types](https://github.com/MystenLabs/sui/tree/main/crates/sui-types) - coins, gas, and other object types @@ -121,6 +115,6 @@ To contribute updates to Sui code, [send pull requests](../contribute/index.md#s Continue your journey through: * [Smart Contracts with Move](move.md) -* [Wallet Quick Start](wallet.md) +* [Sui client Quick Start](cli-client.md) * [RPC Server API](json-rpc.md) * [End-to-End tutorial](../explore/tutorials.md) diff --git a/doc/src/build/json-rpc.md b/doc/src/build/json-rpc.md index 90a0db18b01..222c22a92dc 100644 --- a/doc/src/build/json-rpc.md +++ b/doc/src/build/json-rpc.md @@ -4,14 +4,14 @@ title: Local RPC Server & JSON-RPC API Quick Start Welcome to the Sui RPC server quick start. -This document walks you through setting up your own local Sui RPC Server and using the Sui JSON-RPC API to interact with a local Sui network. This guide is useful for developers interested in Sui network interactions via API. For a similar guide on Sui network interactions via CLI, refer to the [wallet](wallet.md) documentation. +This document walks you through setting up your own local Sui RPC Server and using the Sui JSON-RPC API to interact with a local Sui network. This guide is useful for developers interested in Sui network interactions via API. For a similar guide on Sui network interactions via CLI, refer to the [Sui CLI client](cli-client.md) documentation. ## Local RPC server setup Follow the instructions to [install Sui binaries](install.md). ### Start local Sui network -Follow the instructions to [create](wallet.md#genesis) and [start](wallet.md#starting-the-network) the Sui network. +Follow the instructions to [create](cli-client.md#genesis) and [start](cli-client.md#starting-the-network) the Sui network. The genesis process will create a `gateway.conf` configuration file that will be used by the RPC server. ### Start local RPC server @@ -58,7 +58,7 @@ You can see an example of the discovery service in the [OpenRPC Playground](http ### sui_syncAccountState Synchronize client state with validators with the following command, -replacing `{{address}}` with an actual address value, for example one obtained from `wallet.conf`: +replacing `{{address}}` with an actual address value, for example one obtained from `client.yaml`: ```shell curl --location --request POST $SUI_RPC_HOST \ @@ -80,7 +80,7 @@ curl --location --request POST $SUI_RPC_HOST \ You should replace `{{address}}` in the command above with an actual address value, you can retrieve the list of the addresses created during -genesis from `wallet.conf`. Ensure you have run [`sui_syncAccountState`](#sui_syncaccountstate) +genesis from `client.yaml`. Ensure you have run [`sui_syncAccountState`](#sui_syncaccountstate) The output you see should resemble the following (abbreviated to show only two objects): @@ -147,7 +147,7 @@ A transaction data response will be returned from the gateway server. ``` #### 2, Sign the transaction using the Sui signtool ```shell -sui signtool --address --data +sui keytool sign --address --data ``` The signing tool will create and print out the signature and public key information. You will see output resembling: @@ -178,7 +178,7 @@ transferred natively and require a [Move call](#sui_movecall). You should replace `{{owner_address}}` and `{{to_address}}` in the command above with an actual address values, for example one obtained -from `wallet.conf`. You should also replace +from `client.yaml`. You should also replace `{{object_id}}` and `{{gas_object_id}}` in the command above with an actual object ID, for example one obtained from `objectId` in the output of [`sui_getOwnedObjects`](#sui_getownedobjects). You can see that all gas objects generated @@ -220,7 +220,7 @@ Follow the instructions to [execute the transaction](#3-execute-the-transaction- Arguments are passed in, and type will be inferred from function signature. Gas usage is capped by the gas_budget. The `transfer` function is described in more detail in -the [Sui Wallet](wallet.md#calling-move-code) documentation. +the [Sui CLI client](cli-client.md#calling-move-code) documentation. Calling the `transfer` function in the `Coin` module serves the same purpose as the native transfer ([`sui_transferObject`](#sui_TransferObject)), and is mostly used for illustration @@ -256,9 +256,9 @@ need to execute module initializers. You should replace `{{owner_address}}` in the command above with an actual address values, for example one obtained -from `wallet.conf`. You should also replace `{{gas_object_id}}` in the command above with +from `client.yaml`. You should also replace `{{gas_object_id}}` in the command above with an actual object ID, for example one obtained from `objectId` in the output -of [`sui_getownedobjects`](#sui_getownedobjects). You can see that all gas objects generated +of [`sui_getOwnedObjects`](#sui_getownedobjects). You can see that all gas objects generated during genesis are of `Coin/SUI` type). For this call to work, the object represented by `{{gas_object_id}}` must be owned by the address represented by `{{owner_address}}`. @@ -266,13 +266,13 @@ represented by `{{gas_object_id}}` must be owned by the address represented by To publish a Move module, you also need `{{vector_of_compiled_modules}}`. To generate the value of this field, use the `sui-move` command. The `sui-move` command supports printing the bytecodes as base64 with the following option ``` -sui-move --path build --dump-bytecode-as-base64 +sui move --path build --dump-bytecode-as-base64 ``` Assuming that the location of the package's sources is in the `PATH_TO_PACKAGE` environment variable an example command would resemble the following ``` -sui-move --path $PATH_TO_PACKAGE/my_move_package build --dump-bytecode-as-base64 +sui move --path $PATH_TO_PACKAGE/my_move_package build --dump-bytecode-as-base64 ["oRzrCwUAAAAJAQAIAggUAxw3BFMKBV1yB88BdAjDAigK6wIFDPACQgAAAQEBAgEDAAACAAEEDAEAAQEBDAEAAQMDAgAABQABAAAGAgEAAAcDBAAACAUBAAEFBwEBAAEKCQoBAgMLCwwAAgwNAQEIAQcODwEAAQgQAQEABAYFBgcICAYJBgMHCwEBCAALAgEIAAcIAwABBwgDAwcLAQEIAAMHCAMBCwIBCAADCwEBCAAFBwgDAQgAAgsCAQkABwsBAQkAAQsBAQgAAgkABwgDAQsBAQkAAQYIAwEFAgkABQMDBwsBAQkABwgDAQsCAQkAAgsBAQkABQdNQU5BR0VEBENvaW4IVHJhbnNmZXIJVHhDb250ZXh0C1RyZWFzdXJ5Q2FwBGJ1cm4EaW5pdARtaW50DHRyYW5zZmVyX2NhcAtkdW1teV9maWVsZA9jcmVhdGVfY3VycmVuY3kGc2VuZGVyCHRyYW5zZmVyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgACAQkBAAEAAAEECwELADgAAgEAAAAICwkSAAoAOAEMAQsBCwAuEQY4AgICAQAAAQULAQsACwI4AwIDAQAAAQQLAAsBOAQCAA==", "oRzrCwUAAAALAQAOAg4kAzJZBIsBHAWnAasBB9IC6QEIuwQoBuMECgrtBB0MigWzAQ29BgYAAAABAQIBAwEEAQUBBgAAAgAABwgAAgIMAQABBAQCAAEBAgAGBgIAAxAEAAISDAEAAQAIAAEAAAkCAwAACgQFAAALBgcAAAwEBQAADQQFAAIVCgUBAAIICwMBAAIWDQ4BAAIXERIBAgYYAhMAAhkCDgEABRoVAwEIAhsWAwEAAgsXDgEAAg0YBQEABgkHCQgMCA8JCQsMCw8MFAYPBgwNDA0PDgkPCQMHCAELAgEIAAcIBQILAgEIAwsCAQgEAQcIBQABBggBAQMEBwgBCwIBCAMLAgEIBAcIBQELAgEIAAMLAgEIBAMLAgEIAwEIAAEGCwIBCQACCwIBCQAHCwcBCQABCAMDBwsCAQkAAwcIBQELAgEJAAEIBAELBwEIAAIJAAcIBQELBwEJAAEIBgEIAQEJAAIHCwIBCQALAgEJAAMDBwsHAQkABwgFAQYLBwEJAAZCQVNLRVQHTUFOQUdFRARDb2luAklEA1NVSQhUcmFuc2ZlcglUeENvbnRleHQHUmVzZXJ2ZQRidXJuBGluaXQObWFuYWdlZF9zdXBwbHkEbWludApzdWlfc3VwcGx5DHRvdGFsX3N1cHBseQtkdW1teV9maWVsZAJpZAtWZXJzaW9uZWRJRAx0cmVhc3VyeV9jYXALVHJlYXN1cnlDYXADc3VpB21hbmFnZWQFdmFsdWUId2l0aGRyYXcPY3JlYXRlX2N1cnJlbmN5Bm5ld19pZAR6ZXJvDHNoYXJlX29iamVjdARqb2luAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgMIAAAAAAAAAAAAAgEOAQECBA8IBhELBwEIABMLAgEIAxQLAgEIBAABAAAIFg4BOAAMBAsBCgAPADgBCgAPAQoECgI4AgwFCwAPAgsECwI4AwwDCwULAwIBAAAAEA8JEgAKADgEDAEKABEKCwEKADgFCwA4BhIBOAcCAgEAAAMECwAQAjgIAgMBAAAFHA4BOAkMBAoEDgI4CCEDDgsAAQsDAQcAJwoADwELATgKCgAPAgsCOAsLBAsADwALAzgMAgQBAAADBAsAEAE4CQIFAQAAAwQLABAAOA0CAQEBAgEDAA=="] Build Successful diff --git a/doc/src/build/move.md b/doc/src/build/move.md index 231bbc24412..0d2c41ab4f0 100644 --- a/doc/src/build/move.md +++ b/doc/src/build/move.md @@ -234,7 +234,7 @@ to define the new ones in the section describing how to In addition to functions callable from other functions, however, the Sui flavor of the Move language also defines so called _entry functions_ that can be called directly from Sui (e.g., from a Sui -wallet application that can be written in a different language) and +application that can be written in a different language) and must satisfy a certain set of properties. #### Entry functions @@ -276,8 +276,8 @@ value, and has three parameters: in the function's body as indicated by its name starting with `_`) - Note that since it is unused, the parameter could be removed. The mutable reference to the `TxContext` is optional for entry functions. -You can see how the `transfer` function is called from a sample Sui -wallet in [Calling Move code](wallet.md#calling-move-code). +You can see how the `transfer` function is called from a Sui +CLI client in [Calling Move code](cli-client.md#calling-move-code). ## Writing a package @@ -395,7 +395,7 @@ In order to build a package containing this simple module, we need to put some required metadata into the `Move.toml` file, including package name, package version, local dependency path to locate Sui framework code, and package numeric ID, which must be `0x0` for user-defined modules -to facilitate [package publishing](wallet.md#publish-packages). +to facilitate [package publishing](cli-client.md#publish-packages). ``` [package] @@ -783,10 +783,10 @@ At this point, however, the `sui-move` command does not support package publishing. In fact, it is not clear if it even makes sense to accommodate package publishing, which happens once per package creation, in the context of a unit -testing framework. Instead, one can use a sample Sui wallet to -[publish](wallet.md#publish-packages) Move code and to -[call](wallet.md#calling-move-code) it. See the -[wallet documentation](wallet.md) for a description of how +testing framework. Instead, one can use a Sui CLI client to +[publish](cli-client.md#publish-packages) Move code and to +[call](cli-client.md#calling-move-code) it. See the +[Sui CLI client documentation](cli-client.md) for a description of how to publish the package we have [written](#writing-a-package) as as part of this tutorial. diff --git a/doc/src/build/programming-with-objects/ch1-object-basics.md b/doc/src/build/programming-with-objects/ch1-object-basics.md index 75c0105cc3c..ffc48542f73 100644 --- a/doc/src/build/programming-with-objects/ch1-object-basics.md +++ b/doc/src/build/programming-with-objects/ch1-object-basics.md @@ -146,17 +146,17 @@ sui-move test ``` ### On-chain Interactions -Now let's try to call `create` in actual transactions and see what happens. To do this, we need to start Sui and the wallet. Follow the [Wallet guide](../wallet.md) to start the Sui network and set up the wallet. +Now let's try to call `create` in actual transactions and see what happens. To do this, we need to start Sui and the CLI client. Follow the [Sui CLI client guide](../cli-client.md) to start the Sui network and set up the client. -Before starting, let's take a look at the default wallet address (this is the address that will eventually own the object later): +Before starting, let's take a look at the default client address (this is the address that will eventually own the object later): ``` -$ wallet active-address +$ sui client active-address ``` -This will tell you the current wallet address. +This will tell you the current client address. First, we need to publish the code on-chain. Assuming the path to the root of the repository containing Sui source code is $ROOT: ``` -$ wallet publish --path $ROOT/sui_programmability/examples/objects_tutorial --gas-budget 10000 +$ sui client publish --path $ROOT/sui_programmability/examples/objects_tutorial --gas-budget 10000 ``` You can find the published package object ID in the **Publish Results** output: ``` @@ -169,7 +169,7 @@ $ export PACKAGE=0x57258f32746fd1443f2a077c0c6ec03282087c19 ``` Next we can call the function to create a color object: ``` -$ wallet call --gas-budget 1000 --package $PACKAGE --module "ColorObject" --function "create" --args 0 255 0 +$ sui client call --gas-budget 1000 --package $PACKAGE --module "ColorObject" --function "create" --args 0 255 0 ``` In the **Transaction Effects** portion of the output, you will see an object showing up in the list of **Created Objects**, like this: @@ -183,7 +183,7 @@ $ export OBJECT=0x5eb2c3e55693282faa7f5b07ce1c4803e6fdc1bb ``` We can inspect this object and see what kind of object it is: ``` -$ wallet object --id $OBJECT +$ sui client object --id $OBJECT ``` This will show you the metadata of the object with its type: ``` @@ -193,11 +193,11 @@ ID: 0x5eb2c3e55693282faa7f5b07ce1c4803e6fdc1bb Readonly: false Type: 0x57258f32746fd1443f2a077c0c6ec03282087c19::color_object::ColorObject ``` -As we can see, it's owned by the current default wallet address that we saw earlier. And the type of this object is `ColorObject`! +As we can see, it's owned by the current default client address that we saw earlier. And the type of this object is `ColorObject`! You can also look at the data content of the object by adding the `--json` parameter: ``` -$ wallet object --id $OBJECT --json +$ sui client object --id $OBJECT --json ``` This will print the values of all the fields in the Move object, such as the values of `red`, `green`, and `blue`. diff --git a/doc/src/build/programming-with-objects/ch2-using-objects.md b/doc/src/build/programming-with-objects/ch2-using-objects.md index 2aad11aca1d..bdff39807c0 100644 --- a/doc/src/build/programming-with-objects/ch2-using-objects.md +++ b/doc/src/build/programming-with-objects/ch2-using-objects.md @@ -166,7 +166,7 @@ test_scenario::next_tx(scenario, &recipient); Now it's time to try this out on-chain. Assuming you have already followed the instructions in [Chapter 1](./ch1-object-basics.md#on-chain-interactions), you should already have the package published and a new object created. Now we can try to transfer it to another account address. First let's see what other account addresses you own: ``` -$ wallet addresses +$ sui client addresses ``` Since the default current address is the first address, let's pick the second address in the list as the recipient. In my case, I have `0x1416f3d5af469905b0580b9af843ec82d02efd30`. Let's save it for convenience: ``` @@ -174,33 +174,33 @@ $ export RECIPIENT=0x1416f3d5af469905b0580b9af843ec82d02efd30 ``` Now let's transfer the object to this address: ``` -$ wallet call --gas-budget 1000 --package $PACKAGE --module "ColorObject" --function "transfer" --args \"0x$OBJECT\" \"0x$RECIPIENT\" +$ sui client call --gas-budget 1000 --package $PACKAGE --module "ColorObject" --function "transfer" --args \"0x$OBJECT\" \"0x$RECIPIENT\" ``` Now let's see what objects the `RECIPIENT` owns: ``` -$ wallet objects --address $RECIPIENT +$ sui client objects --address $RECIPIENT ``` We should be able to see that one of the objects in the list is the new `ColorObject`! This means the transfer was successful. Let's also try to delete this object: ``` -$ wallet call --gas-budget 1000 --package $PACKAGE --module "ColorObject" --function "delete" --args \"0x$OBJECT\" +$ sui client call --gas-budget 1000 --package $PACKAGE --module "ColorObject" --function "delete" --args \"0x$OBJECT\" ``` Oops. It will error out and complain that the account address is unable to lock the object, which is a valid error because we have already transferred the object away from the original owner. -In order to operate on this object, we need to switch our wallet address to `$RECIPIENT`: +In order to operate on this object, we need to switch our client address to `$RECIPIENT`: ``` -$ wallet switch --address $RECIPIENT +$ sui client switch --address $RECIPIENT ``` And try the deletion again: ``` -$ wallet call --gas-budget 1000 --package $PACKAGE --module "ColorObject" --function "delete" --args \"0x$OBJECT\" +$ sui client call --gas-budget 1000 --package $PACKAGE --module "ColorObject" --function "delete" --args \"0x$OBJECT\" ``` In the output, you will see in the `Transaction Effects` section a list of deleted objects. This shows that the object was successfully deleted. If we run this again: ``` -$ wallet objects --address $RECIPIENT +$ sui client objects --address $RECIPIENT ``` -We will see that this object is no longer there in the wallet. +We will see that this object is no longer there in the address. Now you know how to pass objects by reference and value and transfer them on-chain. diff --git a/doc/src/build/programming-with-objects/ch3-immutable-objects.md b/doc/src/build/programming-with-objects/ch3-immutable-objects.md index 6beaacd61e9..8ec99628504 100644 --- a/doc/src/build/programming-with-objects/ch3-immutable-objects.md +++ b/doc/src/build/programming-with-objects/ch3-immutable-objects.md @@ -102,40 +102,40 @@ To summarize, we introduced three new API functions to interact with immutable o ### On-chain interactions First of all, take a look at the current list of objects you own: ``` -$ export ADDR=`wallet active-address` -$ wallet objects --address=$ADDR +$ export ADDR=`sui client active-address` +$ sui client objects --address=$ADDR ``` -Let's publish the `ColorObject` code on-chain using the wallet: +Let's publish the `ColorObject` code on-chain using the Sui CLI client: ``` -$ wallet publish --path $ROOT/sui_programmability/examples/objects_tutorial --gas-budget 10000 +$ sui client publish --path $ROOT/sui_programmability/examples/objects_tutorial --gas-budget 10000 ``` Set the package object ID to the `$PACKAGE` environment variable as we did in previous chapters. Then create a new `ColorObject`: ``` -$ wallet call --gas-budget 1000 --package $PACKAGE --module "color_object" --function "create" --args 0 255 0 +$ sui client call --gas-budget 1000 --package $PACKAGE --module "color_object" --function "create" --args 0 255 0 ``` -Set the newly created object ID to `$OBJECT`. If we look at the list of objects in the current active account address's wallet: +Set the newly created object ID to `$OBJECT`. If we look at the list of objects in the current active account address: ``` -$ wallet objects --address=$ADDR +$ sui client objects --address=$ADDR ``` There should be one more, with ID `$OBJECT`. Let's turn it into an immutable object: ``` -$ wallet call --gas-budget 1000 --package $PACKAGE --module "color_object" --function "freeze_object" --args \"0x$OBJECT\" +$ sui client call --gas-budget 1000 --package $PACKAGE --module "color_object" --function "freeze_object" --args \"0x$OBJECT\" ``` Now let's look at the list of objects we own again: ``` -$ wallet objects --address=$ADDR +$ sui client objects --address=$ADDR ``` `$OBJECT` is no longer there. It's no longer owned by anyone. You can see that it's now immutable by querying the object information: ``` -$ wallet object --id $OBJECT +$ sui client object --id $OBJECT Owner: Immutable ... ``` If we try to mutate it: ``` -$ wallet call --gas-budget 1000 --package $PACKAGE --module "color_object" --function "update" --args \"0x$OBJECT\" 0 0 0 +$ sui client call --gas-budget 1000 --package $PACKAGE --module "color_object" --function "update" --args \"0x$OBJECT\" 0 0 0 ``` It will complain that an immutable object cannot be passed to a mutable argument. diff --git a/doc/src/build/programming-with-objects/ch5-child-objects.md b/doc/src/build/programming-with-objects/ch5-child-objects.md index 75d2c61173f..5b30fa097ff 100644 --- a/doc/src/build/programming-with-objects/ch5-child-objects.md +++ b/doc/src/build/programming-with-objects/ch5-child-objects.md @@ -119,7 +119,7 @@ Both functions will compile successfully, because object ownership relationships Let's try to interact with these two entry functions on-chain and see what happens. First we publish the sample code: ``` -$ wallet publish --path sui_core/src/unit_tests/data/object_owner --gas-budget 5000 +$ sui client publish --path sui_core/src/unit_tests/data/object_owner --gas-budget 5000 ``` ``` ----- Publish Results ---- @@ -128,7 +128,7 @@ The newly published package object ID: 0x3cfcee192b2fbafbce74a211e40eaf9e4cb746b Then we create a child object: ``` $ export PKG=0x3cfcee192b2fbafbce74a211e40eaf9e4cb746b9 -$ wallet call --package $PKG --module object_owner --function create_child --gas-budget 1000 +$ sui client call --package $PKG --module object_owner --function create_child --gas-budget 1000 ``` ``` ----- Transaction Effects ---- @@ -138,7 +138,7 @@ Created Objects: At this point we only created the child object, but it's still owned by an account address. We can verify that we should be able to call `mutate_child` function by only passing in the child object: ``` $ export CHILD=0xb41d157fdeda968c5b5f0d8b87b6ebb84d7d1941 -$ wallet call --package $PKG --module object_owner --function mutate_child --args $CHILD --gas-budget 1000 +$ sui client call --package $PKG --module object_owner --function mutate_child --args $CHILD --gas-budget 1000 ``` ``` ----- Transaction Effects ---- @@ -150,7 +150,7 @@ Indeed the transasaction succeeded. Now let's create the `Parent` object as well: ``` -$ wallet call --package $PKG --module object_owner --function create_parent --gas-budget 1000 +$ sui client call --package $PKG --module object_owner --function create_parent --gas-budget 1000 ``` ``` ----- Transaction Effects ---- @@ -160,7 +160,7 @@ Created Objects: Now we can make the parent object own the child object: ``` $ export PARENT=0x2f893c18241cfbcd390875f6e1566f4db949392e -$ wallet call --package $PKG --module object_owner --function add_child --args $PARENT $CHILD --gas-budget 1000 +$ sui client call --package $PKG --module object_owner --function add_child --args $PARENT $CHILD --gas-budget 1000 ``` ``` ----- Transaction Effects ---- @@ -171,7 +171,7 @@ As we can see, the owner of the child object has been changed to the parent obje Now if we try to call `mutate_child` again, we will see an error: ``` -$ wallet call --package $PKG --module object_owner --function mutate_child --args $CHILD --gas-budget 1000 +$ sui client call --package $PKG --module object_owner --function mutate_child --args $CHILD --gas-budget 1000 ``` ``` Object 0xb41d157fdeda968c5b5f0d8b87b6ebb84d7d1941 is owned by object 0x2f893c18241cfbcd390875f6e1566f4db949392e, which is not in the input @@ -179,7 +179,7 @@ Object 0xb41d157fdeda968c5b5f0d8b87b6ebb84d7d1941 is owned by object 0x2f893c182 To be able to mutate the child object, we must also pass the parent object as argument. Hence we need to call the `mutate_child_with_parent` function: ``` -$ wallet call --package $PKG --module object_owner --function mutate_child_with_parent --args $CHILD $PARENT --gas-budget 1000 +$ sui client call --package $PKG --module object_owner --function mutate_child_with_parent --args $CHILD $PARENT --gas-budget 1000 ``` It will finish successfully. @@ -251,7 +251,7 @@ public entry fun delete_child(child: Child, _parent: &mut Parent) { id::delete(id); } ``` -If you follow the wallet interaction above and then try to call the `delete_child` function here on a child object, you will see the following runtime error: +If you follow the client interaction above and then try to call the `delete_child` function here on a child object, you will see the following runtime error: ``` An object that's owned by another object cannot be deleted or wrapped. It must be transferred to an account address first before deletion diff --git a/doc/src/build/pubsub.md b/doc/src/build/pubsub.md index 5a37c1df5ca..25dae6e39fc 100644 --- a/doc/src/build/pubsub.md +++ b/doc/src/build/pubsub.md @@ -152,14 +152,14 @@ We provide a few operators for combining filters: | Operator | Description | Example | |----------|-------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------:| | And | Combine two filters; behaves the same as boolean And operator | `{"And":[{"Package":"0x2"}, {"Module":"devnet_nft"}]}` | -| Or | Combine two filters; behaves the same as boolean Or operator | `{"Or":[{"Package":"0x2"}, {"Package":"0x1"}]}` | -| All | Combine a list of filters; returns true if all filters match the event | `{"All":[{"EventType":"MoveEvent"}, {"Package":"0x2"}, {"Module":"devnet_nft"}]}` | -| Any | Combine a list of filters; returns true if any filter matches the event | `{"Any":[{"EventType":"MoveEvent"}, {"EventType":"TransferObject"}, {"EventType":"DeleteObject"}]}` | +| Or | Combine two filters; behaves the same as boolean Or operator | `{"Or":[{"Package":"0x2"}, {"Package":"0x1"}]}` | +| All | Combine a list of filters; returns true if all filters match the event | `{"All":[{"EventType":"MoveEvent"}, {"Package":"0x2"}, {"Module":"devnet_nft"}]}` | +| Any | Combine a list of filters; returns true if any filter matches the event | `{"Any":[{"EventType":"MoveEvent"}, {"EventType":"TransferObject"}, {"EventType":"DeleteObject"}]}` | ## Examples ### Subscribe -Here is an example of subscribing to a stream of `MoveEvent` emitted by the `0x2::devnet_nft` package, which is created by the [Wallet CLI](wallet.md#creating-example-nfts) `create-example-nft` command: +Here is an example of subscribing to a stream of `MoveEvent` emitted by the `0x2::devnet_nft` package, which is created by the [Sui CLI client](cli-client.md#creating-example-nfts) `create-example-nft` command: ```shell >> {"jsonrpc":"2.0", "id": 1, "method": "sui_subscribeEvent", "params": [{"All":[{"EventType":"MoveEvent"}, {"Package":"0x2"}, {"Module":"devnet_nft"}]}} << {"jsonrpc":"2.0","result":3121662727959200,"id":1} diff --git a/doc/src/build/wallet.md b/doc/src/build/wallet.md deleted file mode 100644 index 5f2a51d86ca..00000000000 --- a/doc/src/build/wallet.md +++ /dev/null @@ -1,1143 +0,0 @@ ---- -title: Wallet Quick Start ---- - -Welcome to the Sui tutorial on the sample Sui wallet developed -to facilitate local experimentation with Sui features using a -command line interface. In this document, we describe how to set up -Sui wallet and execute wallet commands through its command line -interface, *Wallet CLI*. - -## Set up - -Follow the instructions to [install Sui binaries](install.md#binaries). - -## Connect to DevNet -We are hosting a public [DevNet](../explore/devnet.md) for the community to -experiment with our tech and help to shape the future of the Sui network. To -connect the wallet client to the DevNet, run the following command: -```shell -$ wallet -``` -The wallet will print the following line if the wallet is starting up the -first time. -```shell -Config file ["/Users/dir/.sui/sui_config/wallet.conf"] doesn't exist, do you want to connect to a Sui Gateway [y/n]? -``` -Type 'y' and then press 'Enter'. You should see the following output: -```shell -Sui Gateway Url (Default to Sui DevNet if not specified) : -``` -The wallet will prompt for the Gateway URL, press 'Enter' and it will default to the DevNet, -or enter the URL if you want to connect to a Gateway hosted elsewhere. - -If you have used the wallet before with a local network, follow the next section to -[manually change the Gateway URL](#manually-change-the-gateway-url) to DevNet. - -### Manually change the Gateway URL -If you have used the wallet before, you will have an existing `wallet.conf` configuration -file. Change the configured Gateway URL to DevNet by using: -```shell -$ wallet switch --gateway https://gateway.devnet.sui.io:443 -``` - -## Genesis - -The `genesis` command creates four validators and five user accounts -each with five gas objects. These are Sui [objects](objects.md) used -to pay for Sui [transactions](transactions.md#transaction-metadata), -such other object transfers or smart contract (Move) calls. These -numbers represent a sample configuration and have been chosen somewhat -arbitrarily; the process of generating the genesis state can be -customized with additional accounts, objects, code, etc. as described -in [Genesis customization](#customize-genesis). - -1. Optionally, set `RUST_LOG=debug` for verbose logging. -1. Initiate `genesis`: - ```shell - $ sui genesis - ``` - -All of this is contained in configuration and keystore files and an `authorities_db` -database directory. A `client_db` directory is also created upon running the -`wallet new-address` command covered later. - -The network configuration is stored in `network.conf` and can be used -subsequently to start the network. The `wallet.conf` and `wallet.key` -are also created to be used by the Sui wallet to manage the newly -created accounts. - -By default, these files are placed in your home directory at -`~/.sui/sui_config` (created automatically if it does not yet exist). But you -can override this location by providing an alternative path to the `--working-dir` -argument. Run the command like so to place the files in the `dir` directory: - -```shell -$ sui genesis --working-dir /path/to/sui/config/dir -``` - -:note: That path and directory must already exist and will not be -created with the `--working-dir` argument. - -### Recreating genesis - -To recreate Sui genesis state in the same location, which will remove -existing configuration files, pass the `--force` option to the `sui -genesis` command and either run it in the default directory (`~/.sui/sui_config`) or specify -it once again, using the `--working-dir` argument: - -```shell -$ sui genesis --force --working-dir /path/to/sui/config/dir -``` - -## Wallet configuration - -The genesis process creates a configuration file `wallet.conf`, and a keystore file `wallet.key` for the -Sui wallet. The config file contains information of the accounts and -the Sui Network Gateway. The keystore file contains all the public-private key pairs of the created accounts. -Sui wallet uses the network information in `wallet.conf` to communicate -with the Sui network validators and create transactions using the key -pairs residing in the keystore file. - -Here is an example of `wallet.conf` showing the accounts and key pairs -in the wallet configuration (with some values omitted): - -```json -{ - "accounts": [ - "0x48cf013a76d583c027720f7f9852deac7c84b923", - ... - ], - "keystore": { - "File": "./wallet.key" - }, - "gateway": { - "embedded": { - "authorities": [ - { - "name": "5f9701f4bd2cd7c2f1f23ac6d05515407879f0acf2611517ff188e59c5f61743", - "host": "127.0.0.1", - "base_port": 10000 - }, - ... - ], - "send_timeout": { - "secs": 4, - "nanos": 0 - }, - "recv_timeout": { - "secs": 4, - "nanos": 0 - }, - "buffer_size": 65507, - "db_folder_path": "./client_db" - } - } -} -``` - -The `accounts` variable contains the account's address that the wallet manages. The -`gateway` variable contains the information of the Sui network that the wallet will -be connecting to. Currently, only the `embedded` gateway type is supported. - -The `authorities` variable is part of the embedded gateway configuration. It contains -the Sui network validator's name, host and port information. It is used to establish connections -to the Sui network. - -Note `send_timeout`, `recv_timeout` and `buffer_size` are the network -parameters, and `db_folder_path` is the path to the account's client state -database. This database stores all the transaction data, certificates -and object data belonging to the account. - -### Sui Network Gateway - -The Sui Network Gateway (or simply, Sui Gateway) is an abstraction layer that acts as the entry -point to the Sui network. Different gateway implementations can be used by the application layer -based on their use cases. - -#### Embedded gateway - -As the name suggests, embedded gateway embeds the gateway logic into the application; -all data will be stored locally and the application will make direct -connection to the validators. - -#### RPC gateway -You can also connect the wallet to the Sui network via an [RPC Gateway](json-rpc.md#start-local-rpc-server); -To use the RPC gateway, update `wallet.conf`'s `gateway` section to: -```json -{ - ... - "gateway": { - "rpc":"http://127.0.0.1:5001" - }, - ... -} -``` - -### Key management - -The key pairs are stored in `wallet.key`. However, this is not secure -and shouldn't be used in a production environment. We have plans to -implement more secure key management and support hardware signing in a future release. - -:warning: **Do not use in production**: Keys are stored in file! - -## Starting the network - -Run the following command to start the local Sui network, assuming you -accepted the default location for configuration: - -```shell -$ sui start -``` - -This command will look for the Sui network configuration file -`network.conf` in the `~/.sui/sui_config` directory. But you can -override this setting by providing a path to the directory where -this file is stored: - -```shell -$ sui start --config /path/to/sui/network/config/file -``` - -For example: - -```shell -$ sui start --config /Users/name/tmp/network.conf -``` - -Executing any of these two commands in a terminal window will result -in no output but the terminal will be "blocked" by the running Sui -instance (it will not return the command prompt). The command can -also be run in background. - -NOTE: For logs, set `RUST_LOG=debug` before invoking `sui start`. - -If you see errors when trying to start Sui network, particularly if you made some custom changes - (e.g, -[customized wallet configuration](#wallet-configuration)), you should [recreate Sui genesis state](#recreating-genesis). - -## Using the wallet - -Now start a new terminal since you have Sui running in the first terminal. - -The following commands are supported by the wallet: - - active-address Default address used for commands when none specified - addresses Obtain the addresses managed by the wallet - call Call Move function - clear Clear screen (interactive only) - create-example-nft Create an example NFT - echo Write arguments to the console output (interactive only) - env Print environment (interactive only) - exit Exit the interactive shell (interactive only) - gas Obtain all gas objects owned by the address - help Print this message or the help of the given subcommand(s) - history Print history - merge-coin Merge two coin objects into one coin - new-address Generate new address and keypair - object Get object info - objects Obtain all objects owned by the address - publish Publish Move modules - split-coin Split a coin object into multiple coins - switch Switch active address and network(e.g., devnet, local rpc server) - sync Synchronize client state with authorities - transfer-coin Transfer coin object - -> **Note:** The `clear`, `echo`, `env` and `exit` commands exist only in the interactive shell. - -Use `wallet -h` to see the most up-to-date list of commands. - -Use `help ` to see more information on each command. - -You can start the wallet in two modes: interactive shell or command line interface. - -### Interactive shell - -To start the interactive shell, execute the following (in a different -terminal window than one used to execute `sui start`). Assuming you -accepted the default location for configuration: - -```shell -$ wallet -i -``` - -This command will look for the wallet configuration file -`wallet.conf` in the `~/.sui/sui_config` directory. But you can -override this setting by providing a path to the directory where this -file is stored: - -```shell -$ wallet -i --config /path/to/wallet/config/file -``` - -The Sui interactive wallet supports the following shell functionality: - -* *Command history* - - The `history` command can be used to print the interactive shell's command history; - you can also use Up, Down or Ctrl-P, Ctrl-N to navigate previous or next matches from history. - History search is also supported using Ctrl-R. -* *Tab completion* - - Tab completion is supported for all commands using Tab and Ctrl-I keys. -* *Environment variable substitution* - - The wallet shell will substitute inputs prefixed with `$` with environment variables, - you can use the `env` command to print out the entire list of variables and - use `echo` to preview the substitution without invoking any commands. - -### Command line mode - -The wallet can also be used without the interactive shell, which can be useful if -you want to pipe the output of the wallet to another application or invoke wallet -commands using scripts. - -```shell -USAGE: - wallet [SUBCOMMAND] -``` - -For example, we can use the following command to see the list of -accounts available on the platform: - -```shell -$ wallet addresses -``` - -The result of running this command should resemble the following output: - -```shell -Showing 5 results. -0x66af3898e7558b79e115ab61184a958497d1905a -0xae6fb6036570fec1df71599740c132cdf5b45b9d -0x45cda12e3bafe3017b4b3cd62c493e5fbaad7fb0 -0xef999dbdb19ccca504eef5432cec69ea8a1d4a1b -0x4489ab46a230c1876578441d68f25bf968e6f2b0 -``` - -But the actual address values will most likely differ -in your case (as will other values, such as object IDs, in the later -parts of this tutorial). Consequently, **do not copy and paste -the actual command from this tutorial as they are unlikely to work for -you verbatim**. Each time you create a config for the wallet, addresses -and object IDs will be assigned randomly. Consequently, you cannot rely -on copy-pasting commands that include these values, as they will be different -between different users/configs. - -### Active address - -Since a wallet manages multiple disjointed addresses, one might need to specify -which address they want to call a command on. - -For convenience, one can choose to set a default, or active address that will be -used for commands that require an address to operate on. A default address is picked -at the start, but this can be changed later. - -In order to see what the current active address is, use the command `active-address` - -```shell -$ wallet active-address -``` - -Which will reveal an address resembing: - -```shell -0x562f07cf6369e8d22dbf226a5bfedc6300014837 -``` - -Changing the default address is as easy as calling the `switch` command: - -```shell -$ wallet switch --address 0x913cf36f370613ed131868ac6f9da2420166062e -``` - -You will see output like: - -```shell -Active address switched to 0x913cf36f370613ed131868ac6f9da2420166062e -``` - -One can call, for example, the `objects` command with or without an address specified. -When not specified, the active address is used. - -``` -sui>-$ objects - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x0b8a4620426e526fa42995cf26eb610bfe6bf063 | 0 | o#6ea7e2d4bf47b3cc219fdc44bf15530244d3b3d1838d59586c0bb41d3db92221 - -sui>-$ objects --address 0x913cf36f370613ed131868ac6f9da2420166062e - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x0b8a4620426e526fa42995cf26eb610bfe6bf063 | 0 | o#6ea7e2d4bf47b3cc219fdc44bf15530244d3b3d1838d59586c0bb41d3db92221 -``` - -All commands where `address` is omitted will now use the newly specified active address: -0x913cf36f370613ed131868ac6f9da2420166062e - -Note that if one calls a command that uses a gas object not owned by the active address, -the address owned by the gas object is temporarily used for the transaction. - -### Paying For transactions with gas objects - -All Sui transactions require a gas object for payment, as well as a budget. However, specifying -the gas object can be cumbersome; so in the CLI, one is allowed to omit the gas object and leave -the wallet to pick an object that meets the specified budget. This gas selection logic is currently -rudimentary as it does not combine/split gas as needed but currently picks the first object it finds -that meets the budget. Note that one can always specify their own gas if they want to manage the gas -themselves. - -:warning: A gas object cannot be part of the transaction while also being used to -pay for the transaction. For example, one cannot try to transfer gas object X while paying for the -transaction with gas object X. The gas selection logic checks for this and rejects such cases. - -To see how much gas is in an account, use the `gas` command. Note that this command uses the -`active-address`, unless otherwise specified. - -```shell -$ wallet gas -``` - -You will see output like: - -``` - Object ID | Version | Gas Value ------------------------------------------------------------------------- - 0x0b8a4620426e526fa42995cf26eb610bfe6bf063 | 0 | 100000 - 0x3c0763ccdea4ff5a4557505a62ab5e1daf91f4a2 | 0 | 100000 - 0x45a589a9e760d7f75d399327ac0fcba21495c22e | 0 | 100000 - 0x4c377a3a9d4b1b9c92189dd12bb1dcd0302a954b | 0 | 100000 - 0xf2961464ac6860a05d21b48c020b7e121399965c | 0 | 100000 -``` - -If one does not want to use the active address, the addresses can be specified: - -```shell -$ wallet gas --address 0x562f07cf6369e8d22dbf226a5bfedc6300014837 - Object ID | Version | Gas Value ------------------------------------------------------------------------- - 0xa8ddc2661a19010e5f85cbf6d905ddfbe4dd0320 | 0 | 100000 - 0xb2683d0b592e5b002d110989a52943bc9da19158 | 0 | 100000 - 0xb41bf45b01c9befce3a0a371e2b98e062691438d | 0 | 100000 - 0xba9e10f319182f3bd584edb92c7899cc6d018723 | 0 | 100000 - 0xf8bfe77a5b21e7abfa3bc285991f9da4e5cc2d7b | 0 | 100000 - -``` - -## Adding accounts to the wallet - -Sui's genesis process will create five accounts by default; if that's -not enough, there are two ways to add accounts to the Sui wallet if needed. - -### Generating a new account - -To create a new account, execute the `new-address` command: - -```shell -$ wallet new-address -``` - -The output shows a confirmation after the account has been created: - -``` -Created new keypair for address : 0xc72cf3adcc4d11c03079cef2c8992aea5268677a -``` - -### Add existing accounts to `wallet.conf` manually - -If you have an existing key pair from an old wallet config, you can copy the account -address manually to the new `wallet.conf`'s accounts section, and add the key pair to the keystore file; -you won't be able to mutate objects if the account key is missing from the keystore. - -Restart the Sui wallet after the modification; the new accounts will appear in the wallet if you query the addresses. - -## View objects owned by the account - -You can use the `objects` command to view the objects owned by the address. - -`objects` command usage: - -```shell -USAGE: - objects [FLAGS] --address
- -FLAGS: - -h, --help Prints help information - -i Start interactive wallet - --json Returns command outputs in JSON format - -OPTIONS: - --address
Address owning the objects -``` - -To view the objects owned by the accounts created in genesis, run the following command (substitute the address with one of the genesis addresses in your wallet): - -```shell -$ wallet objects --address 0x66af3898e7558b79e115ab61184a958497d1905a -``` - -The result should resemble the following, which shows the object in the format of (`object_id`, `sequence_number`, `object_hash`). - -```shell - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x00a0a5211f6edcf4ba09d23b8a7250072be1edb6 | 0 | o#fbb33b6524d4a648fd5fff8dc93f3d6858945959b710a0893c2b86504b38f731 - 0x054c8263c73abd697a0f5aa8990d6d7668ce3d0d | 0 | o#cb99c4b8bb83a0b0111583cd2671f27d6eaeb89f89fd7ae822dc335f1a09e187 - 0x804aeaa287a7f87dd22a0885bd9e09aff71f1033 | 0 | o#3a7684039086ad33ea313f37d21ddaedd1cd95ed1f9564a61ba18f8e81ea017b - 0xda2237a9890bccebeeeae0d23ec739f00d2ce2b1 | 0 | o#db58b72bd45fb8331558a01baec42ad1575c5870bee882be5bae29c91856fe74 - 0xeea4167be074537f4a2879c7781d8ef4ffd651cc | 0 | o#ded63e5faac3953b25d55634a3471a27696f4886a293c7c6812123784548b7d4 -``` - -If you want to view more information about the objects, you can use the `object` command. - -Usage of `object` command : - -```shell -USAGE: - object [FLAGS] --id - -FLAGS: - -h, --help Prints help information - -i Start interactive wallet - --json Returns command outputs in JSON format - -OPTIONS: - --id Object ID of the object to fetch -``` - -To view the object, use the following command: - -```bash -$ wallet object --id 0x124bbde643189b573c98d05c092f4927225421d7 -``` - -This should give you output similar to the following: - -```shell -ID: 0x124bbde643189b573c98d05c092f4927225421d7 -Version: 1 -Owner: Account Address ( 0x62cd5bc220b28a34265bcb24995fb45a51d39832 ) -Type: 0x2::coin::Coin<0x2::sui::SUI> -``` - -The result shows some basic information about the object, the owner, -version, ID, if the object is immutable and the type of the object. - -> **Important:** To gain a deeper view into the object, include the -> `--json` flag in the `wallet` command to see the raw JSON representation -> of the object. - -Here is example `json` output: - -```json -{ - "contents": { - "fields": { - "balance": { - "fields": { - "value": 99126 - }, - "type": "0x2::balance::Balance<0x2::sui::SUI>" - }, - "id": { - "fields": { - "id": { - "fields": { - "id": { - "fields": { - "bytes": "124bbde643189b573c98d05c092f4927225421d7" - }, - "type": "0x2::id::ID" - } - }, - "type": "0x2::id::UniqueID" - }, - "version": 1 - }, - "type": "0x2::id::VersionedID" - } - }, - "type": "0x2::coin::Coin<0x2::sui::SUI>" - }, - "owner": { - "AddressOwner": "0x62cd5bc220b28a34265bcb24995fb45a51d39832" - }, - "tx_digest": "9811H0rZPbDwZ1dWRFLzQoKJarCue108+pzhGH7dAv4=" -} -``` - -## Transferring coins - -Coins *are* objects yet have a specific use case that allow for native commands like transfer-coin/merge-coin/split-coin to be used. This is different from non-coin objects that can only be mutated via [Move calls](#calling-move-code). - -If you inspect a newly created account, you would expect the account does not own any object. Let us inspect the fresh account we create in the [Generating a new account](#generating-a-new-account) section (`C72CF3ADCC4D11C03079CEF2C8992AEA5268677A`): - -```shell -$ wallet objects --address 0xc72cf3adcc4d11c03079cef2c8992aea5268677a - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- -Showing 0 results. -``` - -To add objects to the account, you can [invoke a Move function](#calling-move-code), -or you can transfer one of the existing coins from the genesis account to the new account using a dedicated wallet command. -We will explore how to transfer coins using the wallet in this section. - -`transfer-coin` command usage: - -```shell -USAGE: - transfer-coin [FLAGS] [OPTIONS] --to --coin-object-id --gas-budget - -FLAGS: - -h, --help Prints help information - -i Start interactive wallet - --json Returns command outputs in JSON format - -OPTIONS: - --coin-object-id Coin to transfer, in 20 bytes Hex string - --gas ID of the coin object for gas payment, in 20 bytes Hex string If not provided, a coin - object with at least gas_budget value will be selected - --gas-budget Gas budget for this transfer - --to Recipient address -``` - -To transfer a coin object to a recipient, you will need the recipient's address, -the object ID of the coin that you want to transfer, -and optionally the coin object ID for the transaction fee payment. If a gas -coin is not specified, one that meets the budget is picked. Gas budget sets a -cap for how much gas you want to spend. We are still finalizing our gas metering -mechanisms. For now, just set something large enough. - -Here is an example transfer of an object to account `0xf456ebef195e4a231488df56b762ac90695be2dd`: - -```shell -$ wallet transfer-coin --to 0xc72cf3adcc4d11c03079cef2c8992aea5268677a --coin-object-id 0xda2237a9890bccebeeeae0d23ec739f00d2ce2b1 --gas-budget 100 -``` - -With output like: - -``` -Transfer confirmed after 4412 us ------ Certificate ---- -Signed Authorities : [k#21d89c3a12409b7aeadf36a9753417ead5fa9ea607ccb666e83b739b8a73c5e8, k#8d86bef2f8ae835d4763c9a697ad5c458130907996d59adc4ea5be37f2e0fab2, k#f9664056f3cc46b03e86beeb3febf99af1c9ec3f6aa709a1dbd101c9e9a79c3a] -Transaction Kind : Transfer -Recipient : 0xc72cf3adcc4d11c03079cef2c8992aea5268677a -Object ID : 0xda2237a9890bccebeeeae0d23ec739f00d2ce2b1 -Sequence Number : SequenceNumber(0) -Object Digest : db58b72bd45fb8331558a01baec42ad1575c5870bee882be5bae29c91856fe74 - ------ Transaction Effects ---- -Status : Success { gas_used: 18, results: [] } -Mutated Objects: -0x00a0a5211f6edcf4ba09d23b8a7250072be1edb6 SequenceNumber(1) o#0a4be8bae4e4ea4d8e3a9f5d4ff8533aa36bff247238ab668edc1e5369843c64 -0xda2237a9890bccebeeeae0d23ec739f00d2ce2b1 SequenceNumber(1) o#f77edd77f5c154a850078b81b320870890bbb4f06d18f80fd512b1cc26bc3297 -``` - -The account will now have one object: - -```shell -$ wallet objects --address 0xc72cf3adcc4d11c03079cef2c8992aea5268677a - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0xda2237a9890bccebeeeae0d23ec739f00d2ce2b1 | 0 | o#f77edd77f5c154a850078b81b320870890bbb4f06d18f80fd512b1cc26bc3297 -``` - -## Creating example NFTs - -You may create an [NFT-like object](https://github.com/MystenLabs/sui/blob/main/crates/sui-framework/sources/devnet_nft.move#L16) on Sui using the following command: - -```shell -$ wallet create-example-nft -``` - -You will see output resembling: - -```shell -Successfully created an ExampleNFT: - -Owner: AddressOwner(k#66af3898e7558b79e115ab61184a958497d1905a) -Version: 1 -ID: 0x70874f1abd0a9a0126726a626ff48374f7b2d9c6 -Readonly: false -Type: 0x2::devnet_nft::DevNetNFT -``` - -The command will invoke the `mint` function in the `devnet_nft` module, which mints a Sui object with three attributes: name, description, and image URL with [default values](https://github.com/MystenLabs/sui/blob/27dff728a4c9cb65cd5d92a574105df20cb51887/sui/src/wallet_commands.rs#L39) and transfers the object to your address. You can also provide custom values using the following instructions: - - -`create-example-nft` command usage: - -```shell -USAGE: - wallet create-example-nft [OPTIONS] - -OPTIONS: - --description Description of the NFT - --gas ID of the gas object for gas payment, in 20 bytes hex string - If not provided, a gas object with at least gas_budget value - will be selected - --gas-budget Gas budget for this transfer - --name Name of the NFT - --url Display url(e.g., an image url) of the NFT -``` - - -## Merging and splitting coin objects - -Overtime, the account might receive coins from other accounts and will become unmanageable when -the number of coins grows; contrarily, the account might need to split the coins for payment or -for transfer to another account. - -We can use the `merge-coin` command and `split-coin` command to consolidate or split coins, respectively. - -### Merge coins - -Usage of `merge-coin`: - -```shell -USAGE: - merge-coin [FLAGS] [OPTIONS] --primary-coin --coin-to-merge --gas-budget - -FLAGS: - -h, --help Prints help information - -i Start interactive wallet - --json Returns command outputs in JSON format - -OPTIONS: - --coin-to-merge Coin to be merged, in 20 bytes Hex string - --gas ID of the gas object for gas payment, in 20 bytes Hex string If not provided, - a gas object with at least gas_budget value will be selected - --gas-budget Gas budget for this call - --primary-coin Coin to merge into, in 20 bytes Hex string -``` - -Here is an example of how to merge coins. To merge coins, you will need at lease three coin objects - -two coin objects for merging, and one for the gas payment. -You also need to specify the maximum gas budget that should be expanded for the coin merge operations. -Let us examine objects owned by address `0xef999dbdb19ccca504eef5432cec69ea8a1d4a1b` -and use the first coin (gas) object as the one to be the result of the merge, the second one to be merged, and the third one to be used as payment: - -```shell -$ wallet objects --address 0xef999dbdb19ccca504eef5432cec69ea8a1d4a1b -``` - -And its output: - -``` - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x149a3493c97fafc696526052fe08e77043d4be0b | 0 | o#2d50f098c913e1863ece507dcdcd5a291252f6c1df89ec8f16c62b542ac723b5 - 0x1b19f74ad77a95d7562432f6991ac9ec1ea2c57c | 0 | o#d390dc554759f892a714b2659046f3f47830cd789b3ec1df9d40bd876c3e1352 - 0x4c21fcc8ca953162877fe740f78d9c109145cc73 | 0 | o#18229401e7eb96bc23878e1f33d134e19ea5fd0a031bdb323c83baae4eab7097 - 0x646902fa947abf2e125131af0f3a9d5697c8f884 | 0 | o#f0bc58de072c0f028b02a0fe53644a74e5b490652c49471a99ffccb2fbb0e60e - 0xbec3bf567a6e32508c96663a339635dc0fb0095c | 0 | o#cfafb0b086cb2df2e8dfb25d84948a45aa19578c45bbaef98d1d5fbcf266db40 -``` - -Then we merge: -```shell -$ wallet merge-coin --primary-coin 0x149a3493c97fafc696526052fe08e77043d4be0b --coin-to-merge 0x1b19f74ad77a95d7562432f6991ac9ec1ea2c57c --gas-budget 1000 -``` - -With results resembling: - -``` ------ Certificate ---- -Signed Authorities : [k#21d89c3a12409b7aeadf36a9753417ead5fa9ea607ccb666e83b739b8a73c5e8, k#8d86bef2f8ae835d4763c9a697ad5c458130907996d59adc4ea5be37f2e0fab2, k#f9664056f3cc46b03e86beeb3febf99af1c9ec3f6aa709a1dbd101c9e9a79c3a] -Transaction Kind : Call -Gas Budget : 1000 -Package ID : 0x2 -Module : Coin -Function : join -Object Arguments : [(0x149a3493c97fafc696526052fe08e77043d4be0b, SequenceNumber(0), o#2d50f098c913e1863ece507dcdcd5a291252f6c1df89ec8f16c62b542ac723b5), (1B19F74AD77A95D7562432F6991AC9EC1EA2C57C, SequenceNumber(0), o#d390dc554759f892a714b2659046f3f47830cd789b3ec1df9d40bd876c3e1352)] -Pure Arguments : [] -Type Arguments : [Struct(StructTag { address: 0000000000000000000000000000000000000002, module: Identifier("sui"), name: Identifier("SUI"), type_params: [] })] - ------ Merge Coin Results ---- -Updated Coin : Coin { id: 0x149a3493c97fafc696526052fe08e77043d4be0b, value: 200000 } -Updated Gas : Coin { id: 0x4c21fcc8ca953162877fe740f78d9c109145cc73, value: 99995 } -``` - -### Split coins - -Usage of `split-coin`: - -```shell -USAGE: - split-coin [FLAGS] [OPTIONS] --coin-id --gas-budget - -FLAGS: - -h, --help Prints help information - -i Start interactive wallet - --json Returns command outputs in JSON format - -OPTIONS: - --amounts ... Amount to split out from the coin - --coin-id Coin to Split, in 20 bytes Hex string - --gas ID of the gas object for gas payment, in 20 bytes Hex string If not provided, a gas - object with at least gas_budget value will be selected - --gas-budget Gas budget for this call -``` - -For splitting coins, you will need at lease two coins to execute the `split-coin` command, -one coin to split, one for the gas payment. - -Let us examine objects owned by address `0x45cda12e3bafe3017b4b3cd62c493e5fbaad7fb0`: - -```shell -$ wallet objects --address 0x45cda12e3bafe3017b4b3cd62c493e5fbaad7fb0 -``` - -With output resembling: - -``` Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x13347bd461e8a2b9ee5de7f6131063a3050a45c4 | 0 | o#4ca351cbf507cac8162cb8278a38c1c9cdf4c6d2be05f2bee405da02ce8a4aa1 - 0xb402f52ba6216a770939e6d4922ae6d6d05c2256 | 0 | o#b95d120c36fab571c2389bccf507530a39e0055cdd9e9793aaf4ef691b1b8c96 - 0xba280146ecd5f74f5a0f31de4d1883bc078d3729 | 0 | o#edb2c038d6fd258b71d811cfa941216991d3a6bf99a783c90835becd443eb66c - 0xbd0c7b951a255b078044ef492099cd6e0ed1fd9b | 0 | o#9a937af506d95bb1ffc77ff8f8cc0fbcc550c566f9b41289e1f17d67fd1b9bf8 - 0xfc4d67d8c7db119901ef0a0d4bc9ec61584a0b2d | 0 | o#f1c1ca7cb3ef5f3e2a4fff5ec4ebc657388b1e2142432f66199886904eaf1669 -Showing 5 results. -``` - -Here is an example of splitting coins. We are splitting out three new coins from the original coin (first one on the list above), -with values of 1000, 5000 and 3000, respectively; note the `--amounts` argument accepts list of values. -We use the second coin on the list to pay for this transaction. - -```shell -$ wallet split-coin --coin-id 0x13347bd461e8a2b9ee5de7f6131063a3050a45c4 --amounts 1000 5000 3000 --gas-budget 1000 -``` - -You will see output resembling: - -``` ------ Certificate ---- -Signed Authorities : [k#21d89c3a12409b7aeadf36a9753417ead5fa9ea607ccb666e83b739b8a73c5e8, k#22d43b47ab73dc69819d7f3c840c9c24344bbd6b2e3692400d1c083825362865, k#8d86bef2f8ae835d4763c9a697ad5c458130907996d59adc4ea5be37f2e0fab2] -Transaction Kind : Call -Gas Budget : 1000 -Package ID : 0x2 -Module : Coin -Function : split_vec -Object Arguments : [(0x13347bd461e8a2b9ee5de7f6131063a3050a45c4, SequenceNumber(0), o#4ca351cbf507cac8162cb8278a38c1c9cdf4c6d2be05f2bee405da02ce8a4aa1)] -Pure Arguments : [[3, 232, 3, 0, 0, 0, 0, 0, 0, 136, 19, 0, 0, 0, 0, 0, 0, 184, 11, 0, 0, 0, 0, 0, 0]] -Type Arguments : [Struct(StructTag { address: 0000000000000000000000000000000000000002, module: Identifier("sui"), name: Identifier("SUI"), type_params: [] })] - ------ Split Coin Results ---- -Updated Coin : Coin { id: 0x13347bd461e8a2b9ee5de7f6131063a3050a45c4, value: 91000 } -New Coins : Coin { id: 0x72129fbf3168c37a4dd8ec7ee69da28d0d4d4636, value: 5000 }, - Coin { id: 0x821942c9375b644c6fc7531e46a70acb98fb5180, value: 1000 }, - Coin { id: 0xd2e65e9a3107662f7b6399bd1d82c235cfd8c874, value: 3000 } -Updated Gas : Coin { id: 0xb402f52ba6216a770939e6d4922ae6d6d05c2256, value: 99780 } - -$ wallet objects --address 0x45cda12e3bafe3017b4b3cd62c493e5fbaad7fb0 - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x13347bd461e8a2b9ee5de7f6131063a3050a45c4 | 1 | o#4f86a454ed9aa482adcbfece78cdd77d491d4e768aa8034af78a237d18e09f9f - 0x72129fbf3168c37a4dd8ec7ee69da28d0d4d4636 | 1 | o#247905d1c8eee09b4d3bd02f4229376cd7482705e28ef7ff4ca86774d09c72b8 - 0x821942c9375b644c6fc7531e46a70acb98fb5180 | 1 | o#51aefcb853df1d24b98b975795e21b90496135e292967f7dee0a8fc12079d3af - 0xb402f52ba6216a770939e6d4922ae6d6d05c2256 | 1 | o#9a20e2565db46aa371ab7932ab4b35494ef2e6a2251955a326e5f0fea6c0ee00 - 0xba280146ecd5f74f5a0f31de4d1883bc078d3729 | 0 | o#edb2c038d6fd258b71d811cfa941216991d3a6bf99a783c90835becd443eb66c - 0xbd0c7b951a255b078044ef492099cd6e0ed1fd9b | 0 | o#9a937af506d95bb1ffc77ff8f8cc0fbcc550c566f9b41289e1f17d67fd1b9bf8 - 0xd2e65e9a3107662f7b6399bd1d82c235cfd8c874 | 1 | o#c904eaa7b7cc659bc34beec8e7d5ab2cfc51236d498c12cde0d7542b3b1d8b89 - 0xfc4d67d8c7db119901ef0a0d4bc9ec61584a0b2d | 0 | o#f1c1ca7cb3ef5f3e2a4fff5ec4ebc657388b1e2142432f66199886904eaf1669 -Showing 8 results. -``` - -From the result, we can see three new coins were created in the transaction. - -## Calling Move code - -The genesis state of the Sui platform includes Move code that is -immediately ready to be called from Wallet CLI. Please see our -[Move developer documentation](move.md#first-look-at-move-source-code) -for the first look at Move source code and a description of the -following function we will be calling in this tutorial: - -```rust -public entry fun transfer(c: coin::Coin, recipient: address) { - coin::transfer(c, Address::new(recipient)) -} -``` - -Please note that there is no real need to use a Move call to transfer -coins as this can be accomplished with a built-in wallet -[command](#transferring-coins) - we chose this example due to its -simplicity. - -Let us examine objects owned by address `0xae6fb6036570fec1df71599740c132cdf5b45b9d`: - -```shell -$ wallet objects --address ae6fb6036570fec1df71599740c132cdf5b45b9d - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x5044dc15d3c71d500116eb026e8b70d0a180f3ac | 0 | o#748fabf1f7f92c8d00b54f5b431fd4e28d9dfd642cc0bc5c48b16dc0efdc58c1 - 0x749e3ee0e0ac93bfc06ed58972efe87717a428da | 0 | o#05efb7971ec89b78fd512913fb6f9bfbd0b5ffd2e99775493f9703ff153b3998 - 0x98765d1cbc66bdfc443aa60b614427470b266b28 | 0 | o#5f1696a263b9c97ba2e50175db0af1052a70943148b697fca98f98781482eba5 - 0xa9e4fda731fc888cc536da62c887c63e9becbe77 | 0 | o#ed2945e8d8a8a6c2f3fdc75a84c6cea2a9d74e2fce90779d6d3955c9416a75a1 - 0xb6e55f0eb3b820cb848b3bbb6db4bc34e54f2413 | 0 | o#4c6be9267d9aeb43f024c1604c765e3f127f8bc2dc4174a5fea5f26d1f7ed03e -Showing 5 results. -``` - -Now that we know which objects are owned by that address, -we can transfer one of them to another address, say the fresh one -we created in the [Generating a new account](#generating-a-new-account) section -(`0xc72cf3adcc4d11c03079cef2c8992aea5268677a`). We can try any object, -but for the sake of this exercise, let's choose the last one on the -list. - -We will perform the transfer by calling the `transfer` function from -the sui module using the following Sui Wallet command: - -```shell -$ wallet call --function transfer --module sui --package 0x2 --args 0x5044DC15D3C71D500116EB026E8B70D0A180F3AC 0xF456EBEF195E4A231488DF56B762AC90695BE2DD --gas-budget 1000 -``` - -This is a pretty complicated command so let's explain all of its -parameters one-by-one: - -* `--function` - name of the function to be called -* `--module` - name of the module containing the function -* `--package` - ID of the package object where the module containing - the function is located. (Remember - that the ID of the genesis Sui package containing the GAS module is - defined in its manifest file, and is equal to `0x2`.) -* `--args` - a list of function arguments formatted as - [SuiJSON](sui-json.md) values (hence the preceding `0x` in address - and object ID): - * ID of the gas object representing the `c` parameter of the `transfer` - function - * address of the new gas object owner -* `--gas` - an optional object containing gas used to pay for this - function call -* `--gas-budget` - a decimal value expressing how much gas we are - willing to pay for the `transfer` call to be completed to avoid - accidental drain of all gas in the gas pay) - -Note the third argument to the `transfer` function representing -`TxContext` does not have to be specified explicitly - it -is a required argument for all functions callable from Sui and is -auto-injected by the platform at the point of a function call. - -The output of the call command is a bit verbose, but the important -information that should be printed at the end indicates objects -changes as a result of the function call: - -```shell ------ Certificate ---- -Signed Authorities : [k#21d89c3a12409b7aeadf36a9753417ead5fa9ea607ccb666e83b739b8a73c5e8, k#f9664056f3cc46b03e86beeb3febf99af1c9ec3f6aa709a1dbd101c9e9a79c3a, k#8d86bef2f8ae835d4763c9a697ad5c458130907996d59adc4ea5be37f2e0fab2] -Transaction Kind : Call -Gas Budget : 1000 -Package ID : 0x2 -Module : sui -Function : transfer -Object Arguments : [(0x5044dc15d3c71d500116eb026e8b70d0a180f3ac, SequenceNumber(0), o#748fabf1f7f92c8d00b54f5b431fd4e28d9dfd642cc0bc5c48b16dc0efdc58c1)] -Pure Arguments : [[244, 86, 235, 239, 25, 94, 74, 35, 20, 136, 223, 86, 183, 98, 172, 144, 105, 91, 226, 221]] -Type Arguments : [] - ------ Transaction Effects ---- -Status : Success { gas_used: 11, results: [] } -Mutated Objects: -0x5044dc15d3c71d500116eb026e8b70d0a180f3ac SequenceNumber(1) o#6b384c50aa19204f3dd98dd52b39217ff234ed321cc2666b91ba6dadc14bd837 -0xb6e55f0eb3b820cb848b3bbb6db4bc34e54f2413 SequenceNumber(1) o#227a2127b17bdfd36c1f7982969588c3baea7a96f7019158018be1c4f152db04 -``` - -This output indicates the gas object -was updated to collect gas payment for the function call, and the -transferred object was updated as its owner had been -modified. We can confirm the latter (and thus a successful execution -of the `transfer` function) by querying objects that are now owned by -the sender: - -```shell -$ wallet objects --address 0xae6fb6036570fec1df71599740c132cdf5b45b9d - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x749e3ee0e0ac93bfc06ed58972efe87717a428da | 0 | o#05efb7971ec89b78fd512913fb6f9bfbd0b5ffd2e99775493f9703ff153b3998 - 0x98765d1cbc66bdfc443aa60b614427470b266b28 | 0 | o#5f1696a263b9c97ba2e50175db0af1052a70943148b697fca98f98781482eba5 - 0xa9e4fda731fc888cc536da62c887c63e9becbe77 | 0 | o#ed2945e8d8a8a6c2f3fdc75a84c6cea2a9d74e2fce90779d6d3955c9416a75a1 - 0xb6e55f0eb3b820cb848b3bbb6db4bc34e54f2413 | 1 | o#227a2127b17bdfd36c1f7982969588c3baea7a96f7019158018be1c4f152db04 -Showing 4 results. -``` - -We can now see this address no longer owns the transferred object. -And if we inspect this object, we can see it has the new -owner, different from the original one: - -```shell -$ wallet object --id 0x5044dc15d3c71d500116eb026e8b70d0a180f3ac -``` - -Resulting in: - -``` -Owner: AddressOwner(k#f456ebef195e4a231488df56b762ac90695be2dd) -Version: 1 -ID: 0x5044dc15d3c71d500116eb026e8b70d0a180f3ac -Readonly: false -Type: 0x2::coin::Coin<0x2::sui::SUI> -``` - -## Publish packages - -In order for user-written code to be available in Sui, it must be -*published* to Sui's [distributed ledger](../learn/how-sui-works.md#architecture). -Please see the [Move developer documentation](move.md) for a -description on how to [write a simple Move code package](move.md#writing-a-package), -which we can publish using Sui wallet's `publish` command. - -The publish command -requires us to specify a directory where the user-defined package lives. -It's the path to the `my_move_package` as per the -[package creation description](move.md#writing-a-package)), a gas -object that will be used to pay for publishing the package (we use the -same gas object we used to pay for the function call in the -[Calling Move code](#calling-move-code)) section, and gas budget to put -an upper limit (we use 1000 as our gas budget. - -Let us use the same address for publishing that we used for calling Move code in the previous [section](#calling-move-code) (`AE6FB6036570FEC1DF71599740C132CDF5B45B9D`) which now has 4 objecst left: - -```shell -$ wallet objects --address 0xae6fb6036570fec1df71599740c132cdf5b45b9d -``` - -Outputting: - -``` - Object ID | Version | Digest ------------------------------------------------------------------------------------------------------------------------------- - 0x749e3ee0e0ac93bfc06ed58972efe87717a428da | 0 | o#05efb7971ec89b78fd512913fb6f9bfbd0b5ffd2e99775493f9703ff153b3998 - 0x98765d1cbc66bdfc443aa60b614427470b266b28 | 0 | o#5f1696a263b9c97ba2e50175db0af1052a70943148b697fca98f98781482eba5 - 0xa9e4fda731fc888cc536da62c887c63e9becbe77 | 0 | o#ed2945e8d8a8a6c2f3fdc75a84c6cea2a9d74e2fce90779d6d3955c9416a75a1 - 0xb6e55f0eb3b820cb848b3bbb6db4bc34e54f2413 | 1 | o#227a2127b17bdfd36c1f7982969588c3baea7a96f7019158018be1c4f152db04 -Showing 4 results. -``` - -The whole command to publish a package for address -`0xae6fb6036570fec1df71599740c132cdf5b45b9d` resembles the following (assuming -that the location of the package's sources is in the `PATH_TO_PACKAGE` -environment variable): - -```shell -$ wallet publish --path $PATH_TO_PACKAGE/my_move_package --gas-budget 30000 -``` - -The result of running this command should look as follows: - -```shell ------ Certificate ---- -Signed Authorities : [k#21d89c3a12409b7aeadf36a9753417ead5fa9ea607ccb666e83b739b8a73c5e8, k#8d86bef2f8ae835d4763c9a697ad5c458130907996d59adc4ea5be37f2e0fab2, k#22d43b47ab73dc69819d7f3c840c9c24344bbd6b2e3692400d1c083825362865] -Transaction Kind : Publish -Gas Budget : 30000 - ------ Publish Results ---- -The newly published package object: (0xbaeef9626cc17311e6a3ee99b44ca453d2cc390f, SequenceNumber(1), o#9bf20104335bcffcaa51e39737206e87df53b6f907afca6117c82818e704968e) -List of objects created by running module initializers: -Owner: AddressOwner(k#ae6fb6036570fec1df71599740c132cdf5b45b9d) -Version: 1 -ID: 0xfdee51771ae2a264d61eb8a7726d43948b278b90 -Readonly: false -Type: 0xbaeef9626cc17311e6a3ee99b44ca453d2cc390f::M1::Forge -Updated Gas : Coin { id: 0x749e3ee0e0ac93bfc06ed58972efe87717a428da, value: 99232 } -``` - -Please note that running this command resulted in creating an object representing the published package. -From now on, we can use the package object ID (`0x52fa2ff453cfecba06bb84b3b43147c586960e69`) in the Sui wallet's call -command just like we used `0x2` for built-in packages in the -[Calling Move code](#calling-move-code) section. - -Another object created as a result of package publishing is a -user-defined object (of type `Forge`) crated inside initializer -function of the (only) module included in the published package - see -the part of Move developer documentation concerning [module -initializers](move.md#module-initializers) for more details on module -initializers. - -Finally, we see that the the gas object that was used to pay for -publishing was updated as well. - -## Customize genesis - -The genesis process can be customized by providing a genesis configuration -file using the `--config` flag. - -```shell -$ sui genesis --config -``` - -Example `genesis.conf`: - -```json -{ - "authorities": [ - { - "key_pair": "xWhgxF5fagohi2V9jzUToxnhJbTwbtV2qX4dbMGXR7lORTBuDBe+ppFDnnHz8L/BcYHWO76EuQzUYe5pnpLsFQ==", - "host": "127.0.0.1", - "port": 10000, - "db_path": "./authorities_db/4e45306e0c17bea691439e71f3f0bfc17181d63bbe84b90cd461ee699e92ec15", - "stake": 1 - } - ], - "accounts": [ - { - "address": "0xbd654f352c895d9ec14c491d3f2b4e1f98fb07323383bebe9f95ab625bff2fa0", - "gas_objects": [ - { - "object_id": "0x5c68ac7ba66ef69fdea0651a21b531a37bf342b7", - "gas_value": 1000 - } - ] - } - ], - "move_packages": [""], - "sui_framework_lib_path": "", - "move_framework_lib_path": "" -} -``` - -All attributes in `genesis.conf` are optional, and default values -will be used if the attributes are not provided. -For example, the -config shown below will create a network of four validators, and -pre-populate two gas objects for four newly generated accounts: - -```json -{ - "authorities": [ - {},{},{},{} - ], - "accounts": [ - { "gas_objects":[{},{}] }, - { "gas_objects":[{},{}] }, - { "gas_objects":[{},{}] }, - { "gas_objects":[{},{}] } - ] -} -``` - -If you use any custom accounts in `genesis.conf`, ensure you have a corresponding private key in -`wallet.key`. Ensure `wallet.key` is in the working directory of the wallet. If you do not have the private key of the addresses specified, you cannot use custom genesis. *Never share your private keys.* For testing the `genesis.conf` example below, you can use the following private key: - -`genesis.conf` - -``` -{ - "authorities": [ - {},{},{},{} - ], - "accounts": [ - { - "address": "0x09818aac3edf9cf9b006b70c36e7241768b26386", - "gas_objects": [ - { - "object_id": "0000000000000000000000000000000000000003", - "gas_value": 10000000 - } - ] - } - ] -} -``` -`wallet.key` -``` -[ - "WKk4nT2oyPKbFrFAyepT5wEsummWsA6qdhsqzc6CVC9fvTt3J2u6yy5WuW9B6OU3mkcyPC/4Axstn0BpIhzZNg==", -] -``` diff --git a/doc/src/contribute/faq.md b/doc/src/contribute/faq.md index 1fb7ac939df..4dcb0d5fa1e 100644 --- a/doc/src/contribute/faq.md +++ b/doc/src/contribute/faq.md @@ -86,7 +86,7 @@ For developers: 1. [Install Sui](https://docs.sui.io/build/install). 2. Spin up a [Sui Fullnode](../build/fullnode.md). -3. Experiment with the [Sui Wallet](../build/wallet.md). +3. Experiment with the [Sui CLI client](../build/cli-client.md). 4. Join the [Move](https://discord.gg/8prNjUqyFj) and [Sui](https://discord.gg/CVcnUzKYCB) developer channels in Discord. 5. [Start building](https://docs.sui.io/build)! @@ -137,7 +137,7 @@ See the instructions to [run a Sui Fullnode](../build/fullnode.md). We have a public [Sui DevNet](../explore/devnet.md) with nodes operated by Mysten Labs. And you can now run a networked [Sui Fullnode](../build/fullnode.md). -You may also run a local, non-networked Sui node for development using the [Sui Wallet](../build/wallet.md). You can interact with the nodes with either the [Sui Wallet CLI](../build/wallet.md#command-line-mode) or over the [Sui RPC API](../build/json-rpc.md). +You may also run a local, non-networked Sui node for development using the [Sui CLI client](../build/cli-client.md). You can interact with the nodes with either the [Sui Wallet CLI](../build/cli-client.md#command-line-mode) or over the [Sui RPC API](../build/json-rpc.md). Soon we will have a TestNet that allow others to operate Sui nodes, but both are on our [roadmap](https://github.com/MystenLabs/sui/blob/main/ROADMAP.md#roadmap). Right now, diff --git a/doc/src/contribute/observability.md b/doc/src/contribute/observability.md index 5bdab7be444..8ec989a55b6 100644 --- a/doc/src/contribute/observability.md +++ b/doc/src/contribute/observability.md @@ -193,7 +193,7 @@ To see nested spans visualized with [Jaeger](https://www.jaegertracing.io), do t ```shell $ SUI_TRACING_ENABLE=1 RUST_LOG="info,sui_core=trace" ./sui start ``` -1. Run some transfers with wallet, or run the benchmarking tool. +1. Run some transfers with Sui CLI client, or run the benchmarking tool. 4. Browse to `http://localhost:16686/` and select Sui as the service. > **Note:** Separate spans (which are not nested) are not connected as a single trace for now. diff --git a/doc/src/explore/devnet.md b/doc/src/explore/devnet.md index 674d773cb54..73f2df24015 100644 --- a/doc/src/explore/devnet.md +++ b/doc/src/explore/devnet.md @@ -14,7 +14,7 @@ Many improvements to the Sui DevNet are underway, such as the ability to run ful We provide the following tools for users to interact with the Sui Devnet: -* The [Sui Wallet command line interface (CLI)](../build/wallet.md) +* The [Sui Wallet command line interface (CLI)](../build/cli-client.md) * create and manage your private keys * submit transactions for creating example NFTs * call and publish Move modules @@ -28,12 +28,12 @@ You may simply [install Sui](../build/install.md) and then request test tokens a 1. Sui [test coins (tokens)](#request-gas-tokens) requested through [Discord](https://discordapp.com/channels/916379725201563759/971488439931392130). 1. the [`git` command line interface](https://git-scm.com/download/). -1. [Sui binaries](../build/install.md#binaries) in your PATH environment variable, particularly `wallet`. +1. [Sui binaries](../build/install.md#binaries) in your PATH environment variable, particularly `sui`. Remember, you can confirm the existence of a command in your PATH by running `which` followed by the command, for example: ```shell -$ which wallet +$ which sui ``` You should see the path to the command. Otherwise, reinstall. @@ -41,9 +41,9 @@ You should see the path to the command. Otherwise, reinstall. In addition, to conduct advanced work such as publishing a Move module or making a Move call, also obtain the [Sui source code](../build/install.md#source-code); for simplicity, we recommend installing in `~/sui` or using an environment variable. -### Set up wallet, connect to gateway +### Set up Sui CLI client, connect to gateway -Now [set up your wallet and connect to DevNet](../build/wallet.md#connect-to-devnet) in a single step. Note you can [manually change the Gateway URL](../build/wallet.md#manually-change-the-gateway-url) if you have already configured a Sui wallet. +Now [set up your Sui CLI client and connect to DevNet](../build/cli-client.md#connect-to-devnet) in a single step. Note you can [manually change the Gateway URL](../build/cli-client.md#manually-change-the-rpc-server-url) if you have already configured a Sui CLI client. > **Tip:** If you run into issues, reset the Sui configuration by removing its directory, by default located at `~/.sui/sui_config`. Then reinstall [Sui binaries](../build/install.md#binaries). @@ -51,18 +51,18 @@ Now [set up your wallet and connect to DevNet](../build/wallet.md#connect-to-dev ### Request gas tokens -Request gas tokens by posting your wallet address in the [#devnet-faucet](https://discordapp.com/channels/916379725201563759/971488439931392130) Discord channel if you haven't already and wait for them to be issued. +Request gas tokens by posting your address in the [#devnet-faucet](https://discordapp.com/channels/916379725201563759/971488439931392130) Discord channel if you haven't already and wait for them to be issued. -You can find your wallet address by running: +You can find your address by running: ```shell -$ wallet active-address +$ sui client active-address ``` ### Mint an example NFT To create a Non-Fungible Token (NFT), run: ```shell -$ wallet create-example-nft +$ sui client create-example-nft ``` You will see output resembling: @@ -75,7 +75,7 @@ Owner: Account Address ( 9E9A9D406961E478AA80F4A6B2B167673F3DF8BA ) Type: 0x2::devnet_nft::DevNetNFT ``` -The above command created an object with ID `ED883F6812AF447B9B0CE220DA5EA9E0F58012FE`. Note you may use `wallet` to [view objects owned by the account](https://docs.sui.io/build/wallet#view-objects-owned-by-the-account). +The above command created an object with ID `ED883F6812AF447B9B0CE220DA5EA9E0F58012FE`. Note you may use `Sui CLI client` to [view objects owned by the account](https://docs.sui.io/build/wallet#view-objects-owned-by-the-account). Now you can view the created object in the [Sui Explorer](https://explorer.devnet.sui.io) at: https://explorer.devnet.sui.io/objects/ED883F6812AF447B9B0CE220DA5EA9E0F58012FE @@ -86,7 +86,7 @@ Replace the object ID in the link above with the object ID of the Example NFT yo Note you may easily customize the name, description, or image of the NFT upon creation, like so: ```shell -$ wallet create-example-nft --url=https://user-images.githubusercontent.com/76067158/166136286-c60fe70e-b982-4813-932a-0414d0f55cfb.png --description="The greatest chef in the world" --name="Greatest Chef" +$ sui client create-example-nft --url=https://user-images.githubusercontent.com/76067158/166136286-c60fe70e-b982-4813-932a-0414d0f55cfb.png --description="The greatest chef in the world" --name="Greatest Chef" ``` Which results in a new object ID: @@ -124,7 +124,7 @@ See the [Sui Explorer README](https://github.com/MystenLabs/sui/tree/main/explor Publish a sample Move package containing code developed in the [Sui Move tutorial](../build/move.md#writing-a-package) as follows (assuming you installed the source code in `~sui` as advised in set up): ```shell -$ wallet publish --path /sui_programmability/examples/move_tutorial --gas-budget 30000 +$ sui client publish --path /sui_programmability/examples/move_tutorial --gas-budget 30000 ``` You will see this output: @@ -156,9 +156,9 @@ Specific object IDs displayed above may differ from one Sui installation to the In the previous section, we learned how to publish a Move package; and in this section, we will learn how to call into functions defined in this package. As a result of publishing a package, we obtained the new package object ID () and ID of the `Forge` object () that can be used to create swords and transfer them to other players. -Let’s assume that the placeholder for the address of the player to receive a sword is . If you don’t know any address other than your own, you can create one using the following `wallet` command and use it whenever you see the placeholder: +Let’s assume that the placeholder for the address of the player to receive a sword is . If you don’t know any address other than your own, you can create one using the following `client` command and use it whenever you see the placeholder: ```shell -$ wallet new-address +$ sui client new-address ``` Which yields output resembling: @@ -172,7 +172,7 @@ In order to create a sword and transfer it to another player, we use the followi Now run: ```shell -$ wallet call --function sword_create --module M1 --package 0x --args \"0x\" 42 7 \"0x\" --gas-budget 30000 +$ sui client call --function sword_create --module M1 --package 0x --args \"0x\" 42 7 \"0x\" --gas-budget 30000 ``` And receive output like: diff --git a/doc/src/explore/tutorials.md b/doc/src/explore/tutorials.md index 332fc3afab1..741c12f047f 100644 --- a/doc/src/explore/tutorials.md +++ b/doc/src/explore/tutorials.md @@ -3,7 +3,7 @@ title: End-to-End Tutorial to Set Up and Play TicTacToe on Sui --- In this tutorial, we demonstrate the end-to-end process for starting a -Sui network locally, connecting to it through our [wallet](../build/wallet.md) +Sui network locally, connecting to it through our [CLI client](../build/cli-client.md) app, publishing a TicTacToe game written in [Move](../build/move.md) on Sui, and playing it to the end. @@ -11,13 +11,13 @@ and playing it to the end. 1. [Install Sui binaries](../build/install.md#binaries) and [download Sui source code](../build/install.md#source-code). -1. [Create Sui genesis](../build/wallet.md#genesis) by running the +1. [Create Sui genesis](../build/cli-client.md#genesis) by running the `sui genesis` command. -1. [Start the Sui network](../build/wallet.md#starting-the-network) by +1. [Start the Sui network](../build/cli-client.md#starting-the-network) by running the `sui start` command. After completing these steps, you will have a running local Sui instance and -the `wallet` command used in the remainder of this tutorial in your path. +the `sui client` command used in the remainder of this tutorial in your path. Simply leave the terminal with Sui running and start a new terminal for the remainder of this tutorial. @@ -29,9 +29,9 @@ gas units) times the price of gas in the SUI currency (i.e. the gas price). ## Gather accounts and gas objects In that new terminal, let us take a look at the account addresses we own in -our wallet with the command: +our CLI client with the command: ```shell -$ wallet addresses +$ sui client addresses ``` Which will result in output resembling: @@ -53,7 +53,7 @@ export PLAYER_O=251CF224B6BA3A019D04B6041357C20490F7A322 For each of these addresses, let's discover their gas objects for each account address: ``` -$ wallet gas --address $ADMIN +$ sui client gas --address $ADMIN Object ID | Version | Gas Value ---------------------------------------------------------------------- 38B89FE9F4A4823F1406938E87A8767CBD7F0B93 | 0 | 100000 @@ -61,7 +61,7 @@ $ wallet gas --address $ADMIN 6AB7D15F41B28FF1EBF6D32499214BBD9035D1EB | 0 | 100000 800F2704E22637A036C4325B539D711BB83CA6C2 | 0 | 100000 D2F52301D5343DD2C1FA076401BC6283C3E4AA34 | 0 | 100000 -$ wallet gas --address $PLAYER_X +$ sui client gas --address $PLAYER_X Object ID | Version | Gas Value ---------------------------------------------------------------------- 6F675038CAA48184707DBBE95ACFBA2030E87CD8 | 0 | 100000 @@ -69,7 +69,7 @@ $ wallet gas --address $PLAYER_X 9FED1FC3D21F284DC53DE87C0E19718971D96D8C | 0 | 100000 E293F935F015C23216867442DB4E712518E7CAB7 | 0 | 100000 F19384C06AE538F9C3C9D9762002B4DAEA49FE3A | 0 | 100000 -$ wallet gas --address $PLAYER_O +$ sui client gas --address $PLAYER_O Object ID | Version | Gas Value ---------------------------------------------------------------------- 2110ADFB7BAF889A05EA6F5889AF7724299F9BED | 0 | 100000 @@ -93,7 +93,7 @@ Find even more [examples](examples.md) in the Sui repository. Of course, you are To publish the game, we run the publish command and specify the path to the source code of the game package: ```shell -$ wallet publish --path ./sui/sui_programmability/examples/games --gas $ADMIN_GAS --gas-budget 30000 +$ sui client publish --path ./sui/sui_programmability/examples/games --gas $ADMIN_GAS --gas-budget 30000 ``` Which will yield results resembling: @@ -125,7 +125,7 @@ Because the admin owns the gameboard, each individual player cannot place a mark Now let's begin the game! First of all, let's create a game with the command: ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function create_game --args $PLAYER_X $PLAYER_O --gas $ADMIN_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function create_game --args $PLAYER_X $PLAYER_O --gas $ADMIN_GAS --gas-budget 1000 ``` You will see output like: @@ -151,21 +151,21 @@ Mutated Objects: ``` The above call created three objects. For each object, it printed out a tuple of three values (object_id, version, object_digest). Object ID is what we care about here. Since we don't have a real application here to display things for us, we need a bit of object printing magic to figure out which object is which. Let's print out the metadata of each created object (replace the object ID with what you see on your screen): ``` -$ wallet object --id 5851B7EA07B93E68696BC0CF811D2E266DFB880D +$ sui client object --id 5851B7EA07B93E68696BC0CF811D2E266DFB880D Owner: AddressOwner(k#251cf224b6ba3a019d04b6041357c20490f7a322) Version: 1 ID: 5851B7EA07B93E68696BC0CF811D2E266DFB880D Readonly: false Type: 0xa613a7ff8cb03e0dfc0d157e232bba50c5f19d17::TicTacToe::MarkMintCap -$ wallet object --id A6D3B507D4533822E690291166891D42694A2721 +$ sui client object --id A6D3B507D4533822E690291166891D42694A2721 Owner: AddressOwner(k#7b61da6aaced7f28c1187d998955f10464beae55) Version: 1 ID: A6D3B507D4533822E690291166891D42694A2721 Readonly: false Type: 0xa613a7ff8cb03e0dfc0d157e232bba50c5f19d17::TicTacToe::MarkMintCap -$ wallet object --id F1B8161BD97D3CD6627E739AD675089C5ACFB452 +$ sui client object --id F1B8161BD97D3CD6627E739AD675089C5ACFB452 Owner: AddressOwner(k#ecf53ce22d1b2fb588573924057e9addad1d8385) Version: 1 ID: F1B8161BD97D3CD6627E739AD675089C5ACFB452 @@ -191,7 +191,7 @@ public entry fun send_mark_to_game(cap: &mut MarkMintCap, game_address: address, ``` The `cap` argument will be Player X's capability object (XCAP), and `game_address` argument will be the admin's address (ADMIN): ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $XCAP $ADMIN 1 1 --gas $X_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $XCAP $ADMIN 1 1 --gas $X_GAS --gas-budget 1000 ``` And its output: ```shell @@ -219,7 +219,7 @@ public entry fun place_mark(game: &mut TicTacToe, mark: Mark, ctx: &mut TxContex ``` The first argument is the game board, and the second argument is the mark the admin just received from the player. We will call this function (replace the second argument with the Mark object ID above): ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0xAE3CE9176F1A8C1F21D922722486DF667FA00394 --gas $ADMIN_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0xAE3CE9176F1A8C1F21D922722486DF667FA00394 --gas $ADMIN_GAS --gas-budget 1000 ``` The gameboard now looks like this (this won't be printed out, so keep it in your imagination): ``` @@ -230,7 +230,7 @@ _|X|_ Player O now tries to put a mark at (0, 0): ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $OCAP $ADMIN 0 0 --gas $O_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $OCAP $ADMIN 0 0 --gas $O_GAS --gas-budget 1000 ``` With output like: @@ -246,7 +246,7 @@ Created Objects: Note, in this second call, the second argument comes from the created objects in the first call. ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0x7A16D266DAD41145F34649258BC1F744D147BF2F --gas $ADMIN_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0x7A16D266DAD41145F34649258BC1F744D147BF2F --gas $ADMIN_GAS --gas-budget 1000 ``` With output like: @@ -266,7 +266,7 @@ _|X|_ Player X puts a mark at (0, 2): ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $XCAP $ADMIN 0 2 --gas $X_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $XCAP $ADMIN 0 2 --gas $X_GAS --gas-budget 1000 ``` With output like: @@ -282,7 +282,7 @@ Created Objects: Then run: ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0x2875D50BD9021ED2009A1278C7CB6D4C876FFF6A --gas $ADMIN_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0x2875D50BD9021ED2009A1278C7CB6D4C876FFF6A --gas $ADMIN_GAS --gas-budget 1000 ``` The gameboard now looks like this: @@ -294,7 +294,7 @@ _|X|_ Player O places a mark at (1, 0): ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $OCAP $ADMIN 1 0 --gas $O_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $OCAP $ADMIN 1 0 --gas $O_GAS --gas-budget 1000 ``` With output like: @@ -310,7 +310,7 @@ Created Objects: Now run: ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0x4F7391F172063D87013DD9DC95B8BD45C35FD2D9 --gas $ADMIN_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0x4F7391F172063D87013DD9DC95B8BD45C35FD2D9 --gas $ADMIN_GAS --gas-budget 1000 ... ``` The gameboard now looks like: @@ -321,7 +321,7 @@ O|X|_ ``` This is a chance for Player X to win! X now mints the winning mark at (2, 0): ```shell -$ wallet call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $XCAP $ADMIN 2 0 --gas $X_GAS --gas-budget 1000 +$ sui client call --package $PACKAGE --module TicTacToe --function send_mark_to_game --args $XCAP $ADMIN 2 0 --gas $X_GAS --gas-budget 1000 ``` And its output: @@ -337,7 +337,7 @@ AA7A6624E16E5E447801462FF6614013FC4AD156 SequenceNumber(1) o#e5e1b15f03531db118e And then finally the admin places the winning mark: ```shell - $ wallet call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0xAA7A6624E16E5E447801462FF6614013FC4AD156 --gas $ADMIN_GAS --gas-budget 1000 + $ sui client call --package $PACKAGE --module TicTacToe --function place_mark --args $GAME 0xAA7A6624E16E5E447801462FF6614013FC4AD156 --gas $ADMIN_GAS --gas-budget 1000 ``` With output: @@ -354,7 +354,7 @@ Mutated Objects: Cool! The last transaction created a new object. Let's find out what object was created: ```shell -$ wallet object --id 54B58C0D5B14A269B1CD424B3CCAB1E315C43343 +$ sui client object --id 54B58C0D5B14A269B1CD424B3CCAB1E315C43343 ``` See output resembling: diff --git a/doc/src/learn/architecture/validators.md b/doc/src/learn/architecture/validators.md index f2d6a75859d..d96925065e8 100644 --- a/doc/src/learn/architecture/validators.md +++ b/doc/src/learn/architecture/validators.md @@ -8,7 +8,7 @@ Sui uses proof of stake (PoS) to determine which validators operate the network ## Epochs -Operation of the Sui network is temporally partitioned into non-overlapping, approximate fixed-duration (e.g. 24-hour) *epochs*. During a particular epoch, the set of validators participating in the network is fixed. At an epoch boundary, reconfiguration may occur and can change the set of validators participating in the network and their voting power. Conceptually, reconfiguration starts a new instance of the Sui protocol with the previous epoch's final state as [genesis](../../build/wallet.md#genesis) and the new set of validators as the operators. +Operation of the Sui network is temporally partitioned into non-overlapping, approximate fixed-duration (e.g. 24-hour) *epochs*. During a particular epoch, the set of validators participating in the network is fixed. At an epoch boundary, reconfiguration may occur and can change the set of validators participating in the network and their voting power. Conceptually, reconfiguration starts a new instance of the Sui protocol with the previous epoch's final state as [genesis](../../build/cli-client.md#genesis) and the new set of validators as the operators. ## Quorums diff --git a/doc/src/learn/index.md b/doc/src/learn/index.md index 2dfd63c4f8f..82afea9f70e 100644 --- a/doc/src/learn/index.md +++ b/doc/src/learn/index.md @@ -36,8 +36,8 @@ See the Sui `doc/src` [history](https://github.com/MystenLabs/sui/commits/main/d ### Move quick start Go to the [Move Quick Start](../build/move.md) for installation, defining custom objects, object operations (create/destroy/update/transfer/freeze), publishing, and invoking your published code. -### Wallet quick start -See the [Wallet Quick Start](../build/wallet.md) for installation, querying the chain, client setup, sending transfer transactions, and viewing the effects. +### Sui CLI client quick start +See the [Sui CLI client Quick Start](../build/cli-client.md) for installation, querying the chain, client setup, sending transfer transactions, and viewing the effects. ### End-to-end tutorial Proceed to the [Sui Tutorial](../explore/tutorials.md) for a summary view of setting up your environment, starting a Sui network, gathering accounts and gas, and publishing and playing a game in Sui. @@ -50,7 +50,7 @@ Finish with the detailed [Programming with objects](../build/programming-with-ob Navigate and search this site however you see fit. Here is the order we recommend if you are new to Sui: 1. Learn [about Sui](../learn/about-sui.md), how [Sui Move differs from Core Move](../learn/sui-move-diffs.md), and [how Sui works](../learn/how-sui-works.md) starting in this very section. -1. [Build](../build/index.md) smart contracts, wallets, validators, transactions, and more. +1. [Build](../build/index.md) smart contracts, the Sui client, a Sui fullnode, and more. 1. [Explore](../explore/index.md) prototypes and examples. 1. [Contribute](../contribute/index.md) to Sui by joining the community, making enhancements, and learning about Mysten Labs. 1. Employ the [Sui API Reference](https://playground.open-rpc.org/?uiSchema%5BappBar%5D%5Bui:splitView%5D=false&schemaUrl=https://raw.githubusercontent.com/MystenLabs/sui/main/sui/open_rpc/spec/openrpc.json&uiSchema%5BappBar%5D%5Bui:input%5D=false) reference files for the [Sui JSON-RPC API](../build/json-rpc.md). diff --git a/doc/src/learn/sui-glossary.md b/doc/src/learn/sui-glossary.md index 2f243f6534a..eac72f51df5 100644 --- a/doc/src/learn/sui-glossary.md +++ b/doc/src/learn/sui-glossary.md @@ -65,7 +65,7 @@ stage is considered closure for an exchange or other blockchain transaction. Genesis is the initial act of creating accounts and gas objects. Sui provides a `genesis` command that allows users to create and inspect the genesis object setting up the network for operation. -For more information, see [Genesis](../build/wallet.md#genesis). +For more information, see [Genesis](../build/cli-client.md#genesis). ### Gateway service @@ -124,10 +124,10 @@ For more information, see [Causal order vs total order](sui-compared#causal-orde ### Transfer A transfer is switching the owner address of a token to a new one via command in Sui. This is accomplished via the -[Sui Wallet](../build/wallet.md) command line interface. It is one of the more common of many commands -available in the wallet. +[Sui CLI client](../build/cli-client.md) command line interface. It is one of the more common of many commands +available in the CLI client. -For more information, see [Transferring objects](../build/wallet.md#transferring-objects). +For more information, see [Transferring objects](../build/cli-client.md#transferring-objects). ### Validator diff --git a/doc/utils/sui-setup.sh b/doc/utils/sui-setup.sh index d6952b28324..865814bcf84 100644 --- a/doc/utils/sui-setup.sh +++ b/doc/utils/sui-setup.sh @@ -15,7 +15,7 @@ command -v cargo >/dev/null 2>&1 || { echo "Cargo (https://doc.rust-lang.org/car rm -rf sui/ ## Build and install Sui binaries -cargo install --locked --git https://github.com/MystenLabs/sui.git --branch devnet sui +cargo install --locked --git https://github.com/MystenLabs/sui.git --branch devnet sui sui-json-rpc ## Install Move Analyzer language server plugin cargo install --git https://github.com/move-language/move move-analyzer diff --git a/docker/sui-tools/Dockerfile b/docker/sui-tools/Dockerfile index 64efa11b688..5702a95f90d 100644 --- a/docker/sui-tools/Dockerfile +++ b/docker/sui-tools/Dockerfile @@ -1,5 +1,7 @@ FROM rust:1.60.0 AS chef WORKDIR sui +ARG GIT_REVISION +ENV GIT_REVISION=$GIT_REVISION RUN apt-get update && apt-get install -y cmake clang # Plan out the 3rd-party dependencies that need to be built. @@ -37,18 +39,15 @@ COPY crates crates RUN cargo build --release \ --bin sui-node \ --bin sui \ - --bin wallet \ - --bin sui-move + --bin rpc-server # Production Image FROM debian:bullseye-slim AS runtime WORKDIR sui COPY --from=builder /sui/target/release/sui-node /usr/local/bin COPY --from=builder /sui/target/release/sui /usr/local/bin -COPY --from=builder /sui/target/release/wallet /usr/local/bin -COPY --from=builder /sui/target/release/sui-move /usr/local/bin +COPY --from=builder /sui/target/release/rpc-server /usr/local/bin ARG BUILD_DATE -ARG GIT_REVISION LABEL build-date=$BUILD_DATE LABEL git-revision=$GIT_REVISION diff --git a/docker/sui-tools/build.sh b/docker/sui-tools/build.sh index b4ab3b4c781..63eaa474ccf 100755 --- a/docker/sui-tools/build.sh +++ b/docker/sui-tools/build.sh @@ -12,7 +12,7 @@ GIT_REVISION="$(git describe --always --dirty)" BUILD_DATE="$(date -u +'%Y-%m-%d')" echo -echo "Building sui-node docker image" +echo "Building sui-tool docker image" echo "Dockerfile: \t$DOCKERFILE" echo "docker context: $REPO_ROOT" echo "build date: \t$BUILD_DATE"