diff --git a/.circleci/token/run.sh b/.circleci/token/run.sh index e52735ed54..812d1c2b85 100644 --- a/.circleci/token/run.sh +++ b/.circleci/token/run.sh @@ -21,6 +21,7 @@ fi echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Publicly mint 100 tokens for Alice. @@ -55,6 +56,7 @@ leo run mint_public aleo13ssze66adjjkt795z9u5wpq8h6kn0y2657726h4h3e3wfnez4vqsm30 echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Privately mint 100 tokens for Bob. @@ -89,6 +91,7 @@ leo run mint_private aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqyshd echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Publicly transfer 10 tokens from Alice to Bob. @@ -123,6 +126,7 @@ leo run transfer_public aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4calsrrqdaqy echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Privately transfer 20 tokens from Bob to Alice. @@ -161,6 +165,7 @@ leo run transfer_private "{ echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Convert 30 public tokens from Alice into 30 private tokens for Bob. @@ -196,6 +201,7 @@ leo run transfer_public_to_private aleo17vy26rpdhqx4598y5gp7nvaa9rk7tnvl6ufhvvf4 echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Convert 40 private tokens from Bob into 40 public tokens for Alice. @@ -237,4 +243,5 @@ leo run transfer_private_to_public "{ echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env diff --git a/Cargo.lock b/Cargo.lock index d6aedbda84..210aef6332 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -742,6 +742,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dialoguer" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" +dependencies = [ + "console", + "shell-words", + "tempfile", + "thiserror", + "zeroize", +] + [[package]] name = "difflib" version = "0.4.0" @@ -858,6 +871,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-iterator" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c280b9e6b3ae19e152d8e31cf47f18389781e119d4013a2a2bb0180e5facc635" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" +dependencies = [ + "proc-macro2", + "quote 1.0.36", + "syn 2.0.66", +] + [[package]] name = "enum_index" version = "0.2.0" @@ -1544,6 +1577,7 @@ dependencies = [ "colored", "console", "crossterm", + "dialoguer", "dirs 5.0.1", "dotenvy", "indexmap 1.9.3", @@ -1582,6 +1616,7 @@ name = "leo-package" version = "1.12.0" dependencies = [ "aleo-std", + "dialoguer", "indexmap 1.9.3", "lazy_static", "leo-errors", @@ -2740,6 +2775,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "signal-hook" version = "0.3.17" @@ -2810,7 +2851,7 @@ dependencies = [ [[package]] name = "snarkvm" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "anstyle", "anyhow", @@ -2839,7 +2880,7 @@ dependencies = [ [[package]] name = "snarkvm-algorithms" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "anyhow", @@ -2869,7 +2910,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-algorithms", @@ -2883,7 +2924,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-account" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-network", @@ -2894,7 +2935,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-algorithms" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-types", "snarkvm-console-algorithms", @@ -2904,7 +2945,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-collections" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-types", @@ -2914,7 +2955,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "indexmap 2.2.6", "itertools 0.11.0", @@ -2932,12 +2973,12 @@ dependencies = [ [[package]] name = "snarkvm-circuit-environment-witness" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" [[package]] name = "snarkvm-circuit-network" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-collections", @@ -2948,7 +2989,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-program" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "paste", "snarkvm-circuit-account", @@ -2963,7 +3004,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-address", @@ -2978,7 +3019,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-address" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -2991,7 +3032,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-boolean" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-environment", "snarkvm-console-types-boolean", @@ -3000,7 +3041,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-field" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3010,7 +3051,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-group" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3022,7 +3063,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-integers" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3034,7 +3075,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-scalar" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3045,7 +3086,7 @@ dependencies = [ [[package]] name = "snarkvm-circuit-types-string" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3057,7 +3098,7 @@ dependencies = [ [[package]] name = "snarkvm-console" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-account", "snarkvm-console-algorithms", @@ -3070,7 +3111,7 @@ dependencies = [ [[package]] name = "snarkvm-console-account" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "bs58", "snarkvm-console-network", @@ -3081,7 +3122,7 @@ dependencies = [ [[package]] name = "snarkvm-console-algorithms" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "blake2s_simd", "smallvec", @@ -3094,7 +3135,7 @@ dependencies = [ [[package]] name = "snarkvm-console-collections" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "rayon", @@ -3105,7 +3146,7 @@ dependencies = [ [[package]] name = "snarkvm-console-network" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "anyhow", "indexmap 2.2.6", @@ -3128,7 +3169,7 @@ dependencies = [ [[package]] name = "snarkvm-console-network-environment" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "anyhow", "bech32", @@ -3146,8 +3187,9 @@ dependencies = [ [[package]] name = "snarkvm-console-program" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ + "enum-iterator", "enum_index", "enum_index_derive", "indexmap 2.2.6", @@ -3167,7 +3209,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-address", @@ -3182,7 +3224,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-address" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3193,7 +3235,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-boolean" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-network-environment", ] @@ -3201,7 +3243,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-field" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3211,7 +3253,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-group" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3222,7 +3264,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-integers" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3233,7 +3275,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-scalar" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3244,7 +3286,7 @@ dependencies = [ [[package]] name = "snarkvm-console-types-string" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3255,7 +3297,7 @@ dependencies = [ [[package]] name = "snarkvm-curves" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "rand", "rayon", @@ -3269,7 +3311,7 @@ dependencies = [ [[package]] name = "snarkvm-fields" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "anyhow", @@ -3286,7 +3328,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "anyhow", @@ -3310,7 +3352,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-authority" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "anyhow", "rand", @@ -3322,7 +3364,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-block" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3341,7 +3383,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-committee" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3353,7 +3395,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-ledger-narwhal-batch-certificate", "snarkvm-ledger-narwhal-batch-header", @@ -3366,7 +3408,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-batch-certificate" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3379,7 +3421,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-batch-header" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3391,7 +3433,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-data" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "bytes", "serde_json", @@ -3402,7 +3444,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-subdag" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3417,7 +3459,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-transmission" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "bytes", "serde_json", @@ -3430,7 +3472,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-narwhal-transmission-id" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "snarkvm-console", "snarkvm-ledger-puzzle", @@ -3439,7 +3481,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-puzzle" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "anyhow", @@ -3459,7 +3501,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-puzzle-epoch" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "anyhow", "colored", @@ -3474,7 +3516,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-query" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "async-trait", "reqwest 0.11.27", @@ -3487,7 +3529,7 @@ dependencies = [ [[package]] name = "snarkvm-ledger-store" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std-storage", "anyhow", @@ -3510,7 +3552,7 @@ dependencies = [ [[package]] name = "snarkvm-parameters" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "anyhow", @@ -3535,7 +3577,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "anyhow", @@ -3545,6 +3587,7 @@ dependencies = [ "parking_lot", "rand", "rayon", + "serde_json", "snarkvm-algorithms", "snarkvm-circuit", "snarkvm-console", @@ -3564,7 +3607,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-process" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "colored", @@ -3587,7 +3630,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-program" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "indexmap 2.2.6", "paste", @@ -3601,7 +3644,7 @@ dependencies = [ [[package]] name = "snarkvm-synthesizer-snark" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "bincode", "once_cell", @@ -3614,7 +3657,7 @@ dependencies = [ [[package]] name = "snarkvm-utilities" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "aleo-std", "anyhow", @@ -3635,7 +3678,7 @@ dependencies = [ [[package]] name = "snarkvm-utilities-derives" version = "0.16.19" -source = "git+https://github.com/AleoNet/snarkVM.git?rev=fddd8b9#fddd8b92b4c6417e37d62722b3b937534dc4fb26" +source = "git+https://github.com/AleoNet/snarkVM.git?rev=8a05317#8a053177f46dc4383d5a8adcc6b14e4c73f34c82" dependencies = [ "proc-macro2", "quote 1.0.36", diff --git a/Cargo.toml b/Cargo.toml index 08e094dd42..15d1038f27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ members = [ [workspace.dependencies.snarkvm] #version = "0.16.19" git = "https://github.com/AleoNet/snarkVM.git" -rev = "fddd8b9" +rev = "d170a9f" [lib] path = "leo/lib.rs" @@ -61,6 +61,7 @@ ci_skip = [ "leo-compiler/ci_skip" ] noconfig = [ ] [dependencies] +dialoguer = "0.11.0" num-format = "0.4.4" text-tables = "0.3.1" ureq = "2.9.7" diff --git a/compiler/compiler/tests/utilities/mod.rs b/compiler/compiler/tests/utilities/mod.rs index 3eeab76f6d..227e65fed0 100644 --- a/compiler/compiler/tests/utilities/mod.rs +++ b/compiler/compiler/tests/utilities/mod.rs @@ -121,6 +121,7 @@ pub fn setup_build_directory( program_name: &str, bytecode: &String, handler: &Handler, + endpoint: String, ) -> Result, ()> { // Initialize a temporary directory. let directory = temp_dir(); @@ -137,7 +138,7 @@ pub fn setup_build_directory( let _manifest_file = Manifest::create(&directory, &program_id).unwrap(); // Create the environment file. - Env::::new().unwrap().write_to(&directory).unwrap(); + Env::::new(None, endpoint).unwrap().write_to(&directory); if Env::::exists_at(&directory) { println!(".env file created at {:?}", &directory); } @@ -283,14 +284,3 @@ pub fn compile_and_process<'a>(parsed: &'a mut Compiler<'a, CurrentNetwork>) -> Ok(bytecode) } - -/// Returns the private key from the .env file specified in the directory. -#[allow(unused)] -pub fn dotenv_private_key(directory: &Path) -> Result> { - use std::str::FromStr; - dotenvy::from_path(directory.join(".env")).map_err(|_| anyhow!("Missing a '.env' file in the test directory."))?; - // Load the private key from the environment. - let private_key = dotenvy::var("PRIVATE_KEY").map_err(|e| anyhow!("Missing PRIVATE_KEY - {e}"))?; - // Parse the private key. - PrivateKey::::from_str(&private_key) -} diff --git a/errors/src/errors/cli/cli_errors.rs b/errors/src/errors/cli/cli_errors.rs index 15f9308394..556fdec39e 100644 --- a/errors/src/errors/cli/cli_errors.rs +++ b/errors/src/errors/cli/cli_errors.rs @@ -264,4 +264,60 @@ create_messages!( msg: format!("{error}"), help: None, } + + @backtraced + failed_to_get_endpoint_from_env { + args: (), + msg: "Failed to get an endpoint.".to_string(), + help: Some("Either make sure you have a `.env` file in current project directory with an `ENDPOINT` variable set, or set the `--endpoint` flag when invoking the CLI command.\n Example: `ENDPOINT=https://api.explorer.aleo.org/v1` or `leo build --endpoint \"https://api.explorer.aleo.org/v1\"`.".to_string()), + } + + @backtraced + failed_to_get_private_key_from_env { + args: (), + msg: "Failed to get a private key.".to_string(), + help: Some("Either make sure you have a `.env` file in current project directory with a `PRIVATE_KEY` variable set, or set the `--private-key` flag when invoking the CLI command.\n Example: `PRIVATE_KEY=0x1234...` or `leo deploy --private-key \"APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH\"`.".to_string()), + } + + @backtraced + failed_to_get_network_from_env { + args: (), + msg: "Failed to get a network.".to_string(), + help: Some("Either make sure you have a `.env` file in current project directory with a `NETWORK` variable set, or set the `--network` flag when invoking the CLI command.\n Example: `NETWORK=testnet` or `leo build --network testnet`.".to_string()), + } + + @backtraced + constraint_limit_exceeded { + args: (program: impl Display, limit: u64, network: impl Display), + msg: format!("Program `{program}` exceeds the constraint limit {limit} for deployment on network {network}."), + help: Some("Reduce the number of constraints in the program by reducing the number of instructions in transition functions.".to_string()), + } + + @backtraced + variable_limit_exceeded { + args: (program: impl Display, limit: u64, network: impl Display), + msg: format!("Program `{program}` exceeds the variable limit {limit} for deployment on network {network}."), + help: Some("Reduce the number of variables in the program by reducing the number of instructions in transition functions.".to_string()), + } + + @backtraced + confirmation_failed { + args: (), + msg: "Failed to confirm transaction".to_string(), + help: None, + } + + @backtraced + invalid_balance { + args: (account: impl Display), + msg: format!("Invalid public balance for account: {account}"), + help: Some("Make sure the account has enough balance to pay for the deployment.".to_string()), + } + + @backtraced + table_render_failed { + args: (error: impl Display), + msg: format!("Failed to render table.\nError: {error}"), + help: None, + } ); diff --git a/errors/src/errors/mod.rs b/errors/src/errors/mod.rs index bbebd974a7..f52f608696 100644 --- a/errors/src/errors/mod.rs +++ b/errors/src/errors/mod.rs @@ -109,7 +109,7 @@ impl LeoError { FlattenError(error) => error.error_code(), UtilError(error) => error.error_code(), LastErrorCode(_) => unreachable!(), - Anyhow(_) => unimplemented!(), // todo: implement error codes for snarkvm errors. + Anyhow(_) => "SnarkVM Error".to_string(), // todo: implement error codes for snarkvm errors. } } @@ -128,7 +128,7 @@ impl LeoError { FlattenError(error) => error.exit_code(), UtilError(error) => error.exit_code(), LastErrorCode(code) => *code, - Anyhow(_) => unimplemented!(), // todo: implement exit codes for snarkvm errors. + Anyhow(_) => 11000, // todo: implement exit codes for snarkvm errors. } } } diff --git a/errors/src/errors/package/package_errors.rs b/errors/src/errors/package/package_errors.rs index c33ca4accd..74ce8eada6 100644 --- a/errors/src/errors/package/package_errors.rs +++ b/errors/src/errors/package/package_errors.rs @@ -418,4 +418,18 @@ create_messages!( msg: format!("❌ Execution error: {error}"), help: Some("Make sure that you are using the right `--network` options.".to_string()), } + + @backtraced + snarkvm_error { + args: (error: impl Display), + msg: format!("[snarkVM Error] {error}"), + help: None, + } + + @backtraced + failed_to_load_package { + args: (path: impl Display), + msg: format!("Failed to load leo project at path {path}"), + help: Some("Make sure that the path is correct and that the project exists.".to_string()), + } ); diff --git a/errors/src/errors/utils/util_errors.rs b/errors/src/errors/utils/util_errors.rs index dbab5af28d..da25660922 100644 --- a/errors/src/errors/utils/util_errors.rs +++ b/errors/src/errors/utils/util_errors.rs @@ -193,4 +193,11 @@ create_messages!( msg: format!("Invalid field: {field}."), help: Some("Field element must be numerical string with optional \"field\" suffix.".to_string()), } + + @backtraced + invalid_bound { + args: (bound: impl Display), + msg: format!("Invalid bound: {bound}."), + help: Some("Bound must be a valid u32.".to_string()), + } ); diff --git a/examples/auction/.env b/examples/auction/.env index 391701926c..f5b42ea894 100644 --- a/examples/auction/.env +++ b/examples/auction/.env @@ -1,4 +1,4 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH - +ENDPOINT=https://localhost:3030 diff --git a/examples/auction/run.sh b/examples/auction/run.sh index d13f3de839..d94296f936 100755 --- a/examples/auction/run.sh +++ b/examples/auction/run.sh @@ -40,6 +40,7 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Have the first bidder place a bid of 10. @@ -62,6 +63,7 @@ leo run place_bid aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9p echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Have the second bidder place a bid of 90. @@ -84,6 +86,7 @@ leo run place_bid aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4 echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2GUmKbVsuc1NSj28pa1WTQuZaK5f1DQJAT6vPcHyWokG +ENDPOINT=https://localhost:3030 " > .env # Have the auctioneer select the winning bid. @@ -141,6 +144,7 @@ leo run finish "{ echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env diff --git a/examples/basic_bank/.env b/examples/basic_bank/.env index 391701926c..f5b42ea894 100644 --- a/examples/basic_bank/.env +++ b/examples/basic_bank/.env @@ -1,4 +1,4 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH - +ENDPOINT=https://localhost:3030 diff --git a/examples/basic_bank/run.sh b/examples/basic_bank/run.sh index 9ac451db87..7ba84051f8 100755 --- a/examples/basic_bank/run.sh +++ b/examples/basic_bank/run.sh @@ -20,6 +20,7 @@ fi echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Have the bank issue 100 tokens to the user. @@ -70,6 +71,7 @@ leo run issue aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t 10 echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Have the user deposit 50 tokens into the bank. @@ -164,6 +166,7 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Have the bank withdraw all of the user's tokens with compound interest over 15 periods at 12.34%. diff --git a/examples/battleship/.env b/examples/battleship/.env index 59936403c4..f0216e5f1b 100644 --- a/examples/battleship/.env +++ b/examples/battleship/.env @@ -1,4 +1,5 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 diff --git a/examples/battleship/run.sh b/examples/battleship/run.sh index e6e86718aa..0f6d6eacae 100755 --- a/examples/battleship/run.sh +++ b/examples/battleship/run.sh @@ -19,6 +19,7 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env echo "✅ Successfully initialized Player 1." @@ -69,6 +70,7 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env leo run initialize_board 31u64 2207646875648u64 224u64 9042383626829824u64 aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t || exit @@ -117,6 +119,7 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env leo run play '{ @@ -152,6 +155,7 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env leo run play '{ @@ -187,6 +191,7 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env leo run play '{ @@ -222,6 +227,7 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env leo run play '{ @@ -250,4 +256,5 @@ echo " echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env diff --git a/examples/bubblesort/.env b/examples/bubblesort/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/bubblesort/.env +++ b/examples/bubblesort/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/core/.env b/examples/core/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/core/.env +++ b/examples/core/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/fibonacci/.env b/examples/fibonacci/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/fibonacci/.env +++ b/examples/fibonacci/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/groups/.env b/examples/groups/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/groups/.env +++ b/examples/groups/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzdebruijn/.env b/examples/hackers-delight/ntzdebruijn/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/hackers-delight/ntzdebruijn/.env +++ b/examples/hackers-delight/ntzdebruijn/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzgaudet/.env b/examples/hackers-delight/ntzgaudet/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/hackers-delight/ntzgaudet/.env +++ b/examples/hackers-delight/ntzgaudet/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzloops/.env b/examples/hackers-delight/ntzloops/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/hackers-delight/ntzloops/.env +++ b/examples/hackers-delight/ntzloops/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzmasks/.env b/examples/hackers-delight/ntzmasks/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/hackers-delight/ntzmasks/.env +++ b/examples/hackers-delight/ntzmasks/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzreisers/.env b/examples/hackers-delight/ntzreisers/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/hackers-delight/ntzreisers/.env +++ b/examples/hackers-delight/ntzreisers/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzseals/.env b/examples/hackers-delight/ntzseals/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/hackers-delight/ntzseals/.env +++ b/examples/hackers-delight/ntzseals/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzsearchtree/.env b/examples/hackers-delight/ntzsearchtree/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/hackers-delight/ntzsearchtree/.env +++ b/examples/hackers-delight/ntzsearchtree/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzsmallvals/.env b/examples/hackers-delight/ntzsmallvals/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/hackers-delight/ntzsmallvals/.env +++ b/examples/hackers-delight/ntzsmallvals/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/helloworld/.env b/examples/helloworld/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/helloworld/.env +++ b/examples/helloworld/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/interest/.env b/examples/interest/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/interest/.env +++ b/examples/interest/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/lottery/.env b/examples/lottery/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/lottery/.env +++ b/examples/lottery/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/message/.env b/examples/message/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/message/.env +++ b/examples/message/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/simple_token/.env b/examples/simple_token/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/simple_token/.env +++ b/examples/simple_token/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/tictactoe/.env b/examples/tictactoe/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/tictactoe/.env +++ b/examples/tictactoe/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/token/.env b/examples/token/.env index 391701926c..f5b42ea894 100644 --- a/examples/token/.env +++ b/examples/token/.env @@ -1,4 +1,4 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH - +ENDPOINT=https://localhost:3030 diff --git a/examples/token/run.sh b/examples/token/run.sh index 1b212bf0fa..69b9f81993 100755 --- a/examples/token/run.sh +++ b/examples/token/run.sh @@ -20,6 +20,7 @@ fi echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Publicly mint 100 tokens for Alice. @@ -54,6 +55,7 @@ leo run mint_public aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Privately mint 100 tokens for Bob. @@ -88,6 +90,7 @@ leo run mint_private aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Publicly transfer 10 tokens from Alice to Bob. @@ -122,6 +125,7 @@ leo run transfer_public aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5p echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Privately transfer 20 tokens from Bob to Alice. @@ -160,6 +164,7 @@ leo run transfer_private "{ echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env # Convert 30 public tokens from Alice into 30 private tokens for Bob. @@ -195,6 +200,7 @@ leo run transfer_public_to_private aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0x echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Convert 40 private tokens from Bob into 40 public tokens for Alice. @@ -236,4 +242,5 @@ leo run transfer_private_to_public "{ echo " NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env diff --git a/examples/twoadicity/.env b/examples/twoadicity/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/twoadicity/.env +++ b/examples/twoadicity/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/vote/.env b/examples/vote/.env index c7836c7232..ab80b96bf5 100644 --- a/examples/vote/.env +++ b/examples/vote/.env @@ -1,2 +1,3 @@ NETWORK=mainnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/leo/cli/cli.rs b/leo/cli/cli.rs index 67b009bb21..0679349e0c 100644 --- a/leo/cli/cli.rs +++ b/leo/cli/cli.rs @@ -315,6 +315,7 @@ mod test_helpers { use std::path::Path; const NETWORK: &str = "mainnet"; + const ENDPOINT: &str = "https://api.explorer.aleo.org/v1"; pub(crate) fn sample_nested_package(temp_dir: &Path) { let name = "nested"; @@ -329,7 +330,9 @@ mod test_helpers { let new = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: name.to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { name: name.to_string(), network: NETWORK.to_string(), endpoint: ENDPOINT.to_string() }, + }, path: Some(project_directory.clone()), home: None, }; @@ -430,7 +433,13 @@ function external_nested_function: let create_grandparent_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "grandparent".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "grandparent".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(grandparent_directory.clone()), home: None, }; @@ -438,7 +447,13 @@ function external_nested_function: let create_parent_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "parent".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "parent".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(parent_directory.clone()), home: None, }; @@ -446,7 +461,13 @@ function external_nested_function: let create_child_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "child".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "child".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(child_directory.clone()), home: None, }; @@ -561,7 +582,13 @@ program child.aleo { let create_outer_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "outer".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "outer".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(outer_directory.clone()), home: None, }; @@ -569,7 +596,13 @@ program child.aleo { let create_inner_1_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "inner_1".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "inner_1".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(inner_1_directory.clone()), home: None, }; @@ -577,7 +610,13 @@ program child.aleo { let create_inner_2_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "inner_2".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "inner_2".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(inner_2_directory.clone()), home: None, }; @@ -699,7 +738,13 @@ program outer.aleo { let create_outer_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "outer_2".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "outer_2".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(outer_directory.clone()), home: None, }; @@ -707,7 +752,13 @@ program outer.aleo { let create_inner_1_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "inner_1".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "inner_1".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(inner_1_directory.clone()), home: None, }; @@ -715,7 +766,13 @@ program outer.aleo { let create_inner_2_project = CLI { debug: false, quiet: false, - command: Commands::New { command: New { name: "inner_2".to_string(), network: NETWORK.to_string() } }, + command: Commands::New { + command: New { + name: "inner_2".to_string(), + network: NETWORK.to_string(), + endpoint: ENDPOINT.to_string(), + }, + }, path: Some(inner_2_directory.clone()), home: None, }; diff --git a/leo/cli/commands/account.rs b/leo/cli/commands/account.rs index 8951519c07..e9a36159c7 100644 --- a/leo/cli/commands/account.rs +++ b/leo/cli/commands/account.rs @@ -26,7 +26,7 @@ use crossterm::ExecutableCommand; use leo_retriever::NetworkName; use rand::SeedableRng; use rand_chacha::ChaChaRng; -use snarkvm::prelude::{MainnetV0, Network, TestnetV0}; +use snarkvm::prelude::{CanaryV0, MainnetV0, Network, TestnetV0}; use std::{ io::{self, Read, Write}, path::PathBuf, @@ -49,6 +49,13 @@ pub enum Account { discreet: bool, #[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")] network: String, + #[clap( + short = 'e', + long, + help = "Endpoint to retrieve network state from.", + default_value = "https://api.explorer.aleo.org/v1" + )] + endpoint: String, }, /// Derive an Aleo account from a private key. Import { @@ -62,6 +69,13 @@ pub enum Account { discreet: bool, #[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")] network: String, + #[clap( + short = 'e', + long, + help = "Endpoint to retrieve network state from.", + default_value = "https://api.explorer.aleo.org/v1" + )] + endpoint: String, }, /// Sign a message using your Aleo private key. Sign { @@ -118,20 +132,22 @@ impl Command for Account { Self: Sized, { match self { - Account::New { seed, write, discreet, network } => { + Account::New { seed, write, discreet, network, endpoint } => { // Parse the network. let network = NetworkName::try_from(network.as_str())?; match network { - NetworkName::MainnetV0 => generate_new_account::(seed, write, discreet, &ctx), - NetworkName::TestnetV0 => generate_new_account::(seed, write, discreet, &ctx), + NetworkName::MainnetV0 => generate_new_account::(seed, write, discreet, &ctx, endpoint), + NetworkName::TestnetV0 => generate_new_account::(seed, write, discreet, &ctx, endpoint), + NetworkName::CanaryV0 => generate_new_account::(seed, write, discreet, &ctx, endpoint), }? } - Account::Import { private_key, write, discreet, network } => { + Account::Import { private_key, write, discreet, network, endpoint } => { // Parse the network. let network = NetworkName::try_from(network.as_str())?; match network { - NetworkName::MainnetV0 => import_account::(private_key, write, discreet, &ctx), - NetworkName::TestnetV0 => import_account::(private_key, write, discreet, &ctx), + NetworkName::MainnetV0 => import_account::(private_key, write, discreet, &ctx, endpoint), + NetworkName::TestnetV0 => import_account::(private_key, write, discreet, &ctx, endpoint), + NetworkName::CanaryV0 => import_account::(private_key, write, discreet, &ctx, endpoint), }? } Self::Sign { message, seed, raw, private_key, private_key_file, network } => { @@ -144,6 +160,9 @@ impl Command for Account { NetworkName::TestnetV0 => { sign_message::(message, seed, raw, private_key, private_key_file) } + NetworkName::CanaryV0 => { + sign_message::(message, seed, raw, private_key, private_key_file) + } }?; println!("{result}") } @@ -153,6 +172,7 @@ impl Command for Account { let result = match network { NetworkName::MainnetV0 => verify_message::(address, signature, message, raw), NetworkName::TestnetV0 => verify_message::(address, signature, message, raw), + NetworkName::CanaryV0 => verify_message::(address, signature, message, raw), }?; println!("{result}") } @@ -164,7 +184,13 @@ impl Command for Account { // Helper functions // Generate a new account. -fn generate_new_account(seed: Option, write: bool, discreet: bool, ctx: &Context) -> Result<()> { +fn generate_new_account( + seed: Option, + write: bool, + discreet: bool, + ctx: &Context, + endpoint: String, +) -> Result<()> { // Sample a new Aleo account. let private_key = match seed { // Recover the field element deterministically. @@ -179,13 +205,19 @@ fn generate_new_account(seed: Option, write: bool, discreet: bo // Save key data to .env file. if write { - write_to_env_file(private_key, ctx)?; + write_to_env_file(private_key, ctx, endpoint)?; } Ok(()) } // Import an account. -fn import_account(private_key: Option, write: bool, discreet: bool, ctx: &Context) -> Result<()> { +fn import_account( + private_key: Option, + write: bool, + discreet: bool, + ctx: &Context, + endpoint: String, +) -> Result<()> { let priv_key = match discreet { true => { let private_key_input = rpassword::prompt_password("Please enter your private key: ").unwrap(); @@ -207,7 +239,7 @@ fn import_account(private_key: Option, write: bool, discreet // Save key data to .env file. if write { - write_to_env_file::(priv_key, ctx)?; + write_to_env_file::(priv_key, ctx, endpoint)?; } Ok(()) @@ -323,9 +355,9 @@ pub(crate) fn verify_message( } // Write the network and private key to the .env file in project directory. -fn write_to_env_file(private_key: PrivateKey, ctx: &Context) -> Result<()> { +fn write_to_env_file(private_key: PrivateKey, ctx: &Context, endpoint: String) -> Result<()> { let program_dir = ctx.dir()?; - Env::::from(private_key).write_to(&program_dir)?; + Env::::new(Some(private_key), endpoint)?.write_to(&program_dir)?; tracing::info!("✅ Private Key written to {}", program_dir.join(".env").display()); Ok(()) } diff --git a/leo/cli/commands/build.rs b/leo/cli/commands/build.rs index 1999df9f79..bc9816df44 100644 --- a/leo/cli/commands/build.rs +++ b/leo/cli/commands/build.rs @@ -29,6 +29,7 @@ use snarkvm::{ }; use indexmap::IndexMap; +use snarkvm::prelude::CanaryV0; use std::{ io::Write, path::{Path, PathBuf}, @@ -93,10 +94,11 @@ impl Command for Build { fn apply(self, context: Context, _: Self::Input) -> Result { // Parse the network. - let network = NetworkName::try_from(self.options.network.as_str())?; + let network = NetworkName::try_from(context.get_network(&self.options.network)?)?; match network { NetworkName::MainnetV0 => handle_build::(&self, context), NetworkName::TestnetV0 => handle_build::(&self, context), + NetworkName::CanaryV0 => handle_build::(&self, context), } } } @@ -123,8 +125,13 @@ fn handle_build(command: &Build, context: Context) -> Result<::new(main_sym, &package_path, &home_path, command.options.endpoint.clone()) - .map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?; + let mut retriever = Retriever::::new( + main_sym, + &package_path, + &home_path, + context.get_endpoint(&command.options.endpoint)?.to_string(), + ) + .map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?; let mut local_dependencies = retriever.retrieve().map_err(|err| UtilError::failed_to_retrieve_dependencies(err, Default::default()))?; diff --git a/leo/cli/commands/deploy.rs b/leo/cli/commands/deploy.rs index 40d7399f0c..08cd8897c5 100644 --- a/leo/cli/commands/deploy.rs +++ b/leo/cli/commands/deploy.rs @@ -16,23 +16,23 @@ use super::*; use aleo_std::StorageMode; +use dialoguer::{theme::ColorfulTheme, Confirm}; use leo_retriever::NetworkName; use snarkvm::{ - circuit::{Aleo, AleoTestnetV0, AleoV0}, - cli::helpers::dotenv_private_key, + circuit::{Aleo, AleoCanaryV0, AleoTestnetV0, AleoV0}, ledger::query::Query as SnarkVMQuery, package::Package as SnarkVMPackage, prelude::{ deployment_cost, store::{helpers::memory::ConsensusMemory, ConsensusStore}, + CanaryV0, MainnetV0, - PrivateKey, ProgramOwner, TestnetV0, VM, }, }; -use std::{path::PathBuf, str::FromStr}; +use std::path::PathBuf; use text_tables; /// Deploys an Aleo program. @@ -71,10 +71,12 @@ impl Command for Deploy { fn apply(self, context: Context, _: Self::Input) -> Result { // Parse the network. - let network = NetworkName::try_from(self.options.network.as_str())?; + let network = NetworkName::try_from(context.get_network(&self.options.network)?)?; + let endpoint = context.get_endpoint(&self.options.endpoint)?; match network { - NetworkName::MainnetV0 => handle_deploy::(&self, context), - NetworkName::TestnetV0 => handle_deploy::(&self, context), + NetworkName::MainnetV0 => handle_deploy::(&self, context, network, &endpoint), + NetworkName::TestnetV0 => handle_deploy::(&self, context, network, &endpoint), + NetworkName::CanaryV0 => handle_deploy::(&self, context, network, &endpoint), } } } @@ -83,20 +85,18 @@ impl Command for Deploy { fn handle_deploy, N: Network>( command: &Deploy, context: Context, + network: NetworkName, + endpoint: &str, ) -> Result<::Output> { // Get the program name. let project_name = context.open_manifest::()?.program_id().to_string(); // Get the private key. - let private_key = match &command.fee_options.private_key { - Some(key) => PrivateKey::from_str(key)?, - None => PrivateKey::from_str( - &dotenv_private_key().map_err(CliError::failed_to_read_environment_private_key)?.to_string(), - )?, - }; + let private_key = context.get_private_key(&command.fee_options.private_key)?; + let address = Address::try_from(&private_key)?; // Specify the query - let query = SnarkVMQuery::from(&command.options.endpoint); + let query = SnarkVMQuery::from(endpoint); let mut all_paths: Vec<(String, PathBuf)> = Vec::new(); @@ -120,6 +120,15 @@ fn handle_deploy, N: Network>( // Generate the deployment let deployment = package.deploy::(None)?; + + // Check if the number of variables and constraints are within the limits. + if deployment.num_combined_variables()? > N::MAX_DEPLOYMENT_VARIABLES { + return Err(CliError::variable_limit_exceeded(name, N::MAX_DEPLOYMENT_VARIABLES, network).into()); + } + if deployment.num_combined_constraints()? > N::MAX_DEPLOYMENT_CONSTRAINTS { + return Err(CliError::constraint_limit_exceeded(name, N::MAX_DEPLOYMENT_CONSTRAINTS, network).into()); + } + let deployment_id = deployment.to_deployment_id()?; let store = ConsensusStore::>::open(StorageMode::Production)?; @@ -139,7 +148,7 @@ fn handle_deploy, N: Network>( synthesis_cost as f64 / 1_000_000.0, namespace_cost as f64 / 1_000_000.0, command.fee_options.priority_fee as f64 / 1_000_000.0, - ); + )?; // Initialize an RNG. let rng = &mut rand::thread_rng(); @@ -160,13 +169,7 @@ fn handle_deploy, N: Network>( } None => { // Make sure the user has enough public balance to pay for the deployment. - check_balance( - &private_key, - &command.options.endpoint, - &command.options.network, - context.clone(), - total_cost, - )?; + check_balance(&private_key, endpoint, &network.to_string(), context.clone(), total_cost)?; let fee_authorization = vm.authorize_fee_public( &private_key, total_cost, @@ -185,18 +188,32 @@ fn handle_deploy, N: Network>( // Determine if the transaction should be broadcast, stored, or displayed to the user. if !command.fee_options.dry_run { - println!("✅ Created deployment transaction for '{}'", name.bold()); - handle_broadcast( - &format!("{}/{}/transaction/broadcast", command.options.endpoint, command.options.network), - transaction, - name, - )?; + if !command.fee_options.yes { + let prompt = format!( + "Do you want to submit deployment of program `{name}.aleo` to network {} via endpoint {} using address {}?", + network, endpoint, address + ); + let confirmation = + Confirm::with_theme(&ColorfulTheme::default()).with_prompt(prompt).default(false).interact(); + + // Check if the user confirmed the transaction. + if let Ok(confirmation) = confirmation { + if !confirmation { + println!("✅ Successfully aborted the execution transaction for '{}'\n", name.bold()); + return Ok(()); + } + } else { + return Err(CliError::confirmation_failed().into()); + } + } + println!("✅ Created deployment transaction for '{}'\n", name.bold()); + handle_broadcast(&format!("{}/{}/transaction/broadcast", endpoint, network), transaction, name)?; // Wait between successive deployments to prevent out of order deployments. if index < all_paths.len() - 1 { std::thread::sleep(std::time::Duration::from_secs(command.wait)); } } else { - println!("✅ Successful dry run deployment for '{}'", name.bold()); + println!("✅ Successful dry run deployment for '{}'\n", name.bold()); } } @@ -211,8 +228,8 @@ fn deploy_cost_breakdown( synthesis_cost: f64, namespace_cost: f64, priority_fee: f64, -) { - println!("Base deployment cost for '{}' is {} credits.", name.bold(), total_cost); +) -> Result<()> { + println!("\nBase deployment cost for '{}' is {} credits.\n", name.bold(), total_cost); // Display the cost breakdown in a table. let data = [ [name, "Cost (credits)"], @@ -223,6 +240,7 @@ fn deploy_cost_breakdown( ["Total", &format!("{:.6}", total_cost)], ]; let mut out = Vec::new(); - text_tables::render(&mut out, data).unwrap(); - println!("{}", ::std::str::from_utf8(&out).unwrap()); + text_tables::render(&mut out, data).map_err(CliError::table_render_failed)?; + println!("{}", ::std::str::from_utf8(&out).map_err(CliError::table_render_failed)?); + Ok(()) } diff --git a/leo/cli/commands/example.rs b/leo/cli/commands/example.rs index 3c759fe077..44863c4c98 100644 --- a/leo/cli/commands/example.rs +++ b/leo/cli/commands/example.rs @@ -25,6 +25,13 @@ pub struct Example { pub(crate) name: String, #[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")] pub(crate) network: String, + #[clap( + short = 'e', + long, + help = "Endpoint to retrieve network state from.", + default_value = "https://api.explorer.aleo.org/v1" + )] + pub(crate) endpoint: String, } impl Command for Example { @@ -33,7 +40,8 @@ impl Command for Example { fn prelude(&self, context: Context) -> Result { // Run leo new --network - (New { name: self.name.clone(), network: self.network.clone() }).execute(context) + (New { name: self.name.clone(), network: self.network.clone(), endpoint: self.endpoint.clone() }) + .execute(context) } fn apply(self, context: Context, _: Self::Input) -> Result diff --git a/leo/cli/commands/execute.rs b/leo/cli/commands/execute.rs index acbe198716..cee8dc6e84 100644 --- a/leo/cli/commands/execute.rs +++ b/leo/cli/commands/execute.rs @@ -24,9 +24,10 @@ use snarkvm::{ use std::collections::HashMap; use crate::cli::query::QueryCommands; +use dialoguer::{theme::ColorfulTheme, Confirm}; use leo_retriever::NetworkName; use snarkvm::{ - circuit::{Aleo, AleoTestnetV0, AleoV0}, + circuit::{Aleo, AleoCanaryV0, AleoTestnetV0, AleoV0}, cli::LOCALE, ledger::Transaction::Execute as ExecuteTransaction, package::Package as SnarkVMPackage, @@ -66,6 +67,8 @@ pub struct Execute { compiler_options: BuildOptions, #[arg(short, long, help = "The inputs to the program, from a file. Overrides the INPUTS argument.")] file: Option, + #[clap(long, help = "Disables building of the project before execution.", default_value = "false")] + pub(crate) no_build: bool, } impl Command for Execute { @@ -78,7 +81,7 @@ impl Command for Execute { fn prelude(&self, context: Context) -> Result { // No need to build if we are executing an external program. - if self.program.is_some() { + if self.program.is_some() || self.no_build { return Ok(()); } (Build { options: self.compiler_options.clone() }).execute(context) @@ -86,16 +89,23 @@ impl Command for Execute { fn apply(self, context: Context, _input: Self::Input) -> Result { // Parse the network. - let network = NetworkName::try_from(self.compiler_options.network.as_str())?; + let network = NetworkName::try_from(context.get_network(&self.compiler_options.network)?)?; + let endpoint = context.get_endpoint(&self.compiler_options.endpoint)?; match network { - NetworkName::MainnetV0 => handle_execute::(self, context), - NetworkName::TestnetV0 => handle_execute::(self, context), + NetworkName::MainnetV0 => handle_execute::(self, context, network, &endpoint), + NetworkName::TestnetV0 => handle_execute::(self, context, network, &endpoint), + NetworkName::CanaryV0 => handle_execute::(self, context, network, &endpoint), } } } // A helper function to handle the `execute` command. -fn handle_execute(command: Execute, context: Context) -> Result<::Output> { +fn handle_execute( + command: Execute, + context: Context, + network: NetworkName, + endpoint: &str, +) -> Result<::Output> { // If input values are provided, then run the program with those inputs. // Otherwise, use the input file. let mut inputs = command.inputs.clone(); @@ -133,13 +143,14 @@ fn handle_execute(command: Execute, context: Context) -> Result< { - let local = context.open_manifest::()?.program_id().to_string(); + let local = context.open_manifest::()?.program_id().name().to_string(); // Throw error if local name doesn't match the specified name. if name == local { local @@ -148,13 +159,12 @@ fn handle_execute(command: Execute, context: Context) -> Result< name.clone(), - (None, true) => context.open_manifest::()?.program_id().to_string(), + (None, true) => context.open_manifest::()?.program_id().name().to_string(), (None, false) => return Err(PackageError::missing_on_chain_program_name().into()), }; // Specify the query - let query = - SnarkVMQuery::>::from(command.compiler_options.endpoint.clone()); + let query = SnarkVMQuery::>::from(endpoint); // Initialize the storage. let store = ConsensusStore::>::open(StorageMode::Production)?; @@ -164,8 +174,7 @@ fn handle_execute(command: Execute, context: Context) -> Result<::from_str(&format!("{}.aleo", program_name))?; - // TODO: X - load_program_from_network(&command, context.clone(), &mut vm.process().write(), program_id)?; + load_program_from_network(context.clone(), &mut vm.process().write(), program_id, network, endpoint)?; let fee_record = if let Some(record) = command.fee_options.record { Some(parse_record(&private_key, &record)?) @@ -176,7 +185,7 @@ fn handle_execute(command: Execute, context: Context) -> Result<(command: Execute, context: Context) -> Result<( - &private_key, - &command.compiler_options.endpoint, - &command.compiler_options.network, - context, - total_cost, - )?; + check_balance::(&private_key, endpoint, &network.to_string(), context, total_cost)?; } // Broadcast the execution transaction. if !command.fee_options.dry_run { - println!("✅ Created execution transaction for '{}'", program_id.to_string().bold()); - handle_broadcast( - &format!( - "{}/{}/transaction/broadcast", - command.compiler_options.endpoint, command.compiler_options.network - ), - transaction, - &program_name, - )?; + if !command.fee_options.yes { + let prompt = format!( + "Do you want to submit execution of function `{}` on program `{program_name}.aleo` to network {} via endpoint {} using address {}?", + &command.name, network, endpoint, address + ); + // Ask the user for confirmation of the transaction. + let confirmation = + Confirm::with_theme(&ColorfulTheme::default()).with_prompt(prompt).default(false).interact(); + + // Check if the user confirmed the transaction. + if let Ok(confirmation) = confirmation { + if !confirmation { + println!("✅ Successfully aborted the execution transaction for '{}'\n", program_name.bold()); + return Ok(()); + } + } else { + return Err(CliError::confirmation_failed().into()); + } + } + println!("✅ Created execution transaction for '{}'\n", program_id.to_string().bold()); + handle_broadcast(&format!("{}/{}/transaction/broadcast", endpoint, network), transaction, &program_name)?; } else { - println!("✅ Successful dry run execution for '{}'", program_id.to_string().bold()); + println!("✅ Successful dry run execution for '{}'\n", program_id.to_string().bold()); } return Ok(()); @@ -241,14 +256,18 @@ fn handle_execute(command: Execute, context: Context) -> Result<>>(); + let mut parsed_inputs: Vec> = Vec::new(); + for input in inputs.iter() { + let value = Value::from_str(input)?; + parsed_inputs.push(value); + } // Execute the request. let (response, execution, metrics) = package .execute::( - command.compiler_options.endpoint.clone(), + endpoint.to_string(), &private_key, Identifier::try_from(command.name.clone())?, - &inputs, + &parsed_inputs, rng, ) .map_err(PackageError::execution_error)?; @@ -318,25 +337,22 @@ fn handle_execute(command: Execute, context: Context) -> Result<( - command: &Execute, context: Context, process: &mut Process, program_id: &ProgramID, + network: NetworkName, + endpoint: &str, ) -> Result<()> { // Fetch the program. let program_src = Query { - endpoint: command.compiler_options.endpoint.clone(), - network: command.compiler_options.network.clone(), + endpoint: Some(endpoint.to_string()), + network: Some(network.to_string()), command: QueryCommands::Program { - command: crate::cli::commands::query::Program { - name: program_id.to_string(), - mappings: false, - mapping_value: None, - }, + command: query::Program { name: program_id.to_string(), mappings: false, mapping_value: None }, }, } .execute(Context::new(context.path.clone(), context.home.clone(), true)?)?; - let program = SnarkVMProgram::::from_str(&program_src).unwrap(); + let program = SnarkVMProgram::::from_str(&program_src)?; // Return early if the program is already loaded. if process.contains_program(program.id()) { @@ -348,7 +364,7 @@ fn load_program_from_network( // Add the imports to the process if does not exist yet. if !process.contains_program(import_program_id) { // Recursively load the program and its imports. - load_program_from_network(command, context.clone(), process, import_program_id)?; + load_program_from_network(context.clone(), process, import_program_id, network, endpoint)?; } } @@ -361,8 +377,14 @@ fn load_program_from_network( } // A helper function to display a cost breakdown of the execution. -fn execution_cost_breakdown(name: &String, total_cost: f64, storage_cost: f64, finalize_cost: f64, priority_fee: f64) { - println!("Base execution cost for '{}' is {} credits.", name.bold(), total_cost); +fn execution_cost_breakdown( + name: &String, + total_cost: f64, + storage_cost: f64, + finalize_cost: f64, + priority_fee: f64, +) -> Result<()> { + println!("\nBase execution cost for '{}' is {} credits.\n", name.bold(), total_cost); // Display the cost breakdown in a table. let data = [ [name, "Cost (credits)"], @@ -372,6 +394,7 @@ fn execution_cost_breakdown(name: &String, total_cost: f64, storage_cost: f64, f ["Total", &format!("{:.6}", total_cost)], ]; let mut out = Vec::new(); - text_tables::render(&mut out, data).unwrap(); - println!("{}", ::std::str::from_utf8(&out).unwrap()); + text_tables::render(&mut out, data).map_err(CliError::table_render_failed)?; + println!("{}", std::str::from_utf8(&out).map_err(CliError::table_render_failed)?); + Ok(()) } diff --git a/leo/cli/commands/mod.rs b/leo/cli/commands/mod.rs index 99fd2a46d0..024e1ade26 100644 --- a/leo/cli/commands/mod.rs +++ b/leo/cli/commands/mod.rs @@ -133,14 +133,10 @@ pub trait Command { /// require Build command output as their input. #[derive(Parser, Clone, Debug)] pub struct BuildOptions { - #[clap( - long, - help = "Endpoint to retrieve network state from.", - default_value = "https://api.explorer.aleo.org/v1" - )] - pub endpoint: String, - #[clap(long, help = "Network to broadcast to. Defaults to mainnet.", default_value = "mainnet")] - pub(crate) network: String, + #[clap(long, help = "Endpoint to retrieve network state from. Overrides setting in `.env`.")] + pub endpoint: Option, + #[clap(long, help = "Network to broadcast to. Overrides setting in `.env`.")] + pub(crate) network: Option, #[clap(long, help = "Does not recursively compile dependencies.")] pub non_recursive: bool, #[clap(long, help = "Enables offline mode.")] @@ -182,8 +178,8 @@ pub struct BuildOptions { impl Default for BuildOptions { fn default() -> Self { Self { - endpoint: "http://api.explorer.aleo.org/v1".to_string(), - network: "mainnet".to_string(), + endpoint: None, + network: None, non_recursive: false, offline: false, enable_symbol_table_spans: false, @@ -210,6 +206,8 @@ impl Default for BuildOptions { /// Used by Execute and Deploy commands. #[derive(Parser, Clone, Debug, Default)] pub struct FeeOptions { + #[clap(short, long, help = "Don't ask for confirmation.", default_value = "false")] + pub(crate) yes: bool, #[clap(short, long, help = "Performs a dry-run of transaction generation")] pub(crate) dry_run: bool, #[clap(long, help = "Priority fee in microcredits. Defaults to 0.", default_value = "0")] @@ -250,8 +248,8 @@ fn check_balance( let address = Address::::try_from(ViewKey::try_from(private_key)?)?; // Query the public balance of the address on the `account` mapping from `credits.aleo`. let mut public_balance = Query { - endpoint: endpoint.to_string(), - network: network.to_string(), + endpoint: Some(endpoint.to_string()), + network: Some(network.to_string()), command: QueryCommands::Program { command: crate::cli::commands::query::Program { name: "credits".to_string(), @@ -263,17 +261,24 @@ fn check_balance( .execute(Context::new(context.path.clone(), context.home.clone(), true)?)?; // Remove the last 3 characters since they represent the `u64` suffix. public_balance.truncate(public_balance.len() - 3); + // Make sure the balance is valid. + let balance = if let Ok(credits) = public_balance.parse::() { + credits + } else { + return Err(CliError::invalid_balance(address).into()); + }; // Compare balance. - if public_balance.parse::().unwrap() < total_cost { + if balance < total_cost { Err(PackageError::insufficient_balance(address, public_balance, total_cost).into()) } else { + println!("Your current public balance is {} credits.\n", balance as f64 / 1_000_000.0); Ok(()) } } /// Determine if the transaction should be broadcast or displayed to user. fn handle_broadcast(endpoint: &String, transaction: Transaction, operation: &String) -> Result<()> { - println!("Broadcasting transaction to {}...", endpoint.clone()); + println!("Broadcasting transaction to {}...\n", endpoint.clone()); // Get the transaction id. let transaction_id = transaction.id(); @@ -287,20 +292,20 @@ fn handle_broadcast(endpoint: &String, transaction: Transaction, match transaction { Transaction::Deploy(..) => { println!( - "⌛ Deployment {transaction_id} ('{}') has been broadcast to {}.", + "⌛ Deployment {transaction_id} ('{}') has been broadcast to {}.\n", operation.bold(), endpoint ) } Transaction::Execute(..) => { println!( - "⌛ Execution {transaction_id} ('{}') has been broadcast to {}.", + "⌛ Execution {transaction_id} ('{}') has been broadcast to {}.\n", operation.bold(), endpoint ) } Transaction::Fee(..) => { - println!("❌ Failed to broadcast fee '{}' to the {}.", operation.bold(), endpoint) + println!("❌ Failed to broadcast fee '{}' to the {}.\n", operation.bold(), endpoint) } } Ok(()) diff --git a/leo/cli/commands/new.rs b/leo/cli/commands/new.rs index 6b494bc2c4..df5fe53062 100644 --- a/leo/cli/commands/new.rs +++ b/leo/cli/commands/new.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use super::*; -use snarkvm::prelude::{MainnetV0, TestnetV0}; +use snarkvm::prelude::{CanaryV0, MainnetV0, TestnetV0}; use leo_retriever::NetworkName; @@ -26,6 +26,13 @@ pub struct New { pub(crate) name: String, #[clap(short = 'n', long, help = "Name of the network to use", default_value = "mainnet")] pub(crate) network: String, + #[clap( + short = 'e', + long, + help = "Endpoint to retrieve network state from.", + default_value = "https://api.explorer.aleo.org/v1" + )] + pub(crate) endpoint: String, } impl Command for New { @@ -53,8 +60,9 @@ impl Command for New { // Initialize the package. match network { - NetworkName::MainnetV0 => Package::initialize::(&self.name, &package_path), - NetworkName::TestnetV0 => Package::initialize::(&self.name, &package_path), + NetworkName::MainnetV0 => Package::initialize::(&self.name, &package_path, self.endpoint), + NetworkName::TestnetV0 => Package::initialize::(&self.name, &package_path, self.endpoint), + NetworkName::CanaryV0 => Package::initialize::(&self.name, &package_path, self.endpoint), }?; Ok(()) diff --git a/leo/cli/commands/query/block.rs b/leo/cli/commands/query/block.rs index 84ef81f9e8..def8386fb8 100644 --- a/leo/cli/commands/query/block.rs +++ b/leo/cli/commands/query/block.rs @@ -69,8 +69,11 @@ impl Command for Block { is_valid_numerical_input(&range[0])?; is_valid_numerical_input(&range[1])?; + // Parse the range values. + let end = &range[1].parse::().map_err(|_| UtilError::invalid_bound(&range[1]))?; + let start = &range[0].parse::().map_err(|_| UtilError::invalid_bound(&range[0]))?; // Make sure the range is not too large. - if range[1].parse::().unwrap() - range[0].parse::().unwrap() > 50 { + if end - start > 50 { return Err(UtilError::invalid_range().into()); } format!("blocks?start={}&end={}", range[0], range[1]) diff --git a/leo/cli/commands/query/mod.rs b/leo/cli/commands/query/mod.rs index b50ac2e88e..591f935d32 100644 --- a/leo/cli/commands/query/mod.rs +++ b/leo/cli/commands/query/mod.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use super::*; -use snarkvm::prelude::{MainnetV0, TestnetV0}; +use snarkvm::prelude::{CanaryV0, MainnetV0, TestnetV0}; mod block; use block::Block; @@ -47,16 +47,10 @@ use leo_retriever::{fetch_from_network, verify_valid_program, NetworkName}; /// Query live data from the Aleo network. #[derive(Parser, Debug)] pub struct Query { - #[clap( - short, - long, - global = true, - help = "Endpoint to retrieve network state from. Defaults to https://api.explorer.aleo.org/v1.", - default_value = "https://api.explorer.aleo.org/v1" - )] - pub endpoint: String, - #[clap(short, long, global = true, help = "Network to use. Defaults to mainnet.", default_value = "mainnet")] - pub(crate) network: String, + #[clap(short, long, global = true, help = "Endpoint to retrieve network state from. Defaults to entry in `.env`.")] + pub endpoint: Option, + #[clap(short, long, global = true, help = "Network to use. Defaults to entry in `.env`.")] + pub(crate) network: Option, #[clap(subcommand)] pub command: QueryCommands, } @@ -75,16 +69,23 @@ impl Command for Query { fn apply(self, context: Context, _: Self::Input) -> Result { // Parse the network. - let network = NetworkName::try_from(self.network.as_str())?; + let network = NetworkName::try_from(context.get_network(&self.network)?)?; + let endpoint = context.get_endpoint(&self.endpoint)?; match network { - NetworkName::MainnetV0 => handle_query::(self, context), - NetworkName::TestnetV0 => handle_query::(self, context), + NetworkName::MainnetV0 => handle_query::(self, context, &network.to_string(), &endpoint), + NetworkName::TestnetV0 => handle_query::(self, context, &network.to_string(), &endpoint), + NetworkName::CanaryV0 => handle_query::(self, context, &network.to_string(), &endpoint), } } } // A helper function to handle the `query` command. -fn handle_query(query: Query, context: Context) -> Result<::Output> { +fn handle_query( + query: Query, + context: Context, + network: &str, + endpoint: &str, +) -> Result<::Output> { let recursive = context.recursive; let (program, output) = match query.command { QueryCommands::Block { command } => (None, command.apply(context, ())?), @@ -98,7 +99,7 @@ fn handle_query(query: Query, context: Context) -> Result< (None, command.apply(context, ())?), QueryCommands::Committee { command } => (None, command.apply(context, ())?), QueryCommands::Mempool { command } => { - if query.endpoint == "https://api.explorer.aleo.org/v1" { + if endpoint == "https://api.explorer.aleo.org/v1" { tracing::warn!( "⚠️ `leo query mempool` is only valid when using a custom endpoint. Specify one using `--endpoint`." ); @@ -106,7 +107,7 @@ fn handle_query(query: Query, context: Context) -> Result< { - if query.endpoint == "https://api.explorer.aleo.org/v1" { + if endpoint == "https://api.explorer.aleo.org/v1" { tracing::warn!( "⚠️ `leo query peers` is only valid when using a custom endpoint. Specify one using `--endpoint`." ); @@ -116,7 +117,7 @@ fn handle_query(query: Query, context: Context) -> Result< Result { // Parse the network. - let network = NetworkName::try_from(self.compiler_options.network.as_str())?; + let network = NetworkName::try_from(context.get_network(&self.compiler_options.network)?)?; match network { NetworkName::MainnetV0 => handle_run::(self, context), NetworkName::TestnetV0 => handle_run::(self, context), + NetworkName::CanaryV0 => handle_run::(self, context), } } } diff --git a/leo/cli/helpers/context.rs b/leo/cli/helpers/context.rs index ca1cbdde3e..38309ce04e 100644 --- a/leo/cli/helpers/context.rs +++ b/leo/cli/helpers/context.rs @@ -23,12 +23,13 @@ use snarkvm::file::Manifest; use aleo_std::aleo_dir; use indexmap::IndexMap; -use snarkvm::prelude::Network; +use snarkvm::prelude::{Network, PrivateKey}; use std::{ env::current_dir, fs::File, io::Write, path::{Path, PathBuf}, + str::FromStr, }; /// Project context, manifest, current directory etc @@ -140,4 +141,54 @@ impl Context { Ok(list) } + + /// Returns the private key from the .env file specified in the directory. + pub fn dotenv_private_key(&self) -> Result> { + dotenvy::from_path(self.dir()?.join(".env")).map_err(|_| CliError::failed_to_get_private_key_from_env())?; + // Load the private key from the environment. + let private_key = dotenvy::var("PRIVATE_KEY").map_err(|_| CliError::failed_to_get_private_key_from_env())?; + // Parse the private key. + Ok(PrivateKey::::from_str(&private_key)?) + } + + /// Returns the endpoint from the .env file specified in the directory. + pub fn dotenv_endpoint(&self) -> Result { + dotenvy::from_path(self.dir()?.join(".env")).map_err(|_| CliError::failed_to_get_endpoint_from_env())?; + // Load the endpoint from the environment. + Ok(dotenvy::var("ENDPOINT").map_err(|_| CliError::failed_to_get_endpoint_from_env())?) + } + + /// Returns the network from the .env file specified in the directory. + pub fn dotenv_network(&self) -> Result { + dotenvy::from_path(self.dir()?.join(".env")).map_err(|_| CliError::failed_to_get_network_from_env())?; + // Load the network from the environment. + Ok(dotenvy::var("NETWORK").map_err(|_| CliError::failed_to_get_network_from_env())?) + } + + /// Returns the endpoint to interact with the network. + /// If the `--endpoint` options is not provided, it will default to the one in the `.env` file. + pub fn get_endpoint(&self, endpoint: &Option) -> Result { + match endpoint { + Some(endpoint) => Ok(endpoint.clone()), + None => Ok(self.dotenv_endpoint()?), + } + } + + /// Returns the network name. + /// If the `--network` options is not provided, it will default to the one in the `.env` file. + pub fn get_network(&self, network: &Option) -> Result { + match network { + Some(network) => Ok(network.clone()), + None => Ok(self.dotenv_network()?), + } + } + + /// Returns the private key. + /// If the `--private-key` options is not provided, it will default to the one in the `.env` file. + pub fn get_private_key(&self, private_key: &Option) -> Result> { + match private_key { + Some(private_key) => Ok(PrivateKey::::from_str(private_key)?), + None => self.dotenv_private_key(), + } + } } diff --git a/leo/package/Cargo.toml b/leo/package/Cargo.toml index ed2c7a6299..340ac49352 100644 --- a/leo/package/Cargo.toml +++ b/leo/package/Cargo.toml @@ -37,6 +37,9 @@ default-features = false version = "1.9" features = [ "serde" ] +[dependencies.dialoguer] +version = "0.11.0" + [dependencies.num-format] version = "0.4.4" diff --git a/leo/package/src/package.rs b/leo/package/src/package.rs index abc6aad9d5..ed4804acf5 100644 --- a/leo/package/src/package.rs +++ b/leo/package/src/package.rs @@ -22,8 +22,8 @@ use leo_errors::{PackageError, Result}; use leo_retriever::{Manifest, NetworkName}; use serde::Deserialize; -use snarkvm::prelude::Network; -use std::path::Path; +use snarkvm::prelude::{Network, PrivateKey}; +use std::{path::Path, str::FromStr}; #[derive(Deserialize)] pub struct Package { @@ -125,7 +125,7 @@ impl Package { } /// Creates a Leo package at the given path - pub fn initialize(package_name: &str, path: &Path) -> Result<()> { + pub fn initialize(package_name: &str, path: &Path, endpoint: String) -> Result<()> { // Construct the path to the package directory. let path = path.join(package_name); @@ -147,7 +147,12 @@ impl Package { Gitignore::new().write_to(&path)?; // Create the .env file. - Env::::new()?.write_to(&path)?; + // Include the private key of validator 0 for ease of use with local devnets, as it will automatically be seeded with funds. + Env::::new( + Some(PrivateKey::::from_str("APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH")?), + endpoint, + )? + .write_to(&path)?; // Create a manifest. let manifest = Manifest::default(package_name); diff --git a/leo/package/src/root/env.rs b/leo/package/src/root/env.rs index f909d6270d..91201e0619 100644 --- a/leo/package/src/root/env.rs +++ b/leo/package/src/root/env.rs @@ -30,17 +30,21 @@ pub static ENV_FILENAME: &str = ".env"; pub struct Env { #[serde(bound(deserialize = ""))] private_key: PrivateKey, + endpoint: String, } impl Env { - pub fn new() -> Result { + pub fn new(private_key: Option>, endpoint: String) -> Result { // Initialize an RNG. let rng = &mut rand::thread_rng(); // Generate a development private key. - let private_key = PrivateKey::::new(rng)?; + let private_key = match private_key { + Some(private_key) => private_key, + None => PrivateKey::::new(rng)?, + }; - Ok(Self { private_key }) + Ok(Self { private_key, endpoint }) } pub fn exists_at(path: &Path) -> bool { @@ -63,12 +67,6 @@ impl Env { } } -impl From> for Env { - fn from(private_key: PrivateKey) -> Self { - Self { private_key } - } -} - impl ToString for Env { fn to_string(&self) -> String { // Get the network name. @@ -78,6 +76,6 @@ impl ToString for Env { _ => unimplemented!("Unsupported network"), }; // Return the formatted string. - format!("NETWORK={network}\nPRIVATE_KEY={}\n", self.private_key) + format!("NETWORK={network}\nPRIVATE_KEY={}\nENDPOINT={}\n", self.private_key, self.endpoint) } } diff --git a/utils/retriever/src/program_context/manifest.rs b/utils/retriever/src/program_context/manifest.rs index 076959371b..eef1c22120 100644 --- a/utils/retriever/src/program_context/manifest.rs +++ b/utils/retriever/src/program_context/manifest.rs @@ -87,7 +87,7 @@ impl Manifest { pub fn read_from_dir(path: &Path) -> Result { // Read the manifest file. let contents = std::fs::read_to_string(path.join("program.json")) - .map_err(|err| PackageError::failed_to_read_file(path.to_str().unwrap(), err))?; + .map_err(|_| PackageError::failed_to_load_package(path.to_str().unwrap()))?; // Deserialize the manifest. serde_json::from_str(&contents) .map_err(|err| PackageError::failed_to_deserialize_manifest_file(path.to_str().unwrap(), err)) diff --git a/utils/retriever/src/program_context/network_name.rs b/utils/retriever/src/program_context/network_name.rs index 9708581e5e..e9a87d07fc 100644 --- a/utils/retriever/src/program_context/network_name.rs +++ b/utils/retriever/src/program_context/network_name.rs @@ -16,7 +16,7 @@ use leo_errors::{CliError, LeoError}; use serde::{Deserialize, Serialize}; -use snarkvm::prelude::{MainnetV0, Network, TestnetV0}; +use snarkvm::prelude::{CanaryV0, MainnetV0, Network, TestnetV0}; use std::fmt; // Retrievable networks for an external program @@ -26,6 +26,8 @@ pub enum NetworkName { TestnetV0, #[serde(rename = "mainnet")] MainnetV0, + #[serde(rename = "canary")] + CanaryV0, } impl NetworkName { @@ -33,6 +35,7 @@ impl NetworkName { match self { NetworkName::TestnetV0 => TestnetV0::ID, NetworkName::MainnetV0 => MainnetV0::ID, + NetworkName::CanaryV0 => CanaryV0::ID, } } } @@ -44,16 +47,33 @@ impl TryFrom<&str> for NetworkName { match network { "testnet" => Ok(NetworkName::TestnetV0), "mainnet" => Ok(NetworkName::MainnetV0), + "canary" => Ok(NetworkName::CanaryV0), _ => Err(LeoError::CliError(CliError::invalid_network_name(network))), } } } +impl TryFrom for NetworkName { + type Error = LeoError; + + fn try_from(network: String) -> Result { + if network == "testnet" { + Ok(NetworkName::TestnetV0) + } else if network == "mainnet" { + Ok(NetworkName::MainnetV0) + } else if network == "canary" { + Ok(NetworkName::CanaryV0) + } else { + Err(LeoError::CliError(CliError::invalid_network_name(&network))) + } + } +} impl fmt::Display for NetworkName { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { NetworkName::TestnetV0 => write!(f, "testnet"), NetworkName::MainnetV0 => write!(f, "mainnet"), + NetworkName::CanaryV0 => write!(f, "canary"), } } }