@clarigen/cli 1.0.0-next.21 → 1.0.0-next.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/config.ts CHANGED
@@ -3,9 +3,11 @@ import { readFile, access } from 'fs/promises';
3
3
  import { constants } from 'fs';
4
4
  import {
5
5
  ClarinetAccounts,
6
+ ClarinetConfig,
6
7
  getClarinetAccounts,
7
8
  getClarinetConfig,
8
9
  getContractsFromClarinet,
10
+ getContractsFromDeployment,
9
11
  } from './clarinet-config';
10
12
 
11
13
  export interface ConfigContract {
@@ -66,7 +68,12 @@ export async function getProjectConfig(rootPath: string): Promise<ConfigFile> {
66
68
  const clarinetPath = resolve(rootPath, configFile.clarinet);
67
69
  const clarinet = await getClarinetConfig(clarinetPath);
68
70
  const accounts = await getClarinetAccounts(clarinetPath);
69
- const contracts = getContractsFromClarinet(clarinet, accounts);
71
+ let contracts: ConfigContract[];
72
+ try {
73
+ contracts = await getContractsFromDeployment(clarinetPath);
74
+ } catch (error) {
75
+ contracts = getContractsFromClarinet(clarinet, accounts);
76
+ }
70
77
  const contractsDir = relative(
71
78
  process.cwd(),
72
79
  join(configFile.clarinet, 'contracts')
@@ -0,0 +1,65 @@
1
+ import { mkdir } from 'fs/promises';
2
+ import { relative, resolve } from 'path';
3
+ import { SessionContract } from './deno-run';
4
+ import { generateMarkdownDoc } from './docs';
5
+ import {
6
+ generateTypesFile,
7
+ generateIndexFile,
8
+ generateInterfaceFile,
9
+ } from './generate/files';
10
+ import { ContractMeta } from './utils';
11
+ import { writeFile } from './writer';
12
+
13
+ export const generateFilesForContractWithSession = async ({
14
+ outputFolder,
15
+ sessionContract,
16
+ dirName,
17
+ docsPath,
18
+ contractFile,
19
+ }: {
20
+ outputFolder: string;
21
+ sessionContract: SessionContract;
22
+ dirName?: string;
23
+ docsPath?: string;
24
+ contractFile: string;
25
+ }): Promise<ContractMeta> => {
26
+ const contractIdentifier = sessionContract.contract_id;
27
+ const [contractAddress, contractName] = contractIdentifier.split('.');
28
+
29
+ const abi = sessionContract.contract_interface;
30
+ const variables = [];
31
+
32
+ const typesFile = generateTypesFile(abi, contractName);
33
+ const indexFile = generateIndexFile({
34
+ contractFile: relative(process.cwd(), contractFile),
35
+ contractAddress: contractAddress,
36
+ contractName,
37
+ });
38
+ const abiFile = generateInterfaceFile({ contractName, abi });
39
+
40
+ if (typeof docsPath !== 'undefined') {
41
+ await generateMarkdownDoc({
42
+ contractFile,
43
+ contractName,
44
+ abi,
45
+ docsPath,
46
+ dirName,
47
+ });
48
+ }
49
+
50
+ const outputPath = resolve(outputFolder, dirName || '.', contractName);
51
+ await mkdir(outputPath, { recursive: true });
52
+
53
+ await writeFile(resolve(outputPath, 'abi.ts'), abiFile);
54
+ await writeFile(resolve(outputPath, 'index.ts'), indexFile);
55
+ await writeFile(resolve(outputPath, 'types.ts'), typesFile);
56
+
57
+ return {
58
+ abi,
59
+ contractFile,
60
+ contractName,
61
+ dirName,
62
+ contractAddress,
63
+ variables,
64
+ };
65
+ };
@@ -0,0 +1,35 @@
1
+ import { exec as _exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import { homedir } from 'os';
4
+ import { resolve } from 'path';
5
+ import { ClarityAbi } from '@clarigen/core';
6
+
7
+ const exec = promisify(_exec);
8
+
9
+ export interface SessionContract {
10
+ contract_id: string;
11
+ contract_interface: ClarityAbi;
12
+ source: string;
13
+ dependencies: string[];
14
+ }
15
+
16
+ export interface Session {
17
+ session_id: number;
18
+ accounts: any[];
19
+ contracts: SessionContract[];
20
+ }
21
+
22
+ export async function getClarinetSession(cwd?: string): Promise<Session> {
23
+ const scriptPath =
24
+ 'https://raw.githubusercontent.com/mechanismHQ/clarigen-deno/main/src/cli/print.ts';
25
+ const command = `clarinet run ${scriptPath}`;
26
+ try {
27
+ const result = await exec(command, { cwd });
28
+ const sessionJSON = result.stdout.split('\n')[1];
29
+ const session = JSON.parse(sessionJSON);
30
+ return session as Session;
31
+ } catch (error) {
32
+ console.error(`Error getting clarinet session`);
33
+ throw error;
34
+ }
35
+ }
@@ -0,0 +1,45 @@
1
+ import { load } from 'js-yaml';
2
+ import { mkdir, readFile } from 'fs/promises';
3
+ import { resolve } from 'path';
4
+ import { existsSync } from 'fs';
5
+ import type { ConfigFile } from '../config';
6
+ import { writeFile } from '../writer';
7
+ import { DeploymentPlan } from '@clarigen/core';
8
+
9
+ export async function parseDeployment(path: string): Promise<DeploymentPlan> {
10
+ const contents = await readFile(path, { encoding: 'utf-8' });
11
+ const parsed = load(contents);
12
+ return parsed as DeploymentPlan;
13
+ }
14
+
15
+ export async function generateDeployment(network: string, config: ConfigFile) {
16
+ const file = `default.${network}-plan.yaml`;
17
+ const deploymentPath = resolve(
18
+ process.cwd(),
19
+ config.clarinet,
20
+ 'deployments',
21
+ file
22
+ );
23
+ if (existsSync(deploymentPath)) {
24
+ const plan = await parseDeployment(deploymentPath);
25
+ const varName = `${network}Deployment`;
26
+ const contents = `export const ${varName} = ${JSON.stringify(
27
+ plan
28
+ )} as const;
29
+ `;
30
+ const outputFile = resolve(
31
+ config.outputDir,
32
+ 'deployments',
33
+ `${network}.ts`
34
+ );
35
+ await writeFile(outputFile, contents);
36
+ }
37
+ }
38
+
39
+ export async function generateDeployments(config: ConfigFile) {
40
+ const networks = ['devnet', 'simnet', 'testnet', 'mainnet'];
41
+ const folder = resolve(process.cwd(), config.outputDir, 'deployments');
42
+ await mkdir(folder, { recursive: true });
43
+ const generates = networks.map((n) => generateDeployment(n, config));
44
+ await Promise.all(generates);
45
+ }
@@ -107,7 +107,7 @@ export const accounts = {
107
107
  const contractInfo = `${contractVar}Info`;
108
108
  const contractInterface = `${toCamelCase(contractName, true)}Contract`;
109
109
  const dirName = dirname(contract.file);
110
- const importPath = `'./${join(dirName || '.', contractName)}'`;
110
+ const importPath = `'./${contractName}'`;
111
111
 
112
112
  const _import = `import { ${contractInfo} } from ${importPath};`;
113
113
  imports.push(_import);
package/src/utils.ts CHANGED
@@ -18,6 +18,9 @@ import { generateContractMeta, generateSingleFile } from './generate/single';
18
18
  import { writeFile } from './writer';
19
19
  import { getVariables, TypedAbiVariable } from './generate/vars';
20
20
  import { ClarityAbiVariable } from 'micro-stacks/clarity';
21
+ import { generateDeployments } from './generate/deployment';
22
+ import { getClarinetSession } from './deno-run';
23
+ import { generateFilesForContractWithSession } from './contract';
21
24
 
22
25
  export interface ContractMeta {
23
26
  abi: ClarityAbi;
@@ -100,18 +103,27 @@ export const generateProject = async (projectPath: string) => {
100
103
  const outputFolder = resolve(projectPath, outputDir);
101
104
  const provider = await createClarityBin();
102
105
  const metas: ContractMeta[] = [];
106
+ const session = await getClarinetSession(
107
+ resolve(projectPath, configFile.clarinet)
108
+ );
103
109
  // this needs to be serial
104
- for (const contract of contracts) {
105
- const contractFile = resolve(projectPath, contractsDir, contract.file);
106
- const dirName = dirname(contract.file);
107
- const meta = await generateFilesForContract({
108
- contractFile,
109
- outputFolder: outputFolder,
110
- provider,
111
- contractAddress: contract.address,
112
- dirName,
113
- contractName: contract.name,
110
+ for (const contract of session.contracts) {
111
+ const configContract = contracts.find(
112
+ (c) => c.name === contract.contract_id.split('.')[1]
113
+ );
114
+ if (typeof configContract === 'undefined') {
115
+ throw new Error(`No config contract found for ${contract.contract_id}`);
116
+ }
117
+ const contractFile = resolve(
118
+ projectPath,
119
+ configFile.clarinet,
120
+ configContract.file
121
+ );
122
+ const meta = await generateFilesForContractWithSession({
123
+ sessionContract: contract,
124
+ outputFolder,
114
125
  docsPath: configFile.docs,
126
+ contractFile,
115
127
  });
116
128
  metas.push(meta);
117
129
  }
@@ -125,4 +137,5 @@ export const generateProject = async (projectPath: string) => {
125
137
  const singleFile = await generateSingleFile(configFile, metas);
126
138
  const singlePath = resolve(outputFolder, 'single.ts');
127
139
  await writeFile(singlePath, singleFile);
140
+ await generateDeployments(configFile);
128
141
  };