gramr 0.0.1

⚔️ A blazing-fast library for scaffolding smart contracts
Documentation
use crate::error::{GramrError, Result};
use crate::foundry::FoundryProject;
use colored::*;
use std::fs;

pub struct ScriptGenerator {
    project: FoundryProject,
    script_name: String,
    pragma: String,
    license: String,
}

impl ScriptGenerator {
    pub fn new(
        project: FoundryProject,
        script_name: String,
        pragma: String,
        license: String,
    ) -> Self {
        Self {
            project,
            script_name,
            pragma,
            license,
        }
    }

    pub fn generate(&self) -> Result<()> {
        self.validate_name()?;
        self.project.ensure_directories()?;
        self.create_script_file()?;
        self.print_success();
        Ok(())
    }

    fn validate_name(&self) -> Result<()> {
        if self.script_name.is_empty() {
            return Err(GramrError::InvalidContractName(
                "Script name cannot be empty".to_string(),
            ));
        }

        if !self.script_name.chars().next().unwrap().is_alphabetic() {
            return Err(GramrError::InvalidContractName(
                "Script name must start with a letter".to_string(),
            ));
        }

        if !self
            .script_name
            .chars()
            .all(|c| c.is_alphanumeric() || c == '_')
        {
            return Err(GramrError::InvalidContractName(
                "Script name can only contain letters, numbers, and underscores".to_string(),
            ));
        }

        Ok(())
    }

    fn create_script_file(&self) -> Result<()> {
        let file_path = self
            .project
            .script_dir
            .join(format!("{}.s.sol", self.script_name));

        if file_path.exists() {
            return Err(GramrError::FileExists(file_path.display().to_string()));
        }

        let content = self.generate_script_content();
        fs::write(&file_path, content)?;

        println!("{} Created script: {}", "".green(), file_path.display());
        Ok(())
    }

    fn generate_script_content(&self) -> String {
        format!(
            r#"// SPDX-License-Identifier: {}
pragma solidity ^{};

import "forge-std/Script.sol";

contract {} is Script {{
    function setUp() public {{}}

    function run() public {{
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
        vm.startBroadcast(deployerPrivateKey);

        // Deploy contracts here

        vm.stopBroadcast();
    }}
}}"#,
            self.license, self.pragma, self.script_name
        )
    }

    fn print_success(&self) {
        println!("\n{} Script generation complete!", "🎉".green());
        println!("\n{}", "Next steps:".bold());
        println!("  1. Add your deployment logic to the run() function");
        println!("  2. Set the PRIVATE_KEY environment variable");
        println!(
            "  3. Run {} to execute",
            format!("forge script script/{}.s.sol", self.script_name).cyan()
        );
    }
}