stellar_scaffold_cli/commands/
init.rs1use clap::Parser;
2use degit::degit;
3use std::fs::{metadata, read_dir, remove_dir_all};
4use std::path::PathBuf;
5use std::{env, io};
6
7use super::generate;
8use stellar_cli::{commands::global, print::Print};
9
10const FRONTEND_TEMPLATE: &str = "https://github.com/AhaLabs/scaffold-stellar-frontend";
11
12#[derive(Parser, Debug, Clone)]
14pub struct Cmd {
15 pub project_path: PathBuf,
17}
18
19#[derive(thiserror::Error, Debug)]
21pub enum Error {
22 #[error("Failed to clone template: {0}")]
23 DegitError(String),
24 #[error("Project path contains invalid UTF-8 characters and cannot be converted to a string")]
25 InvalidProjectPathEncoding,
26 #[error("IO error: {0}")]
27 IoError(#[from] io::Error),
28 #[error(transparent)]
29 GenerateError(#[from] generate::contract::Error),
30}
31
32impl Cmd {
33 pub async fn run(&self, global_args: &global::Args) -> Result<(), Error> {
42 let printer = Print::new(global_args.quiet);
43
44 printer.infoln(format!(
45 "Creating new Stellar project in {:?}",
46 self.project_path
47 ));
48
49 let project_str = self
50 .project_path
51 .to_str()
52 .ok_or(Error::InvalidProjectPathEncoding)?;
53 degit(FRONTEND_TEMPLATE, project_str);
54
55 if metadata(&self.project_path).is_err() || read_dir(&self.project_path)?.next().is_none() {
56 return Err(Error::DegitError(format!(
57 "Failed to clone template into {project_str}: directory is empty or missing",
58 )));
59 }
60
61 self.update_fungible_token_example(global_args).await?;
62
63 printer.checkln(format!("Project successfully created at {project_str}"));
64 Ok(())
65 }
66
67 async fn update_fungible_token_example(&self, global_args: &global::Args) -> Result<(), Error> {
68 let original_dir = env::current_dir()?;
69 env::set_current_dir(&self.project_path)?;
70
71 let contracts_path = self.project_path.join("contracts");
72 let fungible_token_path = contracts_path.join("fungible-token-interface");
73
74 if fungible_token_path.exists() {
75 remove_dir_all(&fungible_token_path)?;
76 }
77
78 let mut quiet_global_args = global_args.clone();
79 quiet_global_args.quiet = true;
80
81 generate::contract::Cmd {
82 from: Some("fungible-token-interface".to_owned()),
83 ls: false,
84 from_wizard: false,
85 output: Some(
86 contracts_path
87 .join("fungible-token-interface")
88 .to_string_lossy()
89 .into_owned(),
90 ),
91 }
92 .run(&quiet_global_args)
93 .await?;
94 env::set_current_dir(original_dir)?;
95 Ok(())
96 }
97}