use std::fs;
use tracing::info;
use crate::compile::ContractWithDeps;
pub fn generate_deployable(contract: &ContractWithDeps) -> eyre::Result<()> {
let mut content = String::new();
content.push_str("//! Auto-generated based on Cargo.toml dependencies\n");
content
.push_str("//! This file provides Deployable implementations for contract dependencies\n");
content.push_str("//! TODO (phase-2): rather than using `fn deploy(args: Args)`, figure out the constructor selector from the contract dependency\n\n");
content.push_str("use alloy_core::primitives::{Address, Bytes};\n");
content.push_str("use eth_riscv_runtime::{create::Deployable, InitInterface, ReadOnly};\n");
content.push_str("use core::include_bytes;\n\n");
for dep in &contract.deps {
let interface_name = format!("I{}", dep.name.ident);
content.push_str(&format!("use {}::{};\n", dep.name.package, interface_name));
}
content.push('\n');
for dep in &contract.deps {
let const_name = dep.name.ident.to_uppercase();
content.push_str(&format!(
"const {}_BYTECODE: &'static [u8] = include_bytes!(\"../out/{}.bin\");\n",
const_name, dep.name.package
));
}
content.push('\n');
for dep in &contract.deps {
let interface_name = format!("I{}", dep.name.ident);
let const_name = dep.name.ident.to_uppercase();
content.push_str(&format!("pub struct {};\n\n", dep.name.ident));
content.push_str(&format!("impl Deployable for {} {{\n", dep.name.ident));
content.push_str(&format!(
" type Interface = {}<ReadOnly>;\n\n",
interface_name
));
content.push_str(" fn __runtime() -> &'static [u8] {\n");
content.push_str(&format!(" {}_BYTECODE\n", const_name));
content.push_str(" }\n");
content.push_str("}\n\n");
}
let output_path = contract.path.join("src").join("deployable.rs");
fs::write(&output_path, content)?;
info!(
"Generated {:?} for contract: {}",
output_path, contract.name.ident
);
Ok(())
}