From 898a2dbf0d02b5dd6f22a74d4469749c2ac51c48 Mon Sep 17 00:00:00 2001 From: Nuno Boavida <45330362+nmboavida@users.noreply.github.com> Date: Mon, 16 Jan 2023 21:53:30 +0000 Subject: [PATCH 1/3] Init Collection Command --- Cargo.lock | 57 +++++ crates/byte_cli/Cargo.toml | 1 + crates/byte_cli/src/endpoints.rs | 3 + crates/byte_cli/src/endpoints/init_config.rs | 249 +++++++++++++++++++ crates/byte_cli/src/lib.rs | 1 + crates/byte_cli/src/main.rs | 7 +- crates/byte_cli/src/prelude.rs | 1 + 7 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 crates/byte_cli/src/endpoints.rs create mode 100644 crates/byte_cli/src/endpoints/init_config.rs diff --git a/Cargo.lock b/Cargo.lock index b044c95..1f76dd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,6 +121,7 @@ dependencies = [ "anyhow", "clap", "console", + "dialoguer", "gutenberg", "pretty_assertions", "serde", @@ -200,6 +201,18 @@ dependencies = [ "syn", ] +[[package]] +name = "dialoguer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af3c796f3b0b408d9fd581611b47fa850821fcb84aa640b83a3c1a5be2d691f2" +dependencies = [ + "console", + "shell-words", + "tempfile", + "zeroize", +] + [[package]] name = "diff" version = "0.1.13" @@ -248,6 +261,15 @@ dependencies = [ "libc", ] +[[package]] +name = "fastrand" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +dependencies = [ + "instant", +] + [[package]] name = "getrandom" version = "0.2.8" @@ -539,6 +561,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + [[package]] name = "rustix" version = "0.36.6" @@ -610,6 +641,12 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "smallvec" version = "1.10.0" @@ -639,6 +676,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi", +] + [[package]] name = "termcolor" version = "1.1.3" @@ -918,3 +969,9 @@ name = "yansi" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/crates/byte_cli/Cargo.toml b/crates/byte_cli/Cargo.toml index 93b6751..583b1ea 100644 --- a/crates/byte_cli/Cargo.toml +++ b/crates/byte_cli/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] gutenberg = { path = "../gutenberg" } +dialoguer = "0.10" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" # thiserror = "1.0" diff --git a/crates/byte_cli/src/endpoints.rs b/crates/byte_cli/src/endpoints.rs new file mode 100644 index 0000000..cbcdd9f --- /dev/null +++ b/crates/byte_cli/src/endpoints.rs @@ -0,0 +1,3 @@ +pub mod init_config; + +pub use init_config::*; diff --git a/crates/byte_cli/src/endpoints/init_config.rs b/crates/byte_cli/src/endpoints/init_config.rs new file mode 100644 index 0000000..a41ed87 --- /dev/null +++ b/crates/byte_cli/src/endpoints/init_config.rs @@ -0,0 +1,249 @@ +use crate::prelude::*; +use anyhow::Result; +use clap::Parser; +use console::{style, Style}; +use dialoguer::theme::ColorfulTheme; +use dialoguer::{Confirm, Input, MultiSelect, Select}; +use gutenberg::{models::nft, schema, types::Royalties}; + +const TAG_OPTIONS: [&str; 11] = [ + "Art", + "ProfilePicture", + "Collectible", + "GameAsset", + "TokenisedAsset", + "Ticker", + "DomainName", + "Music", + "Video", + "Ticket", + "License", +]; + +const FIELD_OPTIONS: [&str; 3] = ["display", "url", "attributes"]; +const BEHAVIOUR_OPTIONS: [&str; 2] = ["composable", "loose"]; +const SUPPLY_OPTIONS: [&str; 2] = ["Unlimited", "Limited"]; +const MINTING_OPTIONS: [&str; 3] = ["Launchpad", "Direct", "Airdrop"]; +const ROYALTY_OPTIONS: [&str; 3] = ["Proportional", "Constant", "None"]; + +pub fn get_dialoguer_theme() -> ColorfulTheme { + ColorfulTheme { + prompt_style: Style::new(), + checked_item_prefix: style("✔".to_string()).green().force_styling(true), + unchecked_item_prefix: style("✔".to_string()) + .black() + .force_styling(true), + ..Default::default() + } +} + +pub fn map_indices(indices: Vec, arr: &[&str]) -> Vec { + let vec: Vec = indices + .iter() + .map(|index| arr[*index].to_string()) + .collect(); + vec +} + +pub fn init_collection_config() { + let mut schema = schema::Schema::new(); + let theme = get_dialoguer_theme(); + + let string_validator = |_input: &String| -> Result<(), String> { Ok(()) }; + + let _float_validator = |input: &String| -> Result<(), String> { + if !input.is_empty() && input.parse::().is_err() { + Err(format!( + "Couldn't parse price input of '{}' to a float.", + input + )) + } else { + Ok(()) + } + }; + + let number_validator = |input: &String| -> Result<(), String> { + if input.parse::().is_err() { + Err(format!("Couldn't parse input of '{}' to a number.", input)) + } else { + Ok(()) + } + }; + + let name = Input::with_theme(&theme) + .with_prompt("What is the name of the Collection?") + .validate_with(string_validator) + .interact() + .unwrap(); + + schema.collection.set_name(name); + + let description = Input::with_theme(&theme) + .with_prompt("What is the description of the Collection?") + .validate_with(string_validator) + .interact() + .unwrap(); + + schema.collection.set_description(description); + + let symbol = Input::with_theme(&theme) + .with_prompt("What is the symbol of the Collection?") + .validate_with(string_validator) + .interact() + .unwrap(); + + schema.collection.set_symbol(symbol); + + let has_tags = Confirm::with_theme(&theme) + .with_prompt("Do you want to add Tags to your Collection?") + .interact() + .unwrap(); + + if has_tags { + let tag_indices = MultiSelect::with_theme(&theme) + .with_prompt("Which tags do you want to add? (use [SPACEBAR] to select options you want and hit [ENTER] when done)") + .items(&TAG_OPTIONS) + .interact() + .unwrap(); + + let tags = map_indices(tag_indices, &TAG_OPTIONS); + + schema.collection.set_tags(&tags).unwrap(); + } + + let has_url = Confirm::with_theme(&theme) + .with_prompt("Do you want to add a URL to your Collection Website?") + .interact() + .unwrap(); + + if has_url { + let url = Input::with_theme(&theme) + .with_prompt("What is the URL of the Collection Website?") + .validate_with(string_validator) + .interact() + .unwrap(); + + schema.collection.set_url(url); + }; + + let nft_field_indices = MultiSelect::with_theme(&theme) + .with_prompt("Which NFT fields do you want the NFTs to have? (use [SPACEBAR] to select options you want and hit [ENTER] when done)") + .items(&FIELD_OPTIONS) + .interact() + .unwrap(); + + let mut nft_fields = map_indices(nft_field_indices, &FIELD_OPTIONS); + + // Since the creator has already mentioned that the Collection has Tags + if has_tags { + nft_fields.push("tags".to_string()); + }; + + schema.nft.fields = nft::Fields::new_from(nft_fields).unwrap(); + + let nft_behaviour_indices = MultiSelect::with_theme(&theme) + .with_prompt("Which NFT behaviours do you want the NFTs to have? (use [SPACEBAR] to select options you want and hit [ENTER] when done)") + .items(&BEHAVIOUR_OPTIONS) + .interact() + .unwrap(); + + let nft_behaviours = map_indices(nft_behaviour_indices, &BEHAVIOUR_OPTIONS); + + schema.nft.behaviours = nft::Behaviours::new_from(nft_behaviours).unwrap(); + + let supply_index = Select::with_theme(&theme) + .with_prompt("Which Supply Policy do you want your Collection to have?") + .items(&SUPPLY_OPTIONS) + .interact() + .unwrap(); + + let supply_policy = SUPPLY_OPTIONS[supply_index]; + + let mut limit = Option::None; + + if supply_policy == "Limited" { + limit = Some( + Input::with_theme(&theme) + .with_prompt("What is the supply limit of the Collection?") + .validate_with(number_validator) + .interact() + .unwrap() + .parse::() + .expect("Failed to parse String into u64 - This error should not occur has input has been already validated.") + ); + } + + schema.nft.supply_policy = + nft::SupplyPolicy::new_from(supply_policy, limit).unwrap(); + + let mint_strategy_indices = MultiSelect::with_theme(&theme) + .with_prompt("Which minting strategies do you plan using? (use [SPACEBAR] to select options you want and hit [ENTER] when done)") + .items(&MINTING_OPTIONS) + .interact() + .unwrap(); + + let mint_strategies = map_indices(mint_strategy_indices, &MINTING_OPTIONS); + + schema.nft.mint_strategy = + nft::MintStrategy::new_from(mint_strategies).unwrap(); + + let royalty_index = Select::with_theme(&theme) + .with_prompt( + "Which Royalty Policy do you want your Collection to have?", + ) + .items(&ROYALTY_OPTIONS) + .interact() + .unwrap(); + + let royalty_policy = ROYALTY_OPTIONS[royalty_index]; + + let mut fee = Option::None; + + if royalty_policy == "Proportional" { + fee = Some( + Input::with_theme(&theme) + .with_prompt("What is the royalty fee in Basis Points?") + .validate_with(number_validator) + .interact() + .unwrap() + .parse::() + .expect("Failed to parse String into u64 - This error should not occur has input has been already validated.") + ); + } + if royalty_policy == "Constant" { + fee = Some( + Input::with_theme(&theme) + .with_prompt("What is the constant royalty commission?") + .validate_with(number_validator) + .interact() + .unwrap() + .parse::() + .expect("Failed to parse String into u64 - This error should not occur has input has been already validated.") + ); + } + + schema.royalties = Royalties::new_from(royalty_policy, fee).unwrap(); + + let listings: u64 = Input::with_theme(&theme) + .with_prompt( + // TODO: The meaning of this questions may be ambiguous + // from the perspective of the creator + "How many Primary Market Listings do you plan on having?", + ) + .validate_with(number_validator) + .interact() + .unwrap() + .parse::() + .expect("Failed to parse String into u64 - This error should not occur has input has been already validated."); + + for i in [..listings] {} + + // // Listings + // pub struct Listing { + // #[serde(default = "default_admin")] + // admin: String, + // #[serde(default = "default_admin")] + // receiver: String, + // markets: Vec, + // } +} diff --git a/crates/byte_cli/src/lib.rs b/crates/byte_cli/src/lib.rs index 438d7e0..c0829de 100644 --- a/crates/byte_cli/src/lib.rs +++ b/crates/byte_cli/src/lib.rs @@ -1,3 +1,4 @@ pub mod cli; pub mod consts; +pub mod endpoints; pub mod prelude; diff --git a/crates/byte_cli/src/main.rs b/crates/byte_cli/src/main.rs index 698b238..e6004f9 100644 --- a/crates/byte_cli/src/main.rs +++ b/crates/byte_cli/src/main.rs @@ -1,12 +1,13 @@ pub mod cli; pub mod consts; +pub mod endpoints; pub mod prelude; +use crate::endpoints::init_config; use crate::prelude::*; use anyhow::Result; use clap::Parser; use console::style; -use gutenberg; #[tokio::main] async fn main() { @@ -29,7 +30,9 @@ async fn run() -> Result<()> { let cli = Cli::parse(); match cli.command { - Commands::InitCollectionConfig {} => {} + Commands::InitCollectionConfig {} => { + init_config::init_collection_config() + } Commands::InitUploadConfig { assets_dir: _ } => {} Commands::InitConfig { assets_dir: _ } => {} Commands::DeployAssets { assets_dir: _ } => {} diff --git a/crates/byte_cli/src/prelude.rs b/crates/byte_cli/src/prelude.rs index ff55808..2606276 100644 --- a/crates/byte_cli/src/prelude.rs +++ b/crates/byte_cli/src/prelude.rs @@ -1,2 +1,3 @@ pub use crate::cli::{Cli, Commands}; pub use crate::consts; +pub use crate::endpoints::init_config; From 7e6f4b0eeff1a03c2a8d5736feaa0350773f6e16 Mon Sep 17 00:00:00 2001 From: Nuno Boavida <45330362+nmboavida@users.noreply.github.com> Date: Mon, 16 Jan 2023 22:35:34 +0000 Subject: [PATCH 2/3] Save state --- crates/byte_cli/src/endpoints/init_config.rs | 44 ++++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/crates/byte_cli/src/endpoints/init_config.rs b/crates/byte_cli/src/endpoints/init_config.rs index a41ed87..2e436cd 100644 --- a/crates/byte_cli/src/endpoints/init_config.rs +++ b/crates/byte_cli/src/endpoints/init_config.rs @@ -25,6 +25,7 @@ const BEHAVIOUR_OPTIONS: [&str; 2] = ["composable", "loose"]; const SUPPLY_OPTIONS: [&str; 2] = ["Unlimited", "Limited"]; const MINTING_OPTIONS: [&str; 3] = ["Launchpad", "Direct", "Airdrop"]; const ROYALTY_OPTIONS: [&str; 3] = ["Proportional", "Constant", "None"]; +const MARKET_OPTIONS: [&str; 2] = ["FixedPrice", "DutchAuction"]; pub fn get_dialoguer_theme() -> ColorfulTheme { ColorfulTheme { @@ -62,6 +63,17 @@ pub fn init_collection_config() { } }; + let address_validator = |input: &String| -> Result<(), String> { + if input.as_bytes().len() != 20 { + Err(format!( + "Couldn't parse input of '{}' to an address.", + input + )) + } else { + Ok(()) + } + }; + let number_validator = |input: &String| -> Result<(), String> { if input.parse::().is_err() { Err(format!("Couldn't parse input of '{}' to a number.", input)) @@ -236,14 +248,28 @@ pub fn init_collection_config() { .parse::() .expect("Failed to parse String into u64 - This error should not occur has input has been already validated."); - for i in [..listings] {} + let admin_address = Input::with_theme(&theme) + .with_prompt("What is the address of the Listing administrator?") + .validate_with(address_validator) + .interact() + .unwrap(); + + let receiver_address = Input::with_theme(&theme) + .with_prompt("What is the address that receives the sale proceeds?") + .validate_with(address_validator) + .interact() + .unwrap(); - // // Listings - // pub struct Listing { - // #[serde(default = "default_admin")] - // admin: String, - // #[serde(default = "default_admin")] - // receiver: String, - // markets: Vec, - // } + for i in 0..listings { + let s = format!( + "What is the market primitive to use for the sale nº {}", + i + 1 + ); + + let market_type = Select::with_theme(&theme) + .with_prompt(s) + .items(&MARKET_OPTIONS) + .interact() + .unwrap(); + } } From 671bf8e1c0957ff9709e7eca540fcee0fdcc6919 Mon Sep 17 00:00:00 2001 From: Nuno Boavida <45330362+nmboavida@users.noreply.github.com> Date: Tue, 17 Jan 2023 18:13:14 +0000 Subject: [PATCH 3/3] Finish logic --- Cargo.lock | 8 + crates/byte_cli/Cargo.toml | 3 +- crates/byte_cli/src/endpoints/init_config.rs | 169 +++++++++++++------ crates/byte_cli/src/err.rs | 13 ++ crates/byte_cli/src/lib.rs | 1 + crates/byte_cli/src/main.rs | 1 + crates/byte_cli/src/prelude.rs | 1 + 7 files changed, 139 insertions(+), 57 deletions(-) create mode 100644 crates/byte_cli/src/err.rs diff --git a/Cargo.lock b/Cargo.lock index 1f76dd4..b3dda28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,9 +123,11 @@ dependencies = [ "console", "dialoguer", "gutenberg", + "hex", "pretty_assertions", "serde", "serde_yaml", + "thiserror", "tokio", ] @@ -342,6 +344,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "indexmap" version = "1.9.2" diff --git a/crates/byte_cli/Cargo.toml b/crates/byte_cli/Cargo.toml index 583b1ea..40be027 100644 --- a/crates/byte_cli/Cargo.toml +++ b/crates/byte_cli/Cargo.toml @@ -8,11 +8,12 @@ gutenberg = { path = "../gutenberg" } dialoguer = "0.10" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.9" -# thiserror = "1.0" +thiserror = "1.0" tokio = {version = "1.24", features = ["macros", "rt-multi-thread"]} clap = {version = "4.0", features = ["derive"]} anyhow = "1.0" console = "0.15.4" +hex = "0.4" [dev-dependencies] pretty_assertions = "1.3.0" diff --git a/crates/byte_cli/src/endpoints/init_config.rs b/crates/byte_cli/src/endpoints/init_config.rs index 2e436cd..d113b4d 100644 --- a/crates/byte_cli/src/endpoints/init_config.rs +++ b/crates/byte_cli/src/endpoints/init_config.rs @@ -1,10 +1,14 @@ use crate::prelude::*; use anyhow::Result; -use clap::Parser; use console::{style, Style}; use dialoguer::theme::ColorfulTheme; use dialoguer::{Confirm, Input, MultiSelect, Select}; -use gutenberg::{models::nft, schema, types::Royalties}; +use gutenberg::{ + models::nft, + schema, + types::{Listing, Market, Royalties}, +}; +use hex; const TAG_OPTIONS: [&str; 11] = [ "Art", @@ -52,23 +56,18 @@ pub fn init_collection_config() { let string_validator = |_input: &String| -> Result<(), String> { Ok(()) }; - let _float_validator = |input: &String| -> Result<(), String> { - if !input.is_empty() && input.parse::().is_err() { - Err(format!( - "Couldn't parse price input of '{}' to a float.", - input - )) + let address_validator = |input: &String| -> Result<(), CliError> { + let hexa_str = if &input[..2] == "0x" { + &input[2..] } else { - Ok(()) - } - }; + &input + }; - let address_validator = |input: &String| -> Result<(), String> { - if input.as_bytes().len() != 20 { - Err(format!( - "Couldn't parse input of '{}' to an address.", - input - )) + let hexa = + hex::decode(hexa_str).map_err(|_| CliError::InvalidAddress)?; + + if hexa.len() != 20 { + Err(CliError::InvalidAddress) } else { Ok(()) } @@ -188,17 +187,6 @@ pub fn init_collection_config() { schema.nft.supply_policy = nft::SupplyPolicy::new_from(supply_policy, limit).unwrap(); - let mint_strategy_indices = MultiSelect::with_theme(&theme) - .with_prompt("Which minting strategies do you plan using? (use [SPACEBAR] to select options you want and hit [ENTER] when done)") - .items(&MINTING_OPTIONS) - .interact() - .unwrap(); - - let mint_strategies = map_indices(mint_strategy_indices, &MINTING_OPTIONS); - - schema.nft.mint_strategy = - nft::MintStrategy::new_from(mint_strategies).unwrap(); - let royalty_index = Select::with_theme(&theme) .with_prompt( "Which Royalty Policy do you want your Collection to have?", @@ -236,40 +224,109 @@ pub fn init_collection_config() { schema.royalties = Royalties::new_from(royalty_policy, fee).unwrap(); - let listings: u64 = Input::with_theme(&theme) - .with_prompt( - // TODO: The meaning of this questions may be ambiguous - // from the perspective of the creator - "How many Primary Market Listings do you plan on having?", - ) - .validate_with(number_validator) - .interact() - .unwrap() - .parse::() - .expect("Failed to parse String into u64 - This error should not occur has input has been already validated."); - - let admin_address = Input::with_theme(&theme) - .with_prompt("What is the address of the Listing administrator?") - .validate_with(address_validator) + let mint_strategy_indices = MultiSelect::with_theme(&theme) + .with_prompt("Which minting strategies do you plan using? (use [SPACEBAR] to select options you want and hit [ENTER] when done)") + .items(&MINTING_OPTIONS) .interact() .unwrap(); - let receiver_address = Input::with_theme(&theme) - .with_prompt("What is the address that receives the sale proceeds?") - .validate_with(address_validator) - .interact() - .unwrap(); + let mint_strategies = map_indices(mint_strategy_indices, &MINTING_OPTIONS); - for i in 0..listings { - let s = format!( - "What is the market primitive to use for the sale nº {}", - i + 1 - ); + let contains_launchpad = mint_strategies.contains(&"Launchpad".to_owned()); + + schema.nft.mint_strategy = + nft::MintStrategy::new_from(mint_strategies).unwrap(); - let market_type = Select::with_theme(&theme) - .with_prompt(s) - .items(&MARKET_OPTIONS) + if contains_launchpad { + let admin_address = Input::with_theme(&theme) + .with_prompt("What is the address of the Listing administrator?") + .validate_with(address_validator) .interact() .unwrap(); + + let receiver_address = Input::with_theme(&theme) + .with_prompt("What is the address that receives the sale proceeds?") + .validate_with(address_validator) + .interact() + .unwrap(); + + let listings: u64 = Input::with_theme(&theme) + .with_prompt( + // TODO: The meaning of this questions may be ambiguous + // from the perspective of the creator + "How many Primary Market Listings do you plan on having?", + ) + .validate_with(number_validator) + .interact() + .unwrap() + .parse::() + .expect("Failed to parse String into u64 - This error should not occur has input has been already validated."); + + for i in 0..listings { + let prompt = format!( + "What is the market primitive to use for the sale nº {}", + i + 1 + ); + + let market_index = Select::with_theme(&theme) + .with_prompt(prompt) + .items(&MARKET_OPTIONS) + .interact() + .unwrap(); + + let is_whitelisted = Confirm::with_theme(&theme) + .with_prompt("What is it a whitelisted sale?") + .interact() + .unwrap(); + + let market: Market; + + match MARKET_OPTIONS[market_index] { + "FixedPrice" => { + let price = Input::with_theme(&theme) + .with_prompt("What is the fixed price of the sale?") + .validate_with(number_validator) + .interact() + .unwrap() + .parse::() + .expect("Failed to parse String into u64 - This error should not occur has input has been already validated."); + + market = Market::FixedPrice { + token: "sui::sui::SUI".to_string(), + price, + is_whitelisted, + }; + } + "DutchAuction" => { + let reserve_price = Input::with_theme(&theme) + .with_prompt( + "What is the reserve price of the auction?", + ) + .validate_with(number_validator) + .interact() + .unwrap() + .parse::() + .expect("Failed to parse String into u64 - This error should not occur has input has been already validated."); + + market = Market::DutchAuction { + token: "sui::sui::SUI".to_string(), + reserve_price, + is_whitelisted, + }; + } + _ => { + eprintln!("TODO: This error handling"); + std::process::exit(2); + } + } + + let listing = Listing::new( + admin_address.as_str(), + receiver_address.as_str(), + market, + ); + + schema.add_listing(listing); + } } } diff --git a/crates/byte_cli/src/err.rs b/crates/byte_cli/src/err.rs new file mode 100644 index 0000000..e0c9290 --- /dev/null +++ b/crates/byte_cli/src/err.rs @@ -0,0 +1,13 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum CliError { + #[error("An IO error has occured")] + IoError(#[from] std::io::Error), + // #[error("The tag provided is not supported")] + // UnsupportedTag, + #[error("The address provided is invalid")] + InvalidAddress, + #[error("The market type provided is invalid")] + InvalidMarket, +} diff --git a/crates/byte_cli/src/lib.rs b/crates/byte_cli/src/lib.rs index c0829de..cdfaf29 100644 --- a/crates/byte_cli/src/lib.rs +++ b/crates/byte_cli/src/lib.rs @@ -1,4 +1,5 @@ pub mod cli; pub mod consts; pub mod endpoints; +pub mod err; pub mod prelude; diff --git a/crates/byte_cli/src/main.rs b/crates/byte_cli/src/main.rs index e6004f9..9abcfe2 100644 --- a/crates/byte_cli/src/main.rs +++ b/crates/byte_cli/src/main.rs @@ -1,6 +1,7 @@ pub mod cli; pub mod consts; pub mod endpoints; +pub mod err; pub mod prelude; use crate::endpoints::init_config; diff --git a/crates/byte_cli/src/prelude.rs b/crates/byte_cli/src/prelude.rs index 2606276..5eabdef 100644 --- a/crates/byte_cli/src/prelude.rs +++ b/crates/byte_cli/src/prelude.rs @@ -1,3 +1,4 @@ pub use crate::cli::{Cli, Commands}; pub use crate::consts; pub use crate::endpoints::init_config; +pub use crate::err::{self, CliError};