1use {
2 crate::{error::CliResult, IdlCommand},
3 quasar_idl::{codegen, parser},
4 std::path::{Path, PathBuf},
5};
6
7pub fn generate(crate_path: &Path, generate_typescript: bool) -> CliResult {
15 let parsed = parser::parse_program(crate_path);
17
18 let client_code = codegen::rust::generate_client(&parsed);
20 let client_cargo_toml = codegen::rust::generate_cargo_toml(&parsed.crate_name, &parsed.version);
21
22 let idl = parser::build_idl(parsed);
24
25 let idl_dir = PathBuf::from("target").join("idl");
27 std::fs::create_dir_all(&idl_dir)?;
28
29 let idl_path = idl_dir.join(format!("{}.idl.json", idl.metadata.name));
30 let json = serde_json::to_string_pretty(&idl)
31 .map_err(|e| anyhow::anyhow!("failed to serialize IDL: {e}"))?;
32 std::fs::write(&idl_path, &json)?;
33
34 if generate_typescript {
35 let ts_code = codegen::typescript::generate_ts_client(&idl);
36 let ts_kit_code = codegen::typescript::generate_ts_client_kit(&idl);
37
38 let ts_dir = PathBuf::from("target")
40 .join("client")
41 .join("typescript")
42 .join(&idl.metadata.name);
43 std::fs::create_dir_all(&ts_dir)?;
44 std::fs::write(ts_dir.join("web3.ts"), &ts_code)?;
45 std::fs::write(ts_dir.join("kit.ts"), &ts_kit_code)?;
46
47 let needs_codecs =
49 !idl.types.is_empty() || idl.instructions.iter().any(|ix| !ix.args.is_empty());
50 let codecs_dep = if needs_codecs {
51 "\n \"@solana/codecs\": \"^6.2.0\","
52 } else {
53 ""
54 };
55 let ts_package_json = format!(
56 r#"{{
57 "name": "{crate_name}-client",
58 "version": "{version}",
59 "private": true,
60 "exports": {{
61 "./web3.js": "./web3.ts",
62 "./kit": "./kit.ts"
63 }},
64 "dependencies": {{{codecs_dep}
65 "@solana/kit": "^6.0.0",
66 "@solana/web3.js": "github:blueshift-gg/web3.js#v2"
67 }}
68}}
69"#,
70 crate_name = idl.metadata.crate_name,
71 version = idl.metadata.version,
72 );
73 std::fs::write(ts_dir.join("package.json"), &ts_package_json)?;
74 }
75
76 let crate_name = &idl.metadata.crate_name;
78 let client_dir = PathBuf::from("target")
79 .join("client")
80 .join("rust")
81 .join(format!("{}-client", crate_name));
82 let client_src_dir = client_dir.join("src");
83 std::fs::create_dir_all(&client_src_dir)?;
84
85 std::fs::write(client_dir.join("Cargo.toml"), &client_cargo_toml)?;
86 std::fs::write(client_src_dir.join("lib.rs"), &client_code)?;
87
88 Ok(())
89}
90
91pub fn run(command: IdlCommand) -> CliResult {
92 let crate_path = &command.crate_path;
93
94 if !crate_path.exists() {
95 eprintln!("Error: path does not exist: {}", crate_path.display());
96 std::process::exit(1);
97 }
98
99 generate(crate_path, true)?;
100 println!(" {}", crate::style::success("IDL generated"));
101 Ok(())
102}