template.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. use crate::config::ProgramWorkspace;
  2. use crate::VERSION;
  3. use anchor_syn::idl::Idl;
  4. use anyhow::Result;
  5. use heck::{ToLowerCamelCase, ToSnakeCase, ToUpperCamelCase};
  6. use solana_sdk::pubkey::Pubkey;
  7. use std::fmt::Write;
  8. pub fn default_program_id() -> Pubkey {
  9. "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
  10. .parse()
  11. .unwrap()
  12. }
  13. pub fn virtual_manifest() -> &'static str {
  14. r#"[workspace]
  15. members = [
  16. "programs/*"
  17. ]
  18. [profile.release]
  19. overflow-checks = true
  20. lto = "fat"
  21. codegen-units = 1
  22. [profile.release.build-override]
  23. opt-level = 3
  24. incremental = false
  25. codegen-units = 1
  26. "#
  27. }
  28. pub fn credentials(token: &str) -> String {
  29. format!(
  30. r#"[registry]
  31. token = "{}"
  32. "#,
  33. token
  34. )
  35. }
  36. pub fn idl_ts(idl: &Idl) -> Result<String> {
  37. let mut idl = idl.clone();
  38. for acc in idl.accounts.iter_mut() {
  39. acc.name = acc.name.to_lower_camel_case();
  40. }
  41. let idl_json = serde_json::to_string_pretty(&idl)?;
  42. Ok(format!(
  43. r#"export type {} = {};
  44. export const IDL: {} = {};
  45. "#,
  46. idl.name.to_upper_camel_case(),
  47. idl_json,
  48. idl.name.to_upper_camel_case(),
  49. idl_json
  50. ))
  51. }
  52. pub fn cargo_toml(name: &str) -> String {
  53. format!(
  54. r#"[package]
  55. name = "{0}"
  56. version = "0.1.0"
  57. description = "Created with Anchor"
  58. edition = "2021"
  59. [lib]
  60. crate-type = ["cdylib", "lib"]
  61. name = "{1}"
  62. [features]
  63. no-entrypoint = []
  64. no-idl = []
  65. no-log-ix-name = []
  66. cpi = ["no-entrypoint"]
  67. default = []
  68. [dependencies]
  69. anchor-lang = "{2}"
  70. "#,
  71. name,
  72. name.to_snake_case(),
  73. VERSION,
  74. )
  75. }
  76. pub fn deploy_js_script_host(cluster_url: &str, script_path: &str) -> String {
  77. format!(
  78. r#"
  79. const anchor = require('@coral-xyz/anchor');
  80. // Deploy script defined by the user.
  81. const userScript = require("{0}");
  82. async function main() {{
  83. const url = "{1}";
  84. const preflightCommitment = 'recent';
  85. const connection = new anchor.web3.Connection(url, preflightCommitment);
  86. const wallet = anchor.Wallet.local();
  87. const provider = new anchor.AnchorProvider(connection, wallet, {{
  88. preflightCommitment,
  89. commitment: 'recent',
  90. }});
  91. // Run the user's deploy script.
  92. userScript(provider);
  93. }}
  94. main();
  95. "#,
  96. script_path, cluster_url,
  97. )
  98. }
  99. pub fn deploy_ts_script_host(cluster_url: &str, script_path: &str) -> String {
  100. format!(
  101. r#"import * as anchor from '@coral-xyz/anchor';
  102. // Deploy script defined by the user.
  103. const userScript = require("{0}");
  104. async function main() {{
  105. const url = "{1}";
  106. const preflightCommitment = 'recent';
  107. const connection = new anchor.web3.Connection(url, preflightCommitment);
  108. const wallet = anchor.Wallet.local();
  109. const provider = new anchor.AnchorProvider(connection, wallet, {{
  110. preflightCommitment,
  111. commitment: 'recent',
  112. }});
  113. // Run the user's deploy script.
  114. userScript(provider);
  115. }}
  116. main();
  117. "#,
  118. script_path, cluster_url,
  119. )
  120. }
  121. pub fn deploy_script() -> &'static str {
  122. r#"// Migrations are an early feature. Currently, they're nothing more than this
  123. // single deploy script that's invoked from the CLI, injecting a provider
  124. // configured from the workspace's Anchor.toml.
  125. const anchor = require("@coral-xyz/anchor");
  126. module.exports = async function (provider) {
  127. // Configure client to use the provider.
  128. anchor.setProvider(provider);
  129. // Add your deploy script here.
  130. };
  131. "#
  132. }
  133. pub fn ts_deploy_script() -> &'static str {
  134. r#"// Migrations are an early feature. Currently, they're nothing more than this
  135. // single deploy script that's invoked from the CLI, injecting a provider
  136. // configured from the workspace's Anchor.toml.
  137. const anchor = require("@coral-xyz/anchor");
  138. module.exports = async function (provider) {
  139. // Configure client to use the provider.
  140. anchor.setProvider(provider);
  141. // Add your deploy script here.
  142. };
  143. "#
  144. }
  145. pub fn xargo_toml() -> &'static str {
  146. r#"[target.bpfel-unknown-unknown.dependencies.std]
  147. features = []
  148. "#
  149. }
  150. pub fn lib_rs(name: &str) -> String {
  151. format!(
  152. r#"use anchor_lang::prelude::*;
  153. declare_id!("{}");
  154. #[program]
  155. pub mod {} {{
  156. use super::*;
  157. pub fn initialize(ctx: Context<Initialize>) -> Result<()> {{
  158. Ok(())
  159. }}
  160. }}
  161. #[derive(Accounts)]
  162. pub struct Initialize {{}}
  163. "#,
  164. default_program_id(),
  165. name.to_snake_case(),
  166. )
  167. }
  168. pub fn mocha(name: &str) -> String {
  169. format!(
  170. r#"const anchor = require("@coral-xyz/anchor");
  171. describe("{}", () => {{
  172. // Configure the client to use the local cluster.
  173. anchor.setProvider(anchor.AnchorProvider.env());
  174. it("Is initialized!", async () => {{
  175. // Add your test here.
  176. const program = anchor.workspace.{};
  177. const tx = await program.methods.initialize().rpc();
  178. console.log("Your transaction signature", tx);
  179. }});
  180. }});
  181. "#,
  182. name,
  183. name.to_upper_camel_case(),
  184. )
  185. }
  186. pub fn jest(name: &str) -> String {
  187. format!(
  188. r#"const anchor = require("@coral-xyz/anchor");
  189. describe("{}", () => {{
  190. // Configure the client to use the local cluster.
  191. anchor.setProvider(anchor.AnchorProvider.env());
  192. it("Is initialized!", async () => {{
  193. // Add your test here.
  194. const program = anchor.workspace.{};
  195. const tx = await program.methods.initialize().rpc();
  196. console.log("Your transaction signature", tx);
  197. }});
  198. }});
  199. "#,
  200. name,
  201. name.to_upper_camel_case(),
  202. )
  203. }
  204. pub fn package_json(jest: bool) -> String {
  205. if jest {
  206. format!(
  207. r#"{{
  208. "scripts": {{
  209. "lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w",
  210. "lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check"
  211. }},
  212. "dependencies": {{
  213. "@coral-xyz/anchor": "^{0}"
  214. }},
  215. "devDependencies": {{
  216. "jest": "^29.0.3",
  217. "prettier": "^2.6.2"
  218. }}
  219. }}
  220. "#,
  221. VERSION
  222. )
  223. } else {
  224. format!(
  225. r#"{{
  226. "scripts": {{
  227. "lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w",
  228. "lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check"
  229. }},
  230. "dependencies": {{
  231. "@coral-xyz/anchor": "^{0}"
  232. }},
  233. "devDependencies": {{
  234. "chai": "^4.3.4",
  235. "mocha": "^9.0.3",
  236. "prettier": "^2.6.2"
  237. }}
  238. }}
  239. "#,
  240. VERSION
  241. )
  242. }
  243. }
  244. pub fn ts_package_json(jest: bool) -> String {
  245. if jest {
  246. format!(
  247. r#"{{
  248. "scripts": {{
  249. "lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w",
  250. "lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check"
  251. }},
  252. "dependencies": {{
  253. "@coral-xyz/anchor": "^{0}"
  254. }},
  255. "devDependencies": {{
  256. "@types/bn.js": "^5.1.0",
  257. "@types/jest": "^29.0.3",
  258. "jest": "^29.0.3",
  259. "prettier": "^2.6.2",
  260. "ts-jest": "^29.0.2",
  261. "typescript": "^4.3.5"
  262. }}
  263. }}
  264. "#,
  265. VERSION
  266. )
  267. } else {
  268. format!(
  269. r#"{{
  270. "scripts": {{
  271. "lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w",
  272. "lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check"
  273. }},
  274. "dependencies": {{
  275. "@coral-xyz/anchor": "^{0}"
  276. }},
  277. "devDependencies": {{
  278. "chai": "^4.3.4",
  279. "mocha": "^9.0.3",
  280. "ts-mocha": "^10.0.0",
  281. "@types/bn.js": "^5.1.0",
  282. "@types/chai": "^4.3.0",
  283. "@types/mocha": "^9.0.0",
  284. "typescript": "^4.3.5",
  285. "prettier": "^2.6.2"
  286. }}
  287. }}
  288. "#,
  289. VERSION
  290. )
  291. }
  292. }
  293. pub fn ts_mocha(name: &str) -> String {
  294. format!(
  295. r#"import * as anchor from "@coral-xyz/anchor";
  296. import {{ Program }} from "@coral-xyz/anchor";
  297. import {{ {} }} from "../target/types/{}";
  298. describe("{}", () => {{
  299. // Configure the client to use the local cluster.
  300. anchor.setProvider(anchor.AnchorProvider.env());
  301. const program = anchor.workspace.{} as Program<{}>;
  302. it("Is initialized!", async () => {{
  303. // Add your test here.
  304. const tx = await program.methods.initialize().rpc();
  305. console.log("Your transaction signature", tx);
  306. }});
  307. }});
  308. "#,
  309. name.to_upper_camel_case(),
  310. name.to_snake_case(),
  311. name,
  312. name.to_upper_camel_case(),
  313. name.to_upper_camel_case(),
  314. )
  315. }
  316. pub fn ts_jest(name: &str) -> String {
  317. format!(
  318. r#"import * as anchor from "@coral-xyz/anchor";
  319. import {{ Program }} from "@coral-xyz/anchor";
  320. import {{ {} }} from "../target/types/{}";
  321. describe("{}", () => {{
  322. // Configure the client to use the local cluster.
  323. anchor.setProvider(anchor.AnchorProvider.env());
  324. const program = anchor.workspace.{} as Program<{}>;
  325. it("Is initialized!", async () => {{
  326. // Add your test here.
  327. const tx = await program.methods.initialize().rpc();
  328. console.log("Your transaction signature", tx);
  329. }});
  330. }});
  331. "#,
  332. name.to_upper_camel_case(),
  333. name.to_snake_case(),
  334. name,
  335. name.to_upper_camel_case(),
  336. name.to_upper_camel_case(),
  337. )
  338. }
  339. pub fn ts_config(jest: bool) -> &'static str {
  340. if jest {
  341. r#"{
  342. "compilerOptions": {
  343. "types": ["jest"],
  344. "typeRoots": ["./node_modules/@types"],
  345. "lib": ["es2015"],
  346. "module": "commonjs",
  347. "target": "es6",
  348. "esModuleInterop": true
  349. }
  350. }
  351. "#
  352. } else {
  353. r#"{
  354. "compilerOptions": {
  355. "types": ["mocha", "chai"],
  356. "typeRoots": ["./node_modules/@types"],
  357. "lib": ["es2015"],
  358. "module": "commonjs",
  359. "target": "es6",
  360. "esModuleInterop": true
  361. }
  362. }
  363. "#
  364. }
  365. }
  366. pub fn git_ignore() -> &'static str {
  367. r#"
  368. .anchor
  369. .DS_Store
  370. target
  371. **/*.rs.bk
  372. node_modules
  373. test-ledger
  374. "#
  375. }
  376. pub fn prettier_ignore() -> &'static str {
  377. r#"
  378. .anchor
  379. .DS_Store
  380. target
  381. node_modules
  382. dist
  383. build
  384. test-ledger
  385. "#
  386. }
  387. pub fn node_shell(
  388. cluster_url: &str,
  389. wallet_path: &str,
  390. programs: Vec<ProgramWorkspace>,
  391. ) -> Result<String> {
  392. let mut eval_string = format!(
  393. r#"
  394. const anchor = require('@coral-xyz/anchor');
  395. const web3 = anchor.web3;
  396. const PublicKey = anchor.web3.PublicKey;
  397. const Keypair = anchor.web3.Keypair;
  398. const __wallet = new anchor.Wallet(
  399. Keypair.fromSecretKey(
  400. Buffer.from(
  401. JSON.parse(
  402. require('fs').readFileSync(
  403. "{}",
  404. {{
  405. encoding: "utf-8",
  406. }},
  407. ),
  408. ),
  409. ),
  410. ),
  411. );
  412. const __connection = new web3.Connection("{}", "processed");
  413. const provider = new anchor.AnchorProvider(__connection, __wallet, {{
  414. commitment: "processed",
  415. preflightcommitment: "processed",
  416. }});
  417. anchor.setProvider(provider);
  418. "#,
  419. wallet_path, cluster_url,
  420. );
  421. for program in programs {
  422. write!(
  423. &mut eval_string,
  424. r#"
  425. anchor.workspace.{} = new anchor.Program({}, new PublicKey("{}"), provider);
  426. "#,
  427. program.name.to_upper_camel_case(),
  428. serde_json::to_string(&program.idl)?,
  429. program.program_id
  430. )?;
  431. }
  432. Ok(eval_string)
  433. }