diff --git a/.circleci/token/run.sh b/.circleci/token/run.sh index 3180c4cfec..bff3959a56 100644 --- a/.circleci/token/run.sh +++ b/.circleci/token/run.sh @@ -21,6 +21,7 @@ fi echo " NETWORK=testnet 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=testnet 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=testnet 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=testnet 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=testnet 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=testnet 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=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env diff --git a/Cargo.lock b/Cargo.lock index ef1f9404e9..b9078f57e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,6 +196,15 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "arrayref" version = "0.3.7" @@ -429,9 +438,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", "clap_derive", @@ -439,9 +448,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstream", "anstyle", @@ -451,9 +460,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck", "proc-macro2", @@ -741,6 +750,30 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote 1.0.36", + "syn 2.0.66", +] + +[[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" @@ -799,6 +832,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote 1.0.36", + "syn 2.0.66", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -857,6 +901,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" @@ -1470,9 +1534,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "leo-abnf" @@ -1560,6 +1624,7 @@ dependencies = [ "colored", "console", "crossterm", + "dialoguer", "dirs 5.0.1", "dotenvy", "indexmap 1.9.3", @@ -1578,7 +1643,7 @@ dependencies = [ "reqwest 0.12.5", "rpassword", "rusty-hook", - "self_update 0.40.0", + "self_update 0.41.0", "serde", "serde_json", "serial_test", @@ -1598,6 +1663,7 @@ name = "leo-package" version = "1.12.0" dependencies = [ "aleo-std", + "dialoguer", "indexmap 1.9.3", "lazy_static", "leo-errors", @@ -2629,9 +2695,9 @@ dependencies = [ [[package]] name = "self_update" -version = "0.40.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4997484b55df069a4773d822715695b2cc27b23829eca2a4b41690e948bdeb" +checksum = "469a3970061380c19852269f393e74c0fe607a4e23d85267382cf25486aa8de5" dependencies = [ "hyper 1.3.1", "indicatif", @@ -2764,6 +2830,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" @@ -2834,7 +2906,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "anstyle", "anyhow", @@ -2863,7 +2935,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "anyhow", @@ -2893,7 +2965,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-account", "snarkvm-circuit-algorithms", @@ -2907,7 +2979,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-network", @@ -2918,7 +2990,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-types", "snarkvm-console-algorithms", @@ -2928,7 +3000,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-types", @@ -2938,7 +3010,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "indexmap 2.2.6", "itertools 0.11.0", @@ -2956,12 +3028,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" [[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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-algorithms", "snarkvm-circuit-collections", @@ -2972,7 +3044,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "paste", "snarkvm-circuit-account", @@ -2987,7 +3059,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-address", @@ -3002,7 +3074,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3015,7 +3087,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-environment", "snarkvm-console-types-boolean", @@ -3024,7 +3096,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3034,7 +3106,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3046,7 +3118,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3058,7 +3130,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3069,7 +3141,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-circuit-environment", "snarkvm-circuit-types-boolean", @@ -3081,7 +3153,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-account", "snarkvm-console-algorithms", @@ -3094,7 +3166,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "bs58", "snarkvm-console-network", @@ -3105,7 +3177,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "blake2s_simd", "smallvec", @@ -3118,7 +3190,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "rayon", @@ -3129,7 +3201,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "anyhow", "indexmap 2.2.6", @@ -3152,7 +3224,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "anyhow", "bech32", @@ -3170,8 +3242,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ + "enum-iterator", "enum_index", "enum_index_derive", "indexmap 2.2.6", @@ -3191,7 +3264,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-address", @@ -3206,7 +3279,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3217,7 +3290,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-network-environment", ] @@ -3225,7 +3298,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3235,7 +3308,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3246,7 +3319,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3257,7 +3330,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3268,7 +3341,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console-network-environment", "snarkvm-console-types-boolean", @@ -3279,7 +3352,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "rand", "rayon", @@ -3293,7 +3366,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "anyhow", @@ -3310,7 +3383,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "anyhow", @@ -3334,7 +3407,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "anyhow", "rand", @@ -3346,7 +3419,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3365,7 +3438,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3377,7 +3450,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-ledger-narwhal-batch-certificate", "snarkvm-ledger-narwhal-batch-header", @@ -3390,7 +3463,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3403,7 +3476,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3415,7 +3488,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "bytes", "serde_json", @@ -3426,7 +3499,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "indexmap 2.2.6", "rayon", @@ -3441,7 +3514,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "bytes", "serde_json", @@ -3454,7 +3527,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "snarkvm-console", "snarkvm-ledger-puzzle", @@ -3463,7 +3536,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "anyhow", @@ -3483,22 +3556,28 @@ 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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ + "aleo-std", "anyhow", "colored", "indexmap 2.2.6", + "lru", + "parking_lot", "rand", "rand_chacha", "rayon", + "snarkvm-circuit", "snarkvm-console", "snarkvm-ledger-puzzle", + "snarkvm-synthesizer-process", + "snarkvm-synthesizer-program", ] [[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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "async-trait", "reqwest 0.11.27", @@ -3511,7 +3590,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std-storage", "anyhow", @@ -3534,7 +3613,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "anyhow", @@ -3559,7 +3638,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "anyhow", @@ -3569,6 +3648,7 @@ dependencies = [ "parking_lot", "rand", "rayon", + "serde_json", "snarkvm-algorithms", "snarkvm-circuit", "snarkvm-console", @@ -3588,7 +3668,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "colored", @@ -3611,7 +3691,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "indexmap 2.2.6", "paste", @@ -3625,7 +3705,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "bincode", "once_cell", @@ -3638,7 +3718,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "aleo-std", "anyhow", @@ -3659,7 +3739,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=d170a9f#d170a9f7c5ef980f9392301dc899dee355599ca6" dependencies = [ "proc-macro2", "quote 1.0.36", @@ -4579,13 +4659,17 @@ dependencies = [ [[package]] name = "zip" -version = "0.6.6" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +checksum = "775a2b471036342aa69bc5a602bc889cb0a06cda00477d0c69566757d5553d39" dependencies = [ - "byteorder", + "arbitrary", "crc32fast", "crossbeam-utils", + "displaydoc", + "indexmap 2.2.6", + "memchr", + "thiserror", "time", ] diff --git a/Cargo.toml b/Cargo.toml index 689ec0f93e..facd11cdf6 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" @@ -124,7 +125,7 @@ version = "1.9" features = [ "serde" ] [dependencies.lazy_static] -version = "1.4.0" +version = "1.5.0" [dependencies.rand] version = "0.8" @@ -141,7 +142,7 @@ version = "0.12.5" features = [ "blocking", "json", "multipart" ] [dependencies.self_update] -version = "0.40.0" +version = "0.41.0" features = [ "archive-zip" ] [dependencies.serde] diff --git a/compiler/compiler/tests/utilities/mod.rs b/compiler/compiler/tests/utilities/mod.rs index 9f007e934c..729297bcaa 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/compiler/parser/Cargo.toml b/compiler/parser/Cargo.toml index b539229d0d..c616ade9aa 100644 --- a/compiler/parser/Cargo.toml +++ b/compiler/parser/Cargo.toml @@ -41,7 +41,7 @@ features = [ "derive" ] version = "1.9" [dependencies.lazy_static] -version = "1.3.0" +version = "1.5.0" [dependencies.serde] version = "1.0" diff --git a/compiler/parser/src/parser/context.rs b/compiler/parser/src/parser/context.rs index 8639412447..da9ade6085 100644 --- a/compiler/parser/src/parser/context.rs +++ b/compiler/parser/src/parser/context.rs @@ -39,7 +39,7 @@ pub(crate) struct ParserContext<'a, N: Network> { /// The previous token, i.e., if `p.tokens = ['3', *, '4']`, /// then after two `p.bump()`s, we'll have `p.token = '*'` and `p.prev_token = '3'`. pub(crate) prev_token: SpannedToken, - /// true if parsing an expression for if and loop statements -- means struct inits are not legal + /// True if parsing an expression for if and loop statements -- means struct inits are not legal. pub(crate) disallow_struct_construction: bool, /// The name of the program being parsed. pub(crate) program_name: Option, @@ -95,7 +95,7 @@ impl<'a, N: Network> ParserContext<'a, N> { &self.token.token == tok } - /// Checks whether the current token is a `Token::Int(_)`. + /// Checks whether the current token is a `Token::Integer(_)`. pub(super) fn check_int(&self) -> bool { matches!(&self.token.token, Token::Integer(_)) } @@ -142,7 +142,7 @@ impl<'a, N: Network> ParserContext<'a, N> { Identifier { name, span, id: self.node_builder.next_id() } } - /// Eats the next token if its an identifier and returns it. + /// Eats the next token if it is an identifier and returns it. pub(super) fn eat_identifier(&mut self) -> Option { if let Token::Identifier(name) = self.token.token { self.bump(); diff --git a/compiler/parser/src/parser/file.rs b/compiler/parser/src/parser/file.rs index 06d844a987..3cd50e1809 100644 --- a/compiler/parser/src/parser/file.rs +++ b/compiler/parser/src/parser/file.rs @@ -75,11 +75,12 @@ impl ParserContext<'_, N> { // Parse `foo`. let import_name = self.expect_identifier()?; - // Parse `.aleo`. + // Parse `.`. self.expect(&Token::Dot)?; + // Parse network, which currently must be `aleo`. if !self.eat(&Token::Aleo) { - // Throw error for non-aleo files. + // Throw error for non-aleo networks. return Err(ParserError::invalid_network(self.token.span).into()); } @@ -100,10 +101,10 @@ impl ParserContext<'_, N> { // Set the program name in the context. self.program_name = Some(name.name); - // Parse the program network. + // Parse the `.`. self.expect(&Token::Dot)?; - // Otherwise throw parser error + // Parse the program network, which must be `aleo`, otherwise throw parser error. self.expect(&Token::Aleo).map_err(|_| ParserError::invalid_network(self.token.span))?; // Construct the program id. diff --git a/compiler/parser/src/parser/mod.rs b/compiler/parser/src/parser/mod.rs index 7a6ee0d571..33e350a893 100644 --- a/compiler/parser/src/parser/mod.rs +++ b/compiler/parser/src/parser/mod.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with the Leo library. If not, see . -//! The parser to convert Leo code text into an [`Program`] AST type. +//! The parser to convert Leo code text into a [`Program`] AST type. //! -//! This module contains the [`parse()`] method which calls the underlying [`tokenize()`] -//! method to create a new program ast. +//! This module contains the [`parse()`] function which calls the underlying [`tokenize()`] +//! method to create a new program AST. use crate::{tokenizer::*, Token}; diff --git a/compiler/parser/src/tokenizer/lexer.rs b/compiler/parser/src/tokenizer/lexer.rs index fbe5bb7864..a7c33af1e7 100644 --- a/compiler/parser/src/tokenizer/lexer.rs +++ b/compiler/parser/src/tokenizer/lexer.rs @@ -154,8 +154,15 @@ impl Token { // } // } - /// Returns a tuple: [(integer length, integer token)] if an integer can be eaten, otherwise returns [`None`]. - /// An integer can be eaten if its bytes are at the front of the given `input` string. + /// Returns a tuple: [(integer length, integer token)] if an integer can be eaten. + /// An integer can be eaten if its characters are at the front of the given `input` string. + /// If there is no input, this function returns an error. + /// If there is input but no integer, this function returns the tuple consisting of + /// length 0 and a dummy integer token that contains an empty string. + /// However, this function is always called when the next character is a digit. + /// This function eats a sequence of one or more digits and underscores + /// (starting from a digit, as explained above, given when it is called), + /// which corresponds to a numeral in the ABNF grammar. fn eat_integer(input: &mut Peekable>) -> Result<(usize, Token)> { if input.peek().is_none() { return Err(ParserError::lexer_empty_input().into()); @@ -178,7 +185,7 @@ impl Token { } /// Returns a tuple: [(token length, token)] if the next token can be eaten, otherwise returns an error. - /// The next token can be eaten if the bytes at the front of the given `input` string can be scanned into a token. + /// The next token can be eaten if the characters at the front of the given `input` string can be scanned into a token. pub(crate) fn eat(input: &str) -> Result<(usize, Token)> { if input.is_empty() { return Err(ParserError::lexer_empty_input().into()); @@ -221,13 +228,13 @@ impl Token { // See the example with the different combinations for Mul, MulAssign, Pow, PowAssign below. let match_four = | input: &mut Peekable<_>, - first_token, // Mul '*' - second_char, // '=' - second_token, // MulAssign '*=' - third_char, // '*' - third_token, // Pow '**' - fourth_char, // '=' - fourth_token // PowAssign '**=' + first_token, // e.e. Mul '*' + second_char, // e.g. '=' + second_token, // e.g. MulAssign '*=' + third_char, // e.g. '*' + third_token, // e.g. Pow '**' + fourth_char, // e.g. '=' + fourth_token // e.g. PowAssign '**=' | { input.next(); Ok(if input.next_if_eq(&second_char).is_some() { @@ -252,7 +259,7 @@ impl Token { // Find end string quotation mark. // Instead of checking each `char` and pushing, we can avoid reallocations. // This works because the code 34 of double quote cannot appear as a byte - // in middle of a multi-byte UTF-8 encoding of a character, + // in the middle of a multi-byte UTF-8 encoding of a character, // because those bytes all have the high bit set to 1; // in UTF-8, the byte 34 can only appear as the single-byte encoding of double quote. let rest = &input_str[1..]; @@ -306,7 +313,7 @@ impl Token { if input.next_if_eq(&'/').is_some() { // Find the end of the comment line. // This works because the code 10 of line feed cannot appear as a byte - // in middle of a multi-byte UTF-8 encoding of a character, + // in the middle of a multi-byte UTF-8 encoding of a character, // because those bytes all have the high bit set to 1; // in UTF-8, the byte 10 can only appear as the single-byte encoding of line feed. let comment = match input_str.as_bytes().iter().position(|c| *c == b'\n') { @@ -416,8 +423,8 @@ impl Token { "record" => Token::Record, "return" => Token::Return, "scalar" => Token::Scalar, - "signature" => Token::Signature, "self" => Token::SelfLower, + "signature" => Token::Signature, "string" => Token::String, "struct" => Token::Struct, "transition" => Token::Transition, diff --git a/compiler/parser/src/tokenizer/token.rs b/compiler/parser/src/tokenizer/token.rs index ce76068b84..f810cea96c 100644 --- a/compiler/parser/src/tokenizer/token.rs +++ b/compiler/parser/src/tokenizer/token.rs @@ -29,20 +29,24 @@ use leo_span::{sym, Symbol}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Token { // Comments - CommentLine(String), - CommentBlock(String), + CommentLine(String), // the string includes the starting '//' and the ending line feed + CommentBlock(String), // the string includes the starting '/*' and the ending '*/' // Whitespace (we do not distinguish among different kinds here) WhiteSpace, // Literals (= atomic literals and numerals in the ABNF grammar) - // The string in Integer(String) consists of digits optionally followed by a type - // The string in AddressLit(String) has the form `aleo1...` + // The string in Integer(String) consists of digits + // The string in AddressLit(String) has the form `aleo1...`. True, False, - Integer(String), // = numeric literal or numeral in the ABNF grammar + Integer(String), // = numeral (including tuple index) in the ABNF grammar AddressLit(String), StaticString(String), + // The numeric literals in the ABNF grammar, which consist of numerals followed by types, + // are represented not as single tokens here, + // but as two separate tokens (one for the numeral and one for the type), + // enforcing, during parsing, the absence of whitespace or comments between those two tokens. // Identifiers Identifier(Symbol), diff --git a/errors/src/common/mod.rs b/errors/src/common/mod.rs index 3a580f97f4..41c10ce326 100644 --- a/errors/src/common/mod.rs +++ b/errors/src/common/mod.rs @@ -32,7 +32,7 @@ pub use self::traits::*; // Right now for cleanliness of calling error functions we say each argument implements one of the follow types rather than giving a specific type. // This allows us to just pass many types rather doing conversions cleaning up the code. -// The args can be made cleaneronce https://github.com/rust-lang/rust/issues/41517 or https://github.com/rust-lang/rust/issues/63063 hits stable. +// The args can be made cleaner once https://github.com/rust-lang/rust/issues/41517 or https://github.com/rust-lang/rust/issues/63063 hits stable. // Either of why would allows to generate a type alias for these trait implementing types. // pub(crate) type DisplayArg = impl std::fmt::Display; // pub(crate) type DebugArg = impl std::fmt::Debug; 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..c99242d405 100644 --- a/errors/src/errors/mod.rs +++ b/errors/src/errors/mod.rs @@ -60,16 +60,16 @@ pub enum LeoError { /// Represents an AST Error in a Leo Error. #[error(transparent)] AstError(#[from] AstError), - /// Represents an CLI Error in a Leo Error. + /// Represents a CLI Error in a Leo Error. #[error(transparent)] CliError(#[from] CliError), - /// Represents an Compiler Error in a Leo Error. + /// Represents a Compiler Error in a Leo Error. #[error(transparent)] CompilerError(#[from] CompilerError), - /// Represents an Package Error in a Leo Error. + /// Represents a Package Error in a Leo Error. #[error(transparent)] PackageError(#[from] PackageError), - /// Represents an Parser Error in a Leo Error. + /// Represents a Parser Error in a Leo Error. #[error(transparent)] ParserError(#[from] ParserError), /// Represents a Type Checker Error in a Leo Error. @@ -85,7 +85,7 @@ pub enum LeoError { /// not re-displaying an error. #[error("")] LastErrorCode(i32), - /// Represents a Utils Error in a Leo Error + /// Represents a Utils Error in a Leo Error. #[error(transparent)] UtilError(#[from] UtilError), /// Anyhow errors. @@ -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,19 +128,19 @@ 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. } } } -/// The LeoWarning type that contains all sub error types. -/// This allows a unified error type throughout the Leo crates. +/// The LeoWarning type that contains all sub warning types. +/// This allows a unified warning type throughout the Leo crates. #[derive(Debug, Error)] pub enum LeoWarning { - /// Represents an Parser Error in a Leo Error. + /// Represents an Parser Warning in a Leo Warning. #[error(transparent)] ParserWarning(#[from] ParserWarning), - /// Represents a Type Checker Error in a Leo Error. + /// Represents a Type Checker Warning in a Leo Warning. #[error(transparent)] TypeCheckerWarning(#[from] TypeCheckerWarning), } 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 4eec2d2cb9..98c1366cc8 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/errors/src/lib.rs b/errors/src/lib.rs index eac73c9d90..55bfc9f5b7 100644 --- a/errors/src/lib.rs +++ b/errors/src/lib.rs @@ -21,7 +21,7 @@ #[macro_use] extern crate thiserror; -/// Contains the common functionalities for defining errors.. +/// Contains the common functionalities for defining errors. #[macro_use] pub mod common; pub use self::common::*; @@ -29,6 +29,6 @@ pub use self::common::*; /// Contains traits and types for channels through which errors go. pub mod emitter; -/// Contains the errors and warnings for the Leo lang. +/// Contains the errors and warnings for the Leo language. pub mod errors; pub use self::errors::*; diff --git a/examples/auction/.env b/examples/auction/.env index 57c2951eba..cb5fec963e 100644 --- a/examples/auction/.env +++ b/examples/auction/.env @@ -1,4 +1,4 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH - +ENDPOINT=https://localhost:3030 diff --git a/examples/auction/run.sh b/examples/auction/run.sh index ecd70abddd..7804637849 100755 --- a/examples/auction/run.sh +++ b/examples/auction/run.sh @@ -40,6 +40,7 @@ echo " echo " NETWORK=testnet 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=testnet 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=testnet PRIVATE_KEY=APrivateKey1zkp2GUmKbVsuc1NSj28pa1WTQuZaK5f1DQJAT6vPcHyWokG +ENDPOINT=https://localhost:3030 " > .env # Have the auctioneer select the winning bid. @@ -141,6 +144,7 @@ leo run finish "{ echo " NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env diff --git a/examples/basic_bank/.env b/examples/basic_bank/.env index 57c2951eba..cb5fec963e 100644 --- a/examples/basic_bank/.env +++ b/examples/basic_bank/.env @@ -1,4 +1,4 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH - +ENDPOINT=https://localhost:3030 diff --git a/examples/basic_bank/run.sh b/examples/basic_bank/run.sh index 764d48c8ff..109119bb78 100755 --- a/examples/basic_bank/run.sh +++ b/examples/basic_bank/run.sh @@ -20,6 +20,7 @@ fi echo " NETWORK=testnet 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=testnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env # Have the user deposit 50 tokens into the bank. @@ -164,6 +166,7 @@ echo " echo " NETWORK=testnet 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 f8b0fa12bb..262ddf8770 100644 --- a/examples/battleship/.env +++ b/examples/battleship/.env @@ -1,3 +1,4 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 diff --git a/examples/battleship/run.sh b/examples/battleship/run.sh index 1553b7adbb..ed66acecc0 100755 --- a/examples/battleship/run.sh +++ b/examples/battleship/run.sh @@ -19,6 +19,7 @@ echo " echo " NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env echo "✅ Successfully initialized Player 1." @@ -69,6 +70,7 @@ echo " echo " NETWORK=testnet 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=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env leo run play '{ @@ -152,6 +155,7 @@ echo " echo " NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env leo run play '{ @@ -187,6 +191,7 @@ echo " echo " NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env leo run play '{ @@ -222,6 +227,7 @@ echo " echo " NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh +ENDPOINT=https://localhost:3030 " > .env leo run play '{ @@ -250,4 +256,5 @@ echo " echo " NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env diff --git a/examples/bubblesort/.env b/examples/bubblesort/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/bubblesort/.env +++ b/examples/bubblesort/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/core/.env b/examples/core/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/core/.env +++ b/examples/core/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/fibonacci/.env b/examples/fibonacci/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/fibonacci/.env +++ b/examples/fibonacci/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/groups/.env b/examples/groups/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/groups/.env +++ b/examples/groups/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzdebruijn/.env b/examples/hackers-delight/ntzdebruijn/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/hackers-delight/ntzdebruijn/.env +++ b/examples/hackers-delight/ntzdebruijn/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzgaudet/.env b/examples/hackers-delight/ntzgaudet/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/hackers-delight/ntzgaudet/.env +++ b/examples/hackers-delight/ntzgaudet/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzloops/.env b/examples/hackers-delight/ntzloops/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/hackers-delight/ntzloops/.env +++ b/examples/hackers-delight/ntzloops/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzmasks/.env b/examples/hackers-delight/ntzmasks/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/hackers-delight/ntzmasks/.env +++ b/examples/hackers-delight/ntzmasks/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzreisers/.env b/examples/hackers-delight/ntzreisers/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/hackers-delight/ntzreisers/.env +++ b/examples/hackers-delight/ntzreisers/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzseals/.env b/examples/hackers-delight/ntzseals/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/hackers-delight/ntzseals/.env +++ b/examples/hackers-delight/ntzseals/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzsearchtree/.env b/examples/hackers-delight/ntzsearchtree/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/hackers-delight/ntzsearchtree/.env +++ b/examples/hackers-delight/ntzsearchtree/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/hackers-delight/ntzsmallvals/.env b/examples/hackers-delight/ntzsmallvals/.env index 1461c50ecc..cb5fec963e 100644 --- a/examples/hackers-delight/ntzsmallvals/.env +++ b/examples/hackers-delight/ntzsmallvals/.env @@ -1,3 +1,4 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/helloworld/.env b/examples/helloworld/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/helloworld/.env +++ b/examples/helloworld/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/interest/.env b/examples/interest/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/interest/.env +++ b/examples/interest/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/lottery/.env b/examples/lottery/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/lottery/.env +++ b/examples/lottery/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/message/.env b/examples/message/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/message/.env +++ b/examples/message/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/simple_token/.env b/examples/simple_token/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/simple_token/.env +++ b/examples/simple_token/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/tictactoe/.env b/examples/tictactoe/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/tictactoe/.env +++ b/examples/tictactoe/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/token/.env b/examples/token/.env index 57c2951eba..cb5fec963e 100644 --- a/examples/token/.env +++ b/examples/token/.env @@ -1,4 +1,4 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH - +ENDPOINT=https://localhost:3030 diff --git a/examples/token/run.sh b/examples/token/run.sh index d3c44dcb1e..cbf5393654 100755 --- a/examples/token/run.sh +++ b/examples/token/run.sh @@ -20,6 +20,7 @@ fi echo " NETWORK=testnet 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=testnet 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=testnet 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=testnet 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=testnet 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=testnet 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=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 " > .env diff --git a/examples/twoadicity/.env b/examples/twoadicity/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/twoadicity/.env +++ b/examples/twoadicity/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/examples/vote/.env b/examples/vote/.env index 376e73c4b1..0a686ef86f 100644 --- a/examples/vote/.env +++ b/examples/vote/.env @@ -1,2 +1,3 @@ NETWORK=testnet PRIVATE_KEY=APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH +ENDPOINT=https://localhost:3030 diff --git a/leo/cli/cli.rs b/leo/cli/cli.rs index ff32376685..9aab0392ce 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 = "testnet"; + 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 457fdb6d29..80e4bff989 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 = "testnet")] 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 = "testnet")] 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 f7eb904c92..86d1aac040 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 = "testnet")] 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 ee19add26b..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 testnet.", default_value = "testnet")] - 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: "testnet".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 5004434cc2..00cb9a622d 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 = "testnet")] 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 7ed2e43532..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 testnet.", default_value = "testnet")] - 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..1fd0e2cc04 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" @@ -60,7 +63,7 @@ version = "0.8" version = "0.1" [dev-dependencies.lazy_static] -version = "1.3.0" +version = "1.5.0" [dev-dependencies.snarkvm] workspace = true 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 b12ed64709..53358ed4e5 100644 --- a/utils/retriever/src/program_context/network_name.rs +++ b/utils/retriever/src/program_context/network_name.rs @@ -15,7 +15,7 @@ // along with the Leo library. If not, see . use leo_errors::{CliError, LeoError}; -use snarkvm::prelude::{MainnetV0, Network, TestnetV0}; +use snarkvm::prelude::{CanaryV0, MainnetV0, Network, TestnetV0}; use serde::{Deserialize, Serialize}; use std::fmt; @@ -27,6 +27,8 @@ pub enum NetworkName { TestnetV0, #[serde(rename = "mainnet")] MainnetV0, + #[serde(rename = "canary")] + CanaryV0, } impl NetworkName { @@ -34,6 +36,7 @@ impl NetworkName { match self { NetworkName::TestnetV0 => TestnetV0::ID, NetworkName::MainnetV0 => MainnetV0::ID, + NetworkName::CanaryV0 => CanaryV0::ID, } } } @@ -45,16 +48,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"), } } }