@clarigen/cli 1.0.0-next.16 → 1.0.0-next.19
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/dist/abi-types.ts.txt +119 -0
- package/dist/commands/index.js +741 -62
- package/dist/index.js +810 -61
- package/package.json +8 -6
- package/src/clarinet-config.ts +6 -0
- package/src/generate/declaration.ts +2 -2
- package/src/generate/files.ts +1 -1
- package/src/generate/single.ts +134 -0
- package/src/generate/vars.ts +82 -0
- package/src/utils.ts +43 -7
- package/src/writer.ts +39 -0
- package/dist/commands/index.d.ts +0 -16
- package/dist/commands/index.mjs +0 -78
- package/dist/index.d.ts +0 -63
- package/dist/index.mjs +0 -78
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@clarigen/cli",
|
|
3
3
|
"description": "A CLI for generating a Typescript interface for a Clarity contract.",
|
|
4
4
|
"author": "Hank Stoever",
|
|
5
|
-
"version": "1.0.0-next.
|
|
5
|
+
"version": "1.0.0-next.19",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"main": "./dist/index.js",
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"lint": "eslint \"src/**/*.{ts,tsx}\" && prettier --check src/**/*.ts",
|
|
25
25
|
"typecheck": "tsc --noEmit -p tsconfig-test.json",
|
|
26
26
|
"prepublishOnly": "yarn build",
|
|
27
|
-
"demo": "yarn build && node bin/run"
|
|
27
|
+
"demo": "yarn build && node bin/run",
|
|
28
|
+
"publish:dev": "yalc publish --push"
|
|
28
29
|
},
|
|
29
30
|
"bin": {
|
|
30
31
|
"clarigen": "./bin/run"
|
|
@@ -49,9 +50,9 @@
|
|
|
49
50
|
"ts-node": "^9.1.1"
|
|
50
51
|
},
|
|
51
52
|
"dependencies": {
|
|
52
|
-
"@clarigen/claridocs": "1.0.0-next.
|
|
53
|
-
"@clarigen/core": "1.0.0-next.
|
|
54
|
-
"@clarigen/native-bin": "1.0.0-next.
|
|
53
|
+
"@clarigen/claridocs": "1.0.0-next.19",
|
|
54
|
+
"@clarigen/core": "1.0.0-next.19",
|
|
55
|
+
"@clarigen/native-bin": "1.0.0-next.19",
|
|
55
56
|
"@ltd/j-toml": "1.12.2",
|
|
56
57
|
"@oclif/command": "^1.8.0",
|
|
57
58
|
"@oclif/config": "^1.17.0",
|
|
@@ -60,11 +61,12 @@
|
|
|
60
61
|
"chokidar": "3.5.1",
|
|
61
62
|
"micro-stacks": "^0.2.0",
|
|
62
63
|
"ora": "5.4.0",
|
|
64
|
+
"prettier": "2.6.2",
|
|
63
65
|
"reserved-words": "0.1.2",
|
|
64
66
|
"toposort": "2.0.2"
|
|
65
67
|
},
|
|
66
68
|
"publishConfig": {
|
|
67
69
|
"access": "public"
|
|
68
70
|
},
|
|
69
|
-
"gitHead": "
|
|
71
|
+
"gitHead": "d6b6fc199e367698d566f38ee3343b04a418c829"
|
|
70
72
|
}
|
package/src/clarinet-config.ts
CHANGED
|
@@ -48,6 +48,12 @@ export interface ClarinetConfig {
|
|
|
48
48
|
contracts: ClarinetContracts;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
export const CLARINET_SETTINGS = [
|
|
52
|
+
'Devnet.toml',
|
|
53
|
+
'Testnet.toml',
|
|
54
|
+
'Mainnet.toml',
|
|
55
|
+
];
|
|
56
|
+
|
|
51
57
|
export async function getClarinetConfig(folder: string) {
|
|
52
58
|
const baseConfigPath = resolve(folder, 'Clarinet.toml');
|
|
53
59
|
const configContents = await readFile(baseConfigPath, { encoding: 'utf-8' });
|
|
@@ -41,7 +41,7 @@ export const jsTypeFromAbiType = (
|
|
|
41
41
|
} else if (isClarityAbiResponse(val)) {
|
|
42
42
|
const ok: any = jsTypeFromAbiType(val.response.ok);
|
|
43
43
|
const err: any = jsTypeFromAbiType(val.response.error);
|
|
44
|
-
return `
|
|
44
|
+
return `Response<${ok}, ${err}>`;
|
|
45
45
|
} else if (isClarityAbiOptional(val)) {
|
|
46
46
|
const innerType = jsTypeFromAbiType(val.optional);
|
|
47
47
|
return `${innerType} | null`;
|
|
@@ -69,7 +69,7 @@ export const jsTypeFromAbiType = (
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
// Check if it's a reserved word, and then camelCase
|
|
72
|
-
function getArgName(name: string) {
|
|
72
|
+
export function getArgName(name: string) {
|
|
73
73
|
const camel = toCamelCase(name);
|
|
74
74
|
const prefix = check(camel, 6) ? '_' : '';
|
|
75
75
|
return `${prefix}${camel}`;
|
package/src/generate/files.ts
CHANGED
|
@@ -115,7 +115,7 @@ export const ${varName}Info: Contract<${contractType}> = {
|
|
|
115
115
|
export const generateTypesFile = (abi: ClarityAbi, contractName: string) => {
|
|
116
116
|
const name = toCamelCase(contractName, true);
|
|
117
117
|
const typings = makePureTypes(abi);
|
|
118
|
-
const fileContents = `import {
|
|
118
|
+
const fileContents = `import { Response, ContractCalls } from '@clarigen/core';
|
|
119
119
|
|
|
120
120
|
// prettier-ignore
|
|
121
121
|
export interface ${name}Contract {
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { toCamelCase } from '@clarigen/core';
|
|
2
|
+
import type { ConfigFile } from '../config';
|
|
3
|
+
import { getArgName, jsTypeFromAbiType } from './declaration';
|
|
4
|
+
import type { ContractMeta } from '../utils';
|
|
5
|
+
import { relative, resolve } from 'path';
|
|
6
|
+
import { readFile } from 'fs/promises';
|
|
7
|
+
import { inspect } from 'util';
|
|
8
|
+
|
|
9
|
+
export function generateContractMeta(contract: ContractMeta) {
|
|
10
|
+
const { abi } = contract;
|
|
11
|
+
const functionLines: string[] = [];
|
|
12
|
+
const { functions, variables, maps, ...rest } = abi;
|
|
13
|
+
functions.forEach((func) => {
|
|
14
|
+
let functionLine = `${toCamelCase(func.name)}: `;
|
|
15
|
+
const args = func.args.map((arg) => {
|
|
16
|
+
return `${getArgName(arg.name)}: ${jsTypeFromAbiType(arg.type, true)}`;
|
|
17
|
+
});
|
|
18
|
+
const argsTuple = `[${args.join(', ')}]`;
|
|
19
|
+
const funcDef = JSON.stringify(func);
|
|
20
|
+
functionLine += funcDef;
|
|
21
|
+
const retType = jsTypeFromAbiType(func.outputs.type);
|
|
22
|
+
functionLine += ` as TypedAbiFunction<${argsTuple}, ${retType}>`;
|
|
23
|
+
functionLines.push(functionLine);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const variableLines = contract.variables.map((v) => {
|
|
27
|
+
let varLine = `${toCamelCase(v.name)}: `;
|
|
28
|
+
const type = jsTypeFromAbiType(v.type);
|
|
29
|
+
const varJSON = inspect(v, false, null, false);
|
|
30
|
+
varLine += `${varJSON} as TypedAbiVariable<${type}>`;
|
|
31
|
+
return varLine;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const constants = contract.variables.filter((v) => v.access === 'constant');
|
|
35
|
+
const constantLines = constants.map((constant) => {
|
|
36
|
+
return `"${toCamelCase(constant.name)}": ${serialize(
|
|
37
|
+
constant.defaultValue
|
|
38
|
+
)}`;
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const mapLines = maps.map((map) => {
|
|
42
|
+
let mapLine = `${toCamelCase(map.name)}: `;
|
|
43
|
+
const keyType = jsTypeFromAbiType(map.key);
|
|
44
|
+
const valType = jsTypeFromAbiType(map.value);
|
|
45
|
+
mapLine += JSON.stringify(map);
|
|
46
|
+
mapLine += ` as TypedAbiMap<${keyType}, ${valType}>`;
|
|
47
|
+
return mapLine;
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const otherAbi = JSON.stringify(rest);
|
|
51
|
+
|
|
52
|
+
const contractFile = relative(process.cwd(), contract.contractFile);
|
|
53
|
+
|
|
54
|
+
return `{
|
|
55
|
+
${serializeLines('functions', functionLines)}
|
|
56
|
+
${serializeLines('variables', variableLines)}
|
|
57
|
+
${serializeLines('maps', mapLines)}
|
|
58
|
+
${serializeLines('constants', constantLines)}
|
|
59
|
+
${otherAbi.slice(1, -1)},
|
|
60
|
+
contractName: '${contract.contractName}',
|
|
61
|
+
contractFile: '${contractFile}',
|
|
62
|
+
}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export async function generateSingleFile(
|
|
66
|
+
config: ConfigFile,
|
|
67
|
+
contracts: ContractMeta[]
|
|
68
|
+
) {
|
|
69
|
+
const contractDefs = contracts.map((contract) => {
|
|
70
|
+
const meta = generateContractMeta(contract);
|
|
71
|
+
const keyName = toCamelCase(contract.contractName);
|
|
72
|
+
return `${keyName}: ${meta}`;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const types = await getSingleTypes();
|
|
76
|
+
const accounts = generateAccounts(config);
|
|
77
|
+
|
|
78
|
+
const file = `
|
|
79
|
+
${types}
|
|
80
|
+
|
|
81
|
+
export const contracts = {
|
|
82
|
+
${contractDefs.join(',\n')}
|
|
83
|
+
} as const;
|
|
84
|
+
|
|
85
|
+
${accounts}
|
|
86
|
+
`;
|
|
87
|
+
return file;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function generateAccounts(config: ConfigFile) {
|
|
91
|
+
let accounts = '';
|
|
92
|
+
if ('accounts' in config) {
|
|
93
|
+
const accountLines = Object.keys(config.accounts).map((key) => {
|
|
94
|
+
const account = config.accounts[key];
|
|
95
|
+
return `"${key}": {
|
|
96
|
+
mnemonic: "${account.mnemonic}",
|
|
97
|
+
balance: ${account.balance.toString()}n,
|
|
98
|
+
address: "${account.address}",
|
|
99
|
+
},`;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
accounts = `export const accounts = {
|
|
103
|
+
${accountLines.join('\n ')}
|
|
104
|
+
} as const;`;
|
|
105
|
+
}
|
|
106
|
+
return accounts;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
Uint8Array.prototype[inspect.custom] = function (this: Uint8Array) {
|
|
110
|
+
return `Uint8Array.from([${this.join(',')}])`;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export function serialize(obj: any) {
|
|
114
|
+
return inspect(obj, {
|
|
115
|
+
showHidden: false,
|
|
116
|
+
maxArrayLength: null,
|
|
117
|
+
maxStringLength: null,
|
|
118
|
+
depth: null,
|
|
119
|
+
colors: false,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function serializeLines(key: string, lines: string[]) {
|
|
124
|
+
return `"${key}": {
|
|
125
|
+
${lines.join(',\n ')}
|
|
126
|
+
},`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function getSingleTypes() {
|
|
130
|
+
// 🤔 weird stuff with tsup shims
|
|
131
|
+
const typesPath = resolve(__dirname, '../../dist/abi-types.ts.txt');
|
|
132
|
+
const typesFile = await readFile(typesPath, { encoding: 'utf-8' });
|
|
133
|
+
return typesFile;
|
|
134
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ClarityAbiType,
|
|
3
|
+
cvToValue,
|
|
4
|
+
AbiTypeTo,
|
|
5
|
+
ClarityAbi,
|
|
6
|
+
} from '@clarigen/core';
|
|
7
|
+
import { evalRaw, NativeClarityBinProvider } from '@clarigen/native-bin';
|
|
8
|
+
import { ClarityAbiVariable, hexToCV } from 'micro-stacks/clarity';
|
|
9
|
+
import type { ContractMeta } from '../utils';
|
|
10
|
+
|
|
11
|
+
// export interface TypedAbiVariable<T extends ClarityAbiType>
|
|
12
|
+
// extends ClarityAbiVariable {
|
|
13
|
+
// type: T;
|
|
14
|
+
// defaultValue: AbiTypeTo<T>;
|
|
15
|
+
// }
|
|
16
|
+
export type TypedAbiVariable<T> = ClarityAbiVariable & {
|
|
17
|
+
defaultValue: T;
|
|
18
|
+
};
|
|
19
|
+
// export type TypedAbiVariable<T> = T extends ClarityAbiVariable ?
|
|
20
|
+
// T['type'] extends ClarityAbiType ?
|
|
21
|
+
export type VariableType<T> = T extends ClarityAbiVariable ? T['type'] : never;
|
|
22
|
+
|
|
23
|
+
export async function getVariables({
|
|
24
|
+
abi,
|
|
25
|
+
contractIdentifier,
|
|
26
|
+
provider,
|
|
27
|
+
}: {
|
|
28
|
+
abi: ClarityAbi;
|
|
29
|
+
contractIdentifier: string;
|
|
30
|
+
provider: NativeClarityBinProvider;
|
|
31
|
+
}) {
|
|
32
|
+
const variableTransforms = abi.variables.map((variable) => {
|
|
33
|
+
return evalVariable({
|
|
34
|
+
variable,
|
|
35
|
+
provider,
|
|
36
|
+
contractIdentifier,
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
const variables = await Promise.all(variableTransforms);
|
|
40
|
+
return variables;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export async function evalVariable<T extends ClarityAbiVariable>({
|
|
44
|
+
contractIdentifier,
|
|
45
|
+
variable,
|
|
46
|
+
provider,
|
|
47
|
+
}: {
|
|
48
|
+
contractIdentifier: string;
|
|
49
|
+
variable: T;
|
|
50
|
+
provider: NativeClarityBinProvider;
|
|
51
|
+
}) {
|
|
52
|
+
const code = getEvalCode(variable);
|
|
53
|
+
const result = await evalRaw({
|
|
54
|
+
contractAddress: contractIdentifier,
|
|
55
|
+
code,
|
|
56
|
+
provider,
|
|
57
|
+
});
|
|
58
|
+
const resultCV = hexToCV(result.output_serialized);
|
|
59
|
+
const value = cvToValue(resultCV, true);
|
|
60
|
+
return {
|
|
61
|
+
...variable,
|
|
62
|
+
defaultValue: value,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// export async function
|
|
67
|
+
|
|
68
|
+
function getEvalCode(variable: ClarityAbiVariable) {
|
|
69
|
+
const { access } = variable;
|
|
70
|
+
if (access === 'variable') {
|
|
71
|
+
return `(var-get ${variable.name})`;
|
|
72
|
+
}
|
|
73
|
+
return variable.name;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// export function serializeVariable(variable: TypedAbiVariable<any>) {
|
|
77
|
+
// const { defaultValue, ...rest } = variable;
|
|
78
|
+
// const lines = Object.keys(rest).map((key) => {
|
|
79
|
+
// return `"${key}": ${JSON.stringify(rest[key])}`;
|
|
80
|
+
// });
|
|
81
|
+
// const valueLine = typeof defaultValue === 'bigint' ? `${defaultValue.toString()}n` : JSON.stringify()
|
|
82
|
+
// }
|
package/src/utils.ts
CHANGED
|
@@ -8,11 +8,26 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
NativeClarityBinProvider,
|
|
10
10
|
createClarityBin,
|
|
11
|
+
deployContract,
|
|
11
12
|
} from '@clarigen/native-bin';
|
|
12
13
|
import { resolve, relative, dirname } from 'path';
|
|
13
|
-
import { mkdir
|
|
14
|
+
import { mkdir } from 'fs/promises';
|
|
14
15
|
import { getProjectConfig } from './config';
|
|
15
16
|
import { generateDocsIndex, generateMarkdownDoc } from './docs';
|
|
17
|
+
import { ClarityAbi, Contract } from '@clarigen/core';
|
|
18
|
+
import { generateContractMeta, generateSingleFile } from './generate/single';
|
|
19
|
+
import { writeFile } from './writer';
|
|
20
|
+
import { getVariables, TypedAbiVariable } from './generate/vars';
|
|
21
|
+
import { ClarityAbiVariable } from 'micro-stacks/clarity';
|
|
22
|
+
|
|
23
|
+
export interface ContractMeta {
|
|
24
|
+
abi: ClarityAbi;
|
|
25
|
+
contractFile: string;
|
|
26
|
+
dirName: string;
|
|
27
|
+
contractName: string;
|
|
28
|
+
contractAddress: string;
|
|
29
|
+
variables: TypedAbiVariable<unknown>[];
|
|
30
|
+
}
|
|
16
31
|
|
|
17
32
|
export const generateFilesForContract = async ({
|
|
18
33
|
contractFile: _contractFile,
|
|
@@ -30,15 +45,21 @@ export const generateFilesForContract = async ({
|
|
|
30
45
|
dirName?: string;
|
|
31
46
|
contractName: string;
|
|
32
47
|
docsPath?: string;
|
|
33
|
-
}) => {
|
|
48
|
+
}): Promise<ContractMeta> => {
|
|
34
49
|
const contractFile = resolve(process.cwd(), _contractFile);
|
|
50
|
+
const contractIdentifier = `${contractAddress}.${contractName}`;
|
|
35
51
|
|
|
36
|
-
const abi = await
|
|
37
|
-
|
|
52
|
+
const abi = await deployContract({
|
|
53
|
+
contractIdentifier,
|
|
54
|
+
contractFilePath: contractFile,
|
|
38
55
|
provider,
|
|
39
|
-
contractAddress,
|
|
40
|
-
contractName,
|
|
41
56
|
});
|
|
57
|
+
const variables = await getVariables({
|
|
58
|
+
abi,
|
|
59
|
+
contractIdentifier,
|
|
60
|
+
provider,
|
|
61
|
+
});
|
|
62
|
+
|
|
42
63
|
const typesFile = generateTypesFile(abi, contractName);
|
|
43
64
|
const indexFile = generateIndexFile({
|
|
44
65
|
contractFile: relative(process.cwd(), contractFile),
|
|
@@ -63,6 +84,15 @@ export const generateFilesForContract = async ({
|
|
|
63
84
|
await writeFile(resolve(outputPath, 'abi.ts'), abiFile);
|
|
64
85
|
await writeFile(resolve(outputPath, 'index.ts'), indexFile);
|
|
65
86
|
await writeFile(resolve(outputPath, 'types.ts'), typesFile);
|
|
87
|
+
|
|
88
|
+
return {
|
|
89
|
+
abi,
|
|
90
|
+
contractFile,
|
|
91
|
+
contractName,
|
|
92
|
+
dirName,
|
|
93
|
+
contractAddress,
|
|
94
|
+
variables,
|
|
95
|
+
};
|
|
66
96
|
};
|
|
67
97
|
|
|
68
98
|
export const generateProject = async (projectPath: string) => {
|
|
@@ -70,11 +100,12 @@ export const generateProject = async (projectPath: string) => {
|
|
|
70
100
|
const { contractsDir, outputDir, contracts } = configFile;
|
|
71
101
|
const outputFolder = resolve(projectPath, outputDir);
|
|
72
102
|
const provider = await createClarityBin();
|
|
103
|
+
const metas: ContractMeta[] = [];
|
|
73
104
|
// this needs to be serial
|
|
74
105
|
for (const contract of contracts) {
|
|
75
106
|
const contractFile = resolve(projectPath, contractsDir, contract.file);
|
|
76
107
|
const dirName = dirname(contract.file);
|
|
77
|
-
await generateFilesForContract({
|
|
108
|
+
const meta = await generateFilesForContract({
|
|
78
109
|
contractFile,
|
|
79
110
|
outputFolder: outputFolder,
|
|
80
111
|
provider,
|
|
@@ -83,6 +114,7 @@ export const generateProject = async (projectPath: string) => {
|
|
|
83
114
|
contractName: contract.name,
|
|
84
115
|
docsPath: configFile.docs,
|
|
85
116
|
});
|
|
117
|
+
metas.push(meta);
|
|
86
118
|
}
|
|
87
119
|
|
|
88
120
|
const indexFile = generateProjectIndexFile(configFile);
|
|
@@ -90,4 +122,8 @@ export const generateProject = async (projectPath: string) => {
|
|
|
90
122
|
|
|
91
123
|
const indexPath = resolve(outputFolder, 'index.ts');
|
|
92
124
|
await writeFile(indexPath, indexFile);
|
|
125
|
+
|
|
126
|
+
const singleFile = await generateSingleFile(configFile, metas);
|
|
127
|
+
const singlePath = resolve(outputFolder, 'single.ts');
|
|
128
|
+
await writeFile(singlePath, singleFile);
|
|
93
129
|
};
|
package/src/writer.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Utilities for writing and formatting files
|
|
2
|
+
import { writeFile as _writeFile } from 'fs/promises';
|
|
3
|
+
import { basename } from 'path';
|
|
4
|
+
import { resolveConfig, format, Options } from 'prettier';
|
|
5
|
+
|
|
6
|
+
const defaultPrettierConfig: Options = {
|
|
7
|
+
printWidth: 80,
|
|
8
|
+
semi: true,
|
|
9
|
+
singleQuote: true,
|
|
10
|
+
trailingComma: 'es5',
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export async function resolvePrettierConfig(): Promise<Options> {
|
|
14
|
+
try {
|
|
15
|
+
const local = await resolveConfig(process.cwd());
|
|
16
|
+
if (local) return local;
|
|
17
|
+
} catch (error) {}
|
|
18
|
+
return defaultPrettierConfig;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function formatFile(contents: string, path: string) {
|
|
22
|
+
try {
|
|
23
|
+
const fileName = basename(path);
|
|
24
|
+
const config = await resolvePrettierConfig();
|
|
25
|
+
const formatted = format(contents, {
|
|
26
|
+
...config,
|
|
27
|
+
filepath: fileName,
|
|
28
|
+
});
|
|
29
|
+
return formatted;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
// handle formatting error
|
|
32
|
+
}
|
|
33
|
+
return contents;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function writeFile(path: string, contents: string) {
|
|
37
|
+
const formatted = await formatFile(contents, path);
|
|
38
|
+
await _writeFile(path, formatted);
|
|
39
|
+
}
|
package/dist/commands/index.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import * as _oclif_parser_lib_flags from '@oclif/parser/lib/flags';
|
|
2
|
-
import { Command } from '@oclif/command';
|
|
3
|
-
|
|
4
|
-
declare class Generate extends Command {
|
|
5
|
-
static description: string;
|
|
6
|
-
static strict: boolean;
|
|
7
|
-
static hidden: boolean;
|
|
8
|
-
static flags: {
|
|
9
|
-
help: _oclif_parser_lib_flags.IBooleanFlag<void>;
|
|
10
|
-
watch: _oclif_parser_lib_flags.IBooleanFlag<boolean>;
|
|
11
|
-
};
|
|
12
|
-
static args: any[];
|
|
13
|
-
run(): Promise<void>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export { Generate };
|
package/dist/commands/index.mjs
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
var rt=Object.defineProperty,nt=Object.defineProperties;var et=Object.getOwnPropertyDescriptors;var w=Object.getOwnPropertySymbols;var k=Object.prototype.hasOwnProperty,N=Object.prototype.propertyIsEnumerable;var j=(t,n,r)=>n in t?rt(t,n,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[n]=r,$=(t,n)=>{for(var r in n||(n={}))k.call(n,r)&&j(t,r,n[r]);if(w)for(var r of w(n))N.call(n,r)&&j(t,r,n[r]);return t},h=(t,n)=>nt(t,et(n));var ot=(t=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(t,{get:(n,r)=>(typeof require!="undefined"?require:n)[r]}):t)(function(t){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var D=(t,n)=>{var r={};for(var e in t)k.call(t,e)&&n.indexOf(e)<0&&(r[e]=t[e]);if(t!=null&&w)for(var e of w(t))n.indexOf(e)<0&&N.call(t,e)&&(r[e]=t[e]);return r};import{Command as Wt,flags as Y}from"@oclif/command";import{hasStdErr as kt}from"@clarigen/native-bin";import{toCamelCase as x}from"@clarigen/core";import{dirname as Nt,join as Dt}from"path";import{run as Cr}from"@oclif/command";import{resolve as R,join as gt,relative as ut}from"path";import{readFile as mt,access as Ct}from"fs/promises";import{constants as dt}from"fs";import{parse as v}from"@ltd/j-toml";import{resolve as S}from"path";import{readFile as O}from"fs/promises";import{generateWallet as it,getStxAddressFromAccount as st}from"micro-stacks/wallet-sdk";import{array as ct}from"toposort";import{StacksNetworkVersion as at}from"micro-stacks/crypto";async function lt(t){let n=S(t,"settings","Devnet.toml"),r=await O(n,{encoding:"utf-8"});return v(r,1,`
|
|
2
|
-
`,!0,{longer:!0})}async function ft(t){let n=S(t,"Clarinet.toml"),r=await O(n,{encoding:"utf-8"});return v(r,1,`
|
|
3
|
-
`,!0)}async function _(t,n){let r=await ft(t),e=n.deployer.address;return pt(r.contracts).map(c=>({file:r.contracts[c].path.replace(/^contracts\//,""),address:e,name:c}))}function pt(t){let n=[],r=[];return Object.entries(t).forEach(([o,i])=>{r.push(o),i.depends_on.forEach(c=>n.push([o,c]))}),ct(r,n).reverse()}async function B(t){let n=await lt(t),r=await Promise.all(Object.entries(n.accounts).map(async([o,i])=>{let c=await it(i.mnemonic,"password"),[s]=c.accounts,a=st(s,at.testnetP2PKH);return[o,h($({},i),{address:a})]}));return Object.fromEntries(r)}var L={outputDir:"src/clarigen",clarinet:"."};function yt(t){return R(t,"clarigen.config.json")}async function $t(t){try{return await Ct(t,dt.R_OK),!0}catch{return!1}}async function xt(t){let n=yt(t);if(await $t(n)){let e=await mt(n,{encoding:"utf-8"}),o=JSON.parse(e);return $($({},L),o)}return L}async function b(t){let n=await xt(t),r=R(t,n.clarinet||"."),e=await B(r),o=await _(r,e),i=ut(process.cwd(),gt(n.clarinet,"contracts"));return h($({},n),{contracts:o,contractsDir:i,accounts:e,clarinet:n.clarinet||"."})}import{isClarityAbiBuffer as wt,isClarityAbiList as ht,isClarityAbiOptional as bt,isClarityAbiPrimitive as Ft,isClarityAbiResponse as J,isClarityAbiStringAscii as At,isClarityAbiStringUtf8 as Pt,isClarityAbiTuple as Tt}from"micro-stacks/transactions";import{toCamelCase as P}from"@clarigen/core";import{check as Et}from"reserved-words";var f=(t,n=!1)=>{if(Ft(t)){if(t==="uint128")return n?"number | bigint":"bigint";if(t==="int128")return n?"number | bigint":"bigint";if(t==="bool")return"boolean";if(t==="principal")return"string";if(t==="none")return"null";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(t)}`)}else{if(wt(t))return"Uint8Array";if(J(t)){let r=f(t.response.ok),e=f(t.response.error);return`ClarityTypes.Response<${r}, ${e}>`}else{if(bt(t))return`${f(t.optional)} | null`;if(Tt(t)){let r=[];return t.tuple.forEach(({name:e,type:o})=>{let i=f(o);r.push(`"${e}": ${i}`)}),`{
|
|
4
|
-
${r.join(`;
|
|
5
|
-
`)}
|
|
6
|
-
}`}else{if(ht(t))return`${f(t.list.type)}[]`;if(At(t))return"string";if(Pt(t))return"string";if(t==="trait_reference")return"string";throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(t)}`)}}}};function It(t){let n=P(t);return`${Et(n,6)?"_":""}${n}`}var jt={public:"Public",read_only:"ReadOnly",private:"Private"};function M(t){let n="";return t.functions.forEach((r,e)=>{let o=`${P(r.name)}: `;if(o+=`(${r.args.map(s=>`${It(s.name)}: ${f(s.type,!0)}`).join(", ")}) => `,o+=`ContractCalls.${jt[r.access]}<`,r.access==="public"){let{type:s}=r.outputs;if(!J(s))throw new Error("Expected response type for public function");let a=f(s.response.ok),l=f(s.response.error);o+=`${a}, ${l}>;`}else o+=`${f(r.outputs.type)}>;`;n+=`${e===0?"":`
|
|
7
|
-
`} ${o}`}),t.maps.forEach(r=>{let e=`${P(r.name)}: `,o=f(r.key,!0),i=`key: ${o}`,c=f(r.value);e+=`(${i}) => ContractCalls.Map<${o}, ${c}>;`,n+=`
|
|
8
|
-
${e}`}),n}var U=async({provider:t,contractFile:n,contractAddress:r,contractName:e})=>{let o=await t.runCommand(["launch",`${r}.${e}`,n,t.dbFilePath,"--output_analysis","--costs","--assets"]);if(kt(o.stderr))throw new Error(`Error on ${n}:
|
|
9
|
-
${o.stderr}
|
|
10
|
-
`);let i=JSON.parse(o.stdout);if(i.error){let{initialization:s}=i.error;if(s!=null&&s.includes(`
|
|
11
|
-
Near:
|
|
12
|
-
`)){let[a,l]=s.split(`
|
|
13
|
-
Near:
|
|
14
|
-
`),p="",g=/start_line: (\d+),/.exec(l);throw g&&(p=g[1]),new Error(`Error on ${n}:
|
|
15
|
-
${a}
|
|
16
|
-
${p?`Near line ${p}`:""}
|
|
17
|
-
Raw trace:
|
|
18
|
-
${l}
|
|
19
|
-
`)}throw new Error(`Error on ${n}:
|
|
20
|
-
${JSON.stringify(i.error,null,2)}
|
|
21
|
-
`)}return i.analysis},W=({contractName:t,abi:n})=>{let r=x(t,!0),s=n,{clarity_version:e}=s,o=D(s,["clarity_version"]),i=JSON.stringify(o,null,2);return`import { ClarityAbi } from '@clarigen/core';
|
|
22
|
-
|
|
23
|
-
// prettier-ignore
|
|
24
|
-
export const ${r}Interface: ClarityAbi = ${i};
|
|
25
|
-
`},V=({contractFile:t,contractAddress:n,contractName:r})=>{let e=x(r,!0),o=x(r),i=`${e}Contract`,c=`${e}Interface`;return`import { pureProxy, Contract } from '@clarigen/core';
|
|
26
|
-
import type { ${i} } from './types';
|
|
27
|
-
import { ${c} } from './abi';
|
|
28
|
-
export type { ${i} } from './types';
|
|
29
|
-
|
|
30
|
-
export function ${o}Contract(contractAddress: string, contractName: string) {
|
|
31
|
-
return pureProxy<${i}>({
|
|
32
|
-
abi: ${c},
|
|
33
|
-
contractAddress,
|
|
34
|
-
contractName,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const ${o}Info: Contract<${i}> = {
|
|
39
|
-
contract: ${o}Contract,
|
|
40
|
-
address: '${n}',
|
|
41
|
-
contractFile: '${t}',
|
|
42
|
-
name: '${r}',
|
|
43
|
-
abi: ${c},
|
|
44
|
-
};
|
|
45
|
-
`},K=(t,n)=>{let r=x(n,!0),e=M(t);return`import { ClarityTypes, ContractCalls } from '@clarigen/core';
|
|
46
|
-
|
|
47
|
-
// prettier-ignore
|
|
48
|
-
export interface ${r}Contract {
|
|
49
|
-
${e}
|
|
50
|
-
}
|
|
51
|
-
`},q=t=>{let n=["import type { ContractInstances } from '@clarigen/core';"],r=[],e=[],o="";"accounts"in t&&(o=`
|
|
52
|
-
|
|
53
|
-
// prettier-ignore
|
|
54
|
-
export const accounts = {
|
|
55
|
-
${Object.keys(t.accounts).map(a=>{let l=t.accounts[a];return`"${a}": {
|
|
56
|
-
mnemonic: "${l.mnemonic}",
|
|
57
|
-
balance: ${l.balance.toString()}n,
|
|
58
|
-
address: "${l.address}",
|
|
59
|
-
},`}).join(`
|
|
60
|
-
`)}
|
|
61
|
-
};`),t.contracts.forEach(s=>{let a=s.name,l=x(a),p=`${l}Info`,y=`${x(a,!0)}Contract`,g=Nt(s.file),I=`'./${Dt(g||".",a)}'`,z=`import { ${p} } from ${I};`;n.push(z);let G=`export type { ${y} } from ${I};`;r.push(G);let tt=`${l}: ${p},`;e.push(tt)});let i=`
|
|
62
|
-
export type Contracts = ContractInstances<typeof contracts>;
|
|
63
|
-
`;return`${n.join(`
|
|
64
|
-
`)}
|
|
65
|
-
${r.join(`
|
|
66
|
-
`)}
|
|
67
|
-
${i}
|
|
68
|
-
export const contracts = {
|
|
69
|
-
${e.join(`
|
|
70
|
-
`)}
|
|
71
|
-
};${o}
|
|
72
|
-
`};import{createClarityBin as Lt}from"@clarigen/native-bin";import{resolve as u,relative as Rt,dirname as Jt}from"path";import{mkdir as Mt,writeFile as F}from"fs/promises";import{createContractDocInfo as vt,generateMarkdown as St}from"@clarigen/claridocs";import{mkdir as Ot,readFile as _t,writeFile as H}from"fs/promises";import{relative as Bt,resolve as T}from"path";async function Q({contractFile:t,contractName:n,docsPath:r,abi:e,dirName:o}){let i=await _t(t,{encoding:"utf-8"}),c=vt({contractSrc:i,abi:e}),s=T(process.cwd(),r,o||"."),a=T(s,`${n}.md`),l=St({contract:c,contractFile:Bt(s,t),contractName:n,abi:e});await Ot(s,{recursive:!0}),await H(a,l)}async function X(t){if(!t.docs)return;let r=`# Contracts
|
|
73
|
-
|
|
74
|
-
${t.contracts.map(o=>{let i=o.file.replace(".clar",".md");return`- [\`${o.name}\`](${i})`}).join(`
|
|
75
|
-
`)}
|
|
76
|
-
`,e=T(process.cwd(),t.docs,"README.md");await H(e,r)}var Ut=async({contractFile:t,outputFolder:n,provider:r,contractAddress:e,dirName:o,contractName:i,docsPath:c})=>{let s=u(process.cwd(),t),a=await U({contractFile:s,provider:r,contractAddress:e,contractName:i}),l=K(a,i),p=V({contractFile:Rt(process.cwd(),s),contractAddress:e,contractName:i}),y=W({contractName:i,abi:a});typeof c<"u"&&await Q({contractFile:s,contractName:i,abi:a,docsPath:c,dirName:o});let g=u(n,o||".",i);await Mt(g,{recursive:!0}),await F(u(g,"abi.ts"),y),await F(u(g,"index.ts"),p),await F(u(g,"types.ts"),l)},A=async t=>{let n=await b(t),{contractsDir:r,outputDir:e,contracts:o}=n,i=u(t,e),c=await Lt();for(let l of o){let p=u(t,r,l.file),y=Jt(l.file);await Ut({contractFile:p,outputFolder:i,provider:c,contractAddress:l.address,dirName:y,contractName:l.name,docsPath:n.docs})}let s=q(n);await X(n);let a=u(i,"index.ts");await F(a,s)};import{watch as Vt}from"chokidar";import{basename as Kt}from"path";import{red as qt,green as Z}from"chalk";var Ht=ot("ora"),E=class extends Wt{async run(){let{flags:n}=this.parse(E),r=process.cwd();if(n.watch){let e=Ht("Generating files").start(),{contractsDir:o}=await b(r),i=Vt([o],{cwd:r});try{await A(r),e.succeed("Finished generating files. Watching for changes.")}catch(c){e.fail(`Error generating files.
|
|
77
|
-
${c.message}`)}i.on("change",async c=>{let s=Kt(c);e.clear(),e.start(`Change detected for ${Z(s)}, generating.`);try{await A(r),e.succeed(`Finished generating files for ${Z(s)}. Watching for changes.`)}catch(a){let l=a.message;e.fail(`Error after saving ${qt(s)}.
|
|
78
|
-
${l}`)}}),process.on("SIGINT",async()=>{await i.close(),process.exit()})}else await A(r)}},d=E;d.description="Generate project files",d.strict=!0,d.hidden=!1,d.flags={help:Y.help({char:"h"}),watch:Y.boolean({char:"w",description:"Watch for changes to your contracts"})},d.args=[];export{d as Generate};
|
package/dist/index.d.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export { run } from '@oclif/command';
|
|
2
|
-
import { ClarityAbiType } from 'micro-stacks/clarity';
|
|
3
|
-
import { ClarityAbi } from '@clarigen/core';
|
|
4
|
-
import { NativeClarityBinProvider } from '@clarigen/native-bin';
|
|
5
|
-
export { Generate } from './commands/index.js';
|
|
6
|
-
import '@oclif/parser/lib/flags';
|
|
7
|
-
|
|
8
|
-
interface ClarinetConfigAccount {
|
|
9
|
-
mnemonic: string;
|
|
10
|
-
balance: bigint;
|
|
11
|
-
}
|
|
12
|
-
interface ClarinetAccount extends ClarinetConfigAccount {
|
|
13
|
-
address: string;
|
|
14
|
-
}
|
|
15
|
-
interface ClarinetAccounts {
|
|
16
|
-
deployer: ClarinetAccount;
|
|
17
|
-
[name: string]: ClarinetAccount;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
interface ConfigContract {
|
|
21
|
-
address: string;
|
|
22
|
-
file: string;
|
|
23
|
-
name: string;
|
|
24
|
-
}
|
|
25
|
-
interface ConfigFileContents {
|
|
26
|
-
outputDir: string;
|
|
27
|
-
clarinet: string;
|
|
28
|
-
docs?: string;
|
|
29
|
-
}
|
|
30
|
-
interface ConfigFile extends ConfigFileContents {
|
|
31
|
-
contractsDir: string;
|
|
32
|
-
contracts: ConfigContract[];
|
|
33
|
-
accounts: ClarinetAccounts;
|
|
34
|
-
clarinet: string;
|
|
35
|
-
}
|
|
36
|
-
declare const defaultConfigFile: ConfigFileContents;
|
|
37
|
-
declare function configFilePath(rootPath: string): string;
|
|
38
|
-
declare function configFileExists(configPath: string): Promise<boolean>;
|
|
39
|
-
declare function getConfigFile(rootPath: string): Promise<ConfigFileContents>;
|
|
40
|
-
declare function getProjectConfig(rootPath: string): Promise<ConfigFile>;
|
|
41
|
-
|
|
42
|
-
declare const jsTypeFromAbiType: (val: ClarityAbiType, isArgument?: boolean) => string;
|
|
43
|
-
declare function makePureTypes(abi: ClarityAbi): string;
|
|
44
|
-
|
|
45
|
-
declare const generateInterface: ({ provider, contractFile, contractAddress, contractName, }: {
|
|
46
|
-
contractFile: string;
|
|
47
|
-
provider: NativeClarityBinProvider;
|
|
48
|
-
contractAddress: string;
|
|
49
|
-
contractName: string;
|
|
50
|
-
}) => Promise<ClarityAbi>;
|
|
51
|
-
declare const generateInterfaceFile: ({ contractName, abi, }: {
|
|
52
|
-
contractName: string;
|
|
53
|
-
abi: ClarityAbi;
|
|
54
|
-
}) => string;
|
|
55
|
-
declare const generateIndexFile: ({ contractFile, contractAddress, contractName, }: {
|
|
56
|
-
contractFile: string;
|
|
57
|
-
contractAddress: string;
|
|
58
|
-
contractName: string;
|
|
59
|
-
}) => string;
|
|
60
|
-
declare const generateTypesFile: (abi: ClarityAbi, contractName: string) => string;
|
|
61
|
-
declare const generateProjectIndexFile: (config: ConfigFile) => string;
|
|
62
|
-
|
|
63
|
-
export { ConfigContract, ConfigFile, ConfigFileContents, configFileExists, configFilePath, defaultConfigFile, generateIndexFile, generateInterface, generateInterfaceFile, generateProjectIndexFile, generateTypesFile, getConfigFile, getProjectConfig, jsTypeFromAbiType, makePureTypes };
|