@clarigen/cli 0.2.0 → 0.3.0
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/README.md +0 -58
- package/bin/run +2 -1
- package/dist/clarinet-config.js +57 -0
- package/dist/commands/contract.js +33 -0
- package/dist/commands/index.js +65 -0
- package/dist/config.js +31 -0
- package/dist/generate/declaration.js +157 -0
- package/dist/generate/files.js +142 -0
- package/dist/index.js +19 -0
- package/dist/start.js +9 -0
- package/dist/utils.js +56 -0
- package/package.json +11 -9
- package/src/clarinet-config.ts +4 -7
- package/src/commands/contract.ts +1 -0
- package/src/commands/index.ts +66 -2
- package/src/generate/files.ts +17 -3
- package/src/index.ts +1 -0
- package/CHANGELOG.md +0 -29
- package/src/commands/generate.ts +0 -63
package/README.md
CHANGED
|
@@ -6,66 +6,8 @@ Most of the time, you'll only need to run `clarigen` to automatically build your
|
|
|
6
6
|
|
|
7
7
|
# Usage
|
|
8
8
|
|
|
9
|
-
<!-- usage -->
|
|
10
|
-
```sh-session
|
|
11
|
-
$ npm install -g @clarigen/cli
|
|
12
|
-
$ clarigen COMMAND
|
|
13
|
-
running command...
|
|
14
|
-
$ clarigen (-v|--version|version)
|
|
15
|
-
@clarigen/cli/0.1.1 darwin-arm64 node-v16.4.2
|
|
16
|
-
$ clarigen --help [COMMAND]
|
|
17
|
-
USAGE
|
|
18
|
-
$ clarigen COMMAND
|
|
19
|
-
...
|
|
20
|
-
```
|
|
21
|
-
<!-- usagestop -->
|
|
22
|
-
|
|
23
9
|
<!-- commands -->
|
|
24
|
-
* [`clarigen `](#clarigen-)
|
|
25
|
-
* [`clarigen contract [CONTRACT]`](#clarigen-contract-contract)
|
|
26
|
-
* [`clarigen generate`](#clarigen-generate)
|
|
27
|
-
|
|
28
|
-
## `clarigen `
|
|
29
|
-
|
|
30
|
-
Generate project files
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
USAGE
|
|
34
|
-
$ clarigen
|
|
35
|
-
|
|
36
|
-
OPTIONS
|
|
37
|
-
-h, --help show CLI help
|
|
38
|
-
-w, --watch Watch for changes to your contracts
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## `clarigen contract [CONTRACT]`
|
|
42
|
-
|
|
43
|
-
Generate files for a single contract
|
|
44
10
|
|
|
45
|
-
```
|
|
46
|
-
USAGE
|
|
47
|
-
$ clarigen contract [CONTRACT]
|
|
48
|
-
|
|
49
|
-
ARGUMENTS
|
|
50
|
-
CONTRACT The file path for your contract
|
|
51
|
-
|
|
52
|
-
OPTIONS
|
|
53
|
-
-h, --help show CLI help
|
|
54
|
-
-o, --output=output [default: clarion] Output destination folder
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## `clarigen generate`
|
|
58
|
-
|
|
59
|
-
Generate project files
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
USAGE
|
|
63
|
-
$ clarigen generate
|
|
64
|
-
|
|
65
|
-
OPTIONS
|
|
66
|
-
-h, --help show CLI help
|
|
67
|
-
-w, --watch Watch for changes to your contracts
|
|
68
|
-
```
|
|
69
11
|
<!-- commandsstop -->
|
|
70
12
|
|
|
71
13
|
## Development
|
package/bin/run
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getClarinetAccounts = exports.getContractsFromClarinet = exports.getClarinetConfig = exports.getClarinetDevConfig = void 0;
|
|
4
|
+
const j_toml_1 = require("@ltd/j-toml");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const promises_1 = require("fs/promises");
|
|
7
|
+
const wallet_sdk_1 = require("@stacks/wallet-sdk");
|
|
8
|
+
async function getClarinetDevConfig(folder) {
|
|
9
|
+
const baseConfigPath = path_1.resolve(folder, 'settings', 'Devnet.toml');
|
|
10
|
+
const configContents = await promises_1.readFile(baseConfigPath, { encoding: 'utf-8' });
|
|
11
|
+
const config = j_toml_1.parse(configContents, 1.0, '\n', true, {
|
|
12
|
+
longer: true,
|
|
13
|
+
});
|
|
14
|
+
return config;
|
|
15
|
+
}
|
|
16
|
+
exports.getClarinetDevConfig = getClarinetDevConfig;
|
|
17
|
+
async function getClarinetConfig(folder) {
|
|
18
|
+
const baseConfigPath = path_1.resolve(folder, 'Clarinet.toml');
|
|
19
|
+
const configContents = await promises_1.readFile(baseConfigPath, { encoding: 'utf-8' });
|
|
20
|
+
const config = j_toml_1.parse(configContents, 1.0, '\n', true);
|
|
21
|
+
return config;
|
|
22
|
+
}
|
|
23
|
+
exports.getClarinetConfig = getClarinetConfig;
|
|
24
|
+
async function getContractsFromClarinet(folder, accounts) {
|
|
25
|
+
const clarinetConfig = await getClarinetConfig(folder);
|
|
26
|
+
const deployerAddress = accounts.deployer.address;
|
|
27
|
+
const contracts = Object.entries(clarinetConfig.contracts).map(([contractName, info]) => {
|
|
28
|
+
const file = info.path.replace(/^contracts\//, '');
|
|
29
|
+
return {
|
|
30
|
+
file,
|
|
31
|
+
address: deployerAddress,
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
return contracts;
|
|
35
|
+
}
|
|
36
|
+
exports.getContractsFromClarinet = getContractsFromClarinet;
|
|
37
|
+
async function getClarinetAccounts(folder) {
|
|
38
|
+
const devConfig = await getClarinetDevConfig(folder);
|
|
39
|
+
const accountEntries = await Promise.all(Object.entries(devConfig.accounts).map(async ([key, info]) => {
|
|
40
|
+
const wallet = await wallet_sdk_1.generateWallet({
|
|
41
|
+
secretKey: info.mnemonic,
|
|
42
|
+
password: 'password',
|
|
43
|
+
});
|
|
44
|
+
const [account] = wallet.accounts;
|
|
45
|
+
const address = wallet_sdk_1.getStxAddress({ account });
|
|
46
|
+
return [
|
|
47
|
+
key,
|
|
48
|
+
{
|
|
49
|
+
...info,
|
|
50
|
+
address,
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
}));
|
|
54
|
+
const accounts = Object.fromEntries(accountEntries);
|
|
55
|
+
return accounts;
|
|
56
|
+
}
|
|
57
|
+
exports.getClarinetAccounts = getClarinetAccounts;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Contract = void 0;
|
|
4
|
+
const command_1 = require("@oclif/command");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
class Contract extends command_1.Command {
|
|
7
|
+
async run() {
|
|
8
|
+
const { argv, flags } = this.parse(Contract);
|
|
9
|
+
const [contractFile] = argv;
|
|
10
|
+
await utils_1.generateFilesForContract({
|
|
11
|
+
contractFile,
|
|
12
|
+
outputFolder: flags.output,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.Contract = Contract;
|
|
17
|
+
Contract.description = `Generate files for a single contract`;
|
|
18
|
+
Contract.strict = true;
|
|
19
|
+
Contract.hidden = true;
|
|
20
|
+
Contract.flags = {
|
|
21
|
+
help: command_1.flags.help({ char: 'h' }),
|
|
22
|
+
output: command_1.flags.string({
|
|
23
|
+
char: 'o',
|
|
24
|
+
description: 'Output destination folder',
|
|
25
|
+
default: 'clarion',
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
Contract.args = [
|
|
29
|
+
{
|
|
30
|
+
name: 'contract',
|
|
31
|
+
description: 'The file path for your contract',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Generate = void 0;
|
|
4
|
+
const command_1 = require("@oclif/command");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const config_1 = require("../config");
|
|
7
|
+
const chokidar_1 = require("chokidar");
|
|
8
|
+
const path_1 = require("path");
|
|
9
|
+
const chalk_1 = require("chalk");
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
11
|
+
const ora = require('ora');
|
|
12
|
+
class Generate extends command_1.Command {
|
|
13
|
+
async run() {
|
|
14
|
+
const { flags } = this.parse(Generate);
|
|
15
|
+
const cwd = process.cwd();
|
|
16
|
+
if (flags.watch) {
|
|
17
|
+
const spinner = ora('Generating files').start();
|
|
18
|
+
const { contractsDir } = await config_1.getConfigFile(cwd);
|
|
19
|
+
const watcher = chokidar_1.watch([contractsDir], {
|
|
20
|
+
cwd,
|
|
21
|
+
});
|
|
22
|
+
try {
|
|
23
|
+
await utils_1.generateProject(cwd);
|
|
24
|
+
spinner.succeed(`Finished generating files. Watching for changes.`);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
28
|
+
spinner.fail(`Error generating files.\n${error.message}`);
|
|
29
|
+
}
|
|
30
|
+
watcher.on('change', async (path) => {
|
|
31
|
+
const file = path_1.basename(path);
|
|
32
|
+
spinner.clear();
|
|
33
|
+
spinner.start(`Change detected for ${chalk_1.green(file)}, generating.`);
|
|
34
|
+
try {
|
|
35
|
+
await utils_1.generateProject(cwd);
|
|
36
|
+
spinner.succeed(`Finished generating files for ${chalk_1.green(file)}. Watching for changes.`);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
40
|
+
const msg = error.message;
|
|
41
|
+
spinner.fail(`Error after saving ${chalk_1.red(file)}.\n${msg}`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
process.on('SIGINT', async () => {
|
|
45
|
+
await watcher.close();
|
|
46
|
+
process.exit();
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
await utils_1.generateProject(cwd);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.Generate = Generate;
|
|
55
|
+
Generate.description = `Generate project files`;
|
|
56
|
+
Generate.strict = true;
|
|
57
|
+
Generate.hidden = false;
|
|
58
|
+
Generate.flags = {
|
|
59
|
+
help: command_1.flags.help({ char: 'h' }),
|
|
60
|
+
watch: command_1.flags.boolean({
|
|
61
|
+
char: 'w',
|
|
62
|
+
description: 'Watch for changes to your contracts',
|
|
63
|
+
}),
|
|
64
|
+
};
|
|
65
|
+
Generate.args = [];
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getConfigFile = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const promises_1 = require("fs/promises");
|
|
6
|
+
const clarinet_config_1 = require("./clarinet-config");
|
|
7
|
+
async function getConfigFile(rootPath) {
|
|
8
|
+
const fullPath = path_1.resolve(rootPath, 'clarigen.config.json');
|
|
9
|
+
const configContents = await promises_1.readFile(fullPath, { encoding: 'utf-8' });
|
|
10
|
+
const configFile = JSON.parse(configContents);
|
|
11
|
+
if (!configFile.outputDir)
|
|
12
|
+
throw new Error('Config file missing "outputDir"');
|
|
13
|
+
if ('clarinet' in configFile) {
|
|
14
|
+
const clarinetPath = path_1.resolve(rootPath, configFile.clarinet);
|
|
15
|
+
const accounts = await clarinet_config_1.getClarinetAccounts(clarinetPath);
|
|
16
|
+
const contracts = await clarinet_config_1.getContractsFromClarinet(clarinetPath, accounts);
|
|
17
|
+
const contractsDir = path_1.relative(process.cwd(), path_1.join(configFile.clarinet, 'contracts'));
|
|
18
|
+
return {
|
|
19
|
+
...configFile,
|
|
20
|
+
contracts,
|
|
21
|
+
contractsDir,
|
|
22
|
+
accounts,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (!configFile.contracts)
|
|
26
|
+
throw new Error('Config file missing "contracts"');
|
|
27
|
+
if (!configFile.contractsDir)
|
|
28
|
+
throw new Error('Config file missing "contractDir"');
|
|
29
|
+
return configFile;
|
|
30
|
+
}
|
|
31
|
+
exports.getConfigFile = getConfigFile;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.makeTypes = exports.jsTypeFromAbiType = exports.cvFromType = void 0;
|
|
4
|
+
const transactions_1 = require("@stacks/transactions");
|
|
5
|
+
const core_1 = require("@clarigen/core");
|
|
6
|
+
const cvFromType = (val) => {
|
|
7
|
+
if (transactions_1.isClarityAbiPrimitive(val)) {
|
|
8
|
+
if (val === 'uint128') {
|
|
9
|
+
return 'ClarityTypes.UIntCV';
|
|
10
|
+
}
|
|
11
|
+
else if (val === 'int128') {
|
|
12
|
+
return 'ClarityTypes.IntCV';
|
|
13
|
+
}
|
|
14
|
+
else if (val === 'bool') {
|
|
15
|
+
return 'ClarityTypes.BooleanCV';
|
|
16
|
+
}
|
|
17
|
+
else if (val === 'principal') {
|
|
18
|
+
return 'ClarityTypes.PrincipalCV';
|
|
19
|
+
}
|
|
20
|
+
else if (val === 'none') {
|
|
21
|
+
return 'ClarityTypes.NoneCV';
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(val)}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (transactions_1.isClarityAbiBuffer(val)) {
|
|
28
|
+
return 'ClarityTypes.BufferCV';
|
|
29
|
+
}
|
|
30
|
+
else if (transactions_1.isClarityAbiResponse(val)) {
|
|
31
|
+
return 'ClarityTypes.ResponseCV';
|
|
32
|
+
}
|
|
33
|
+
else if (transactions_1.isClarityAbiOptional(val)) {
|
|
34
|
+
return 'ClarityTypes.OptionalCV';
|
|
35
|
+
}
|
|
36
|
+
else if (transactions_1.isClarityAbiTuple(val)) {
|
|
37
|
+
return 'ClarityTypes.TupleCV';
|
|
38
|
+
}
|
|
39
|
+
else if (transactions_1.isClarityAbiList(val)) {
|
|
40
|
+
return 'ClarityTypes.ListCV';
|
|
41
|
+
}
|
|
42
|
+
else if (transactions_1.isClarityAbiStringAscii(val)) {
|
|
43
|
+
return 'ClarityTypes.StringAsciiCV';
|
|
44
|
+
}
|
|
45
|
+
else if (transactions_1.isClarityAbiStringUtf8(val)) {
|
|
46
|
+
return 'ClarityTypes.StringUtf8CV';
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(val)}`);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
exports.cvFromType = cvFromType;
|
|
53
|
+
const jsTypeFromAbiType = (val, isArgument = false) => {
|
|
54
|
+
if (transactions_1.isClarityAbiPrimitive(val)) {
|
|
55
|
+
if (val === 'uint128') {
|
|
56
|
+
if (isArgument)
|
|
57
|
+
return 'number | bigint';
|
|
58
|
+
return 'bigint';
|
|
59
|
+
}
|
|
60
|
+
else if (val === 'int128') {
|
|
61
|
+
if (isArgument)
|
|
62
|
+
return 'number | bigint';
|
|
63
|
+
return 'bigint';
|
|
64
|
+
}
|
|
65
|
+
else if (val === 'bool') {
|
|
66
|
+
return 'boolean';
|
|
67
|
+
}
|
|
68
|
+
else if (val === 'principal') {
|
|
69
|
+
return 'string';
|
|
70
|
+
}
|
|
71
|
+
else if (val === 'none') {
|
|
72
|
+
return 'null';
|
|
73
|
+
}
|
|
74
|
+
else if (val === 'trait_reference') {
|
|
75
|
+
return 'string';
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
throw new Error(`Unexpected Clarity ABI type primitive: ${JSON.stringify(val)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (transactions_1.isClarityAbiBuffer(val)) {
|
|
82
|
+
return 'Buffer';
|
|
83
|
+
}
|
|
84
|
+
else if (transactions_1.isClarityAbiResponse(val)) {
|
|
85
|
+
const ok = exports.jsTypeFromAbiType(val.response.ok);
|
|
86
|
+
const err = exports.jsTypeFromAbiType(val.response.error);
|
|
87
|
+
return `ClarityTypes.Response<${ok}, ${err}>`;
|
|
88
|
+
}
|
|
89
|
+
else if (transactions_1.isClarityAbiOptional(val)) {
|
|
90
|
+
const innerType = exports.jsTypeFromAbiType(val.optional);
|
|
91
|
+
return `${innerType} | null`;
|
|
92
|
+
}
|
|
93
|
+
else if (transactions_1.isClarityAbiTuple(val)) {
|
|
94
|
+
const tupleDefs = [];
|
|
95
|
+
val.tuple.forEach(({ name, type }) => {
|
|
96
|
+
const innerType = exports.jsTypeFromAbiType(type);
|
|
97
|
+
tupleDefs.push(`"${name}": ${innerType}`);
|
|
98
|
+
});
|
|
99
|
+
return `{
|
|
100
|
+
${tupleDefs.join(';\n ')}
|
|
101
|
+
}`;
|
|
102
|
+
}
|
|
103
|
+
else if (transactions_1.isClarityAbiList(val)) {
|
|
104
|
+
const innerType = exports.jsTypeFromAbiType(val.list.type);
|
|
105
|
+
return `${innerType}[]`;
|
|
106
|
+
}
|
|
107
|
+
else if (transactions_1.isClarityAbiStringAscii(val)) {
|
|
108
|
+
return 'string';
|
|
109
|
+
}
|
|
110
|
+
else if (transactions_1.isClarityAbiStringUtf8(val)) {
|
|
111
|
+
return 'string';
|
|
112
|
+
}
|
|
113
|
+
else if (val === 'trait_reference') {
|
|
114
|
+
return 'string';
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(val)}`);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
exports.jsTypeFromAbiType = jsTypeFromAbiType;
|
|
121
|
+
const makeTypes = (abi) => {
|
|
122
|
+
let typings = '';
|
|
123
|
+
abi.functions.forEach((func, index) => {
|
|
124
|
+
if (func.access === 'private')
|
|
125
|
+
return;
|
|
126
|
+
let functionLine = `${core_1.toCamelCase(func.name)}: `;
|
|
127
|
+
const args = func.args.map((arg) => {
|
|
128
|
+
return `${core_1.toCamelCase(arg.name)}: ${exports.jsTypeFromAbiType(arg.type, true)}`;
|
|
129
|
+
});
|
|
130
|
+
functionLine += `(${args.join(', ')}) => `;
|
|
131
|
+
if (func.access === 'public') {
|
|
132
|
+
const { type } = func.outputs;
|
|
133
|
+
if (!transactions_1.isClarityAbiResponse(type))
|
|
134
|
+
throw new Error('Expected response type for public function');
|
|
135
|
+
functionLine += 'Transaction';
|
|
136
|
+
const ok = exports.jsTypeFromAbiType(type.response.ok);
|
|
137
|
+
const err = exports.jsTypeFromAbiType(type.response.error);
|
|
138
|
+
functionLine += `<${ok}, ${err}>;`;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
const jsType = exports.jsTypeFromAbiType(func.outputs.type);
|
|
142
|
+
functionLine += `Promise<${jsType}>;`;
|
|
143
|
+
// const { type } = func.outputs;
|
|
144
|
+
// if (isClarityAbiResponse(type)) {
|
|
145
|
+
// const ok = jsTypeFromAbiType(type.response.ok);
|
|
146
|
+
// const err = jsTypeFromAbiType(type.response.error);
|
|
147
|
+
// functionLine += `Promise<ClarityTypes.Response<${ok}, ${err}>>;`;
|
|
148
|
+
// } else {
|
|
149
|
+
// const jsType = jsTypeFromAbiType(func.outputs.type);
|
|
150
|
+
// functionLine += `Promise<${jsType}>;`;
|
|
151
|
+
// }
|
|
152
|
+
}
|
|
153
|
+
typings += `${index === 0 ? '' : '\n'} ${functionLine}`;
|
|
154
|
+
});
|
|
155
|
+
return typings;
|
|
156
|
+
};
|
|
157
|
+
exports.makeTypes = makeTypes;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateProjectIndexFile = exports.generateTypesFile = exports.generateIndexFile = exports.generateInterfaceFile = exports.generateInterface = void 0;
|
|
4
|
+
const native_bin_1 = require("@clarigen/native-bin");
|
|
5
|
+
const core_1 = require("@clarigen/core");
|
|
6
|
+
const declaration_1 = require("./declaration");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const generateInterface = async ({ provider: _provider, contractFile, contractAddress = 'S1G2081040G2081040G2081040G208105NK8PE5', }) => {
|
|
9
|
+
const provider = _provider || (await native_bin_1.createClarityBin());
|
|
10
|
+
const contractName = core_1.getContractNameFromPath(contractFile);
|
|
11
|
+
const receipt = await provider.runCommand([
|
|
12
|
+
'launch',
|
|
13
|
+
`${contractAddress}.${contractName}`,
|
|
14
|
+
contractFile,
|
|
15
|
+
provider.dbFilePath,
|
|
16
|
+
'--output_analysis',
|
|
17
|
+
'--costs',
|
|
18
|
+
'--assets',
|
|
19
|
+
]);
|
|
20
|
+
if (receipt.stderr &&
|
|
21
|
+
!receipt.stderr.includes('Used unimplemented cost function')) {
|
|
22
|
+
throw new Error(`Error on ${contractFile}:
|
|
23
|
+
${receipt.stderr}
|
|
24
|
+
`);
|
|
25
|
+
}
|
|
26
|
+
const output = JSON.parse(receipt.stdout);
|
|
27
|
+
if (output.error) {
|
|
28
|
+
const { initialization } = output.error;
|
|
29
|
+
if (initialization?.includes('\nNear:\n')) {
|
|
30
|
+
const [error, trace] = initialization.split('\nNear:\n');
|
|
31
|
+
let startLine = '';
|
|
32
|
+
const matcher = /start_line: (\d+),/;
|
|
33
|
+
const matches = matcher.exec(trace);
|
|
34
|
+
if (matches)
|
|
35
|
+
startLine = matches[1];
|
|
36
|
+
throw new Error(`Error on ${contractFile}:
|
|
37
|
+
${error}
|
|
38
|
+
${startLine ? `Near line ${startLine}` : ''}
|
|
39
|
+
Raw trace:
|
|
40
|
+
${trace}
|
|
41
|
+
`);
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`Error on ${contractFile}:
|
|
44
|
+
${JSON.stringify(output.error, null, 2)}
|
|
45
|
+
`);
|
|
46
|
+
}
|
|
47
|
+
const abi = output.analysis;
|
|
48
|
+
return abi;
|
|
49
|
+
};
|
|
50
|
+
exports.generateInterface = generateInterface;
|
|
51
|
+
const generateInterfaceFile = ({ contractFile, abi, }) => {
|
|
52
|
+
const contractName = core_1.getContractNameFromPath(contractFile);
|
|
53
|
+
const variableName = core_1.toCamelCase(contractName, true);
|
|
54
|
+
const abiString = JSON.stringify(abi, null, 2);
|
|
55
|
+
const fileContents = `import { ClarityAbi } from '@clarigen/core';
|
|
56
|
+
|
|
57
|
+
// prettier-ignore
|
|
58
|
+
export const ${variableName}Interface: ClarityAbi = ${abiString};
|
|
59
|
+
`;
|
|
60
|
+
return fileContents;
|
|
61
|
+
};
|
|
62
|
+
exports.generateInterfaceFile = generateInterfaceFile;
|
|
63
|
+
const generateIndexFile = ({ contractFile, address, }) => {
|
|
64
|
+
const contractName = core_1.getContractNameFromPath(contractFile);
|
|
65
|
+
const contractTitle = core_1.toCamelCase(contractName, true);
|
|
66
|
+
const varName = core_1.toCamelCase(contractName);
|
|
67
|
+
const contractType = `${contractTitle}Contract`;
|
|
68
|
+
const fileContents = `import { proxy, BaseProvider, Contract } from '@clarigen/core';
|
|
69
|
+
import type { ${contractType} } from './types';
|
|
70
|
+
import { ${contractTitle}Interface } from './abi';
|
|
71
|
+
export type { ${contractType} } from './types';
|
|
72
|
+
|
|
73
|
+
export const ${varName}Contract = (provider: BaseProvider) => {
|
|
74
|
+
const contract = proxy<${contractType}>(${contractTitle}Interface, provider);
|
|
75
|
+
return contract;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const ${varName}Info: Contract<${contractType}> = {
|
|
79
|
+
contract: ${varName}Contract,
|
|
80
|
+
address: '${address}',
|
|
81
|
+
contractFile: '${contractFile}',
|
|
82
|
+
};
|
|
83
|
+
`;
|
|
84
|
+
return fileContents;
|
|
85
|
+
};
|
|
86
|
+
exports.generateIndexFile = generateIndexFile;
|
|
87
|
+
const generateTypesFile = (abi, contractName) => {
|
|
88
|
+
const name = core_1.toCamelCase(contractName, true);
|
|
89
|
+
const typings = declaration_1.makeTypes(abi);
|
|
90
|
+
const fileContents = `import { ClarityTypes, Transaction } from '@clarigen/core';
|
|
91
|
+
|
|
92
|
+
// prettier-ignore
|
|
93
|
+
export interface ${name}Contract {
|
|
94
|
+
${typings}
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
return fileContents;
|
|
98
|
+
};
|
|
99
|
+
exports.generateTypesFile = generateTypesFile;
|
|
100
|
+
const generateProjectIndexFile = (config) => {
|
|
101
|
+
const imports = [];
|
|
102
|
+
const exports = [];
|
|
103
|
+
const contractMap = [];
|
|
104
|
+
let accounts = '';
|
|
105
|
+
if ('accounts' in config) {
|
|
106
|
+
const accountLines = Object.keys(config.accounts).map((key) => {
|
|
107
|
+
const account = config.accounts[key];
|
|
108
|
+
return `"${key}": {
|
|
109
|
+
mnemonic: "${account.mnemonic}",
|
|
110
|
+
balance: ${account.balance.toString()}n,
|
|
111
|
+
address: "${account.address}",
|
|
112
|
+
},`;
|
|
113
|
+
});
|
|
114
|
+
accounts = `\n\n// prettier-ignore
|
|
115
|
+
export const accounts = {
|
|
116
|
+
${accountLines.join('\n ')}
|
|
117
|
+
};`;
|
|
118
|
+
}
|
|
119
|
+
config.contracts.forEach((contract) => {
|
|
120
|
+
const contractName = core_1.getContractNameFromPath(contract.file);
|
|
121
|
+
const contractVar = core_1.toCamelCase(contractName);
|
|
122
|
+
const contractInfo = `${contractVar}Info`;
|
|
123
|
+
const contractInterface = `${core_1.toCamelCase(contractName, true)}Contract`;
|
|
124
|
+
const dirName = path_1.dirname(contract.file);
|
|
125
|
+
const importPath = `'./${path_1.join(dirName || '.', contractName)}'`;
|
|
126
|
+
const _import = `import { ${contractInfo} } from ${importPath};`;
|
|
127
|
+
imports.push(_import);
|
|
128
|
+
const _export = `export type { ${contractInterface} } from ${importPath};`;
|
|
129
|
+
exports.push(_export);
|
|
130
|
+
const map = `${contractVar}: ${contractInfo},`;
|
|
131
|
+
contractMap.push(map);
|
|
132
|
+
});
|
|
133
|
+
const file = `${imports.join('\n')}
|
|
134
|
+
${exports.join('\n')}
|
|
135
|
+
|
|
136
|
+
export const contracts = {
|
|
137
|
+
${contractMap.join('\n ')}
|
|
138
|
+
};${accounts}
|
|
139
|
+
`;
|
|
140
|
+
return file;
|
|
141
|
+
};
|
|
142
|
+
exports.generateProjectIndexFile = generateProjectIndexFile;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.run = void 0;
|
|
14
|
+
var command_1 = require("@oclif/command");
|
|
15
|
+
Object.defineProperty(exports, "run", { enumerable: true, get: function () { return command_1.run; } });
|
|
16
|
+
__exportStar(require("./config"), exports);
|
|
17
|
+
__exportStar(require("./generate/declaration"), exports);
|
|
18
|
+
__exportStar(require("./generate/files"), exports);
|
|
19
|
+
__exportStar(require("./commands"), exports);
|
package/dist/start.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const errors_1 = require("@oclif/errors");
|
|
7
|
+
const flush_1 = __importDefault(require("@oclif/command/flush"));
|
|
8
|
+
const index_1 = require("./index");
|
|
9
|
+
index_1.run().then(flush_1.default, errors_1.handle);
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateProject = exports.generateFilesForContract = void 0;
|
|
4
|
+
const files_1 = require("./generate/files");
|
|
5
|
+
const core_1 = require("@clarigen/core");
|
|
6
|
+
const native_bin_1 = require("@clarigen/native-bin");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const promises_1 = require("fs/promises");
|
|
9
|
+
const config_1 = require("./config");
|
|
10
|
+
const generateFilesForContract = async ({ contractFile: _contractFile, outputFolder, provider, contractAddress, dirName, }) => {
|
|
11
|
+
const contractFile = path_1.resolve(process.cwd(), _contractFile);
|
|
12
|
+
const contractName = core_1.getContractNameFromPath(contractFile);
|
|
13
|
+
const abi = await files_1.generateInterface({
|
|
14
|
+
contractFile,
|
|
15
|
+
provider,
|
|
16
|
+
contractAddress,
|
|
17
|
+
});
|
|
18
|
+
const typesFile = files_1.generateTypesFile(abi, contractName);
|
|
19
|
+
if (!contractAddress && process.env.NODE_ENV !== 'test') {
|
|
20
|
+
console.warn('Please provide an address with every contract.');
|
|
21
|
+
}
|
|
22
|
+
const indexFile = files_1.generateIndexFile({
|
|
23
|
+
contractFile: path_1.relative(process.cwd(), contractFile),
|
|
24
|
+
address: contractAddress || '',
|
|
25
|
+
});
|
|
26
|
+
const abiFile = files_1.generateInterfaceFile({ contractFile, abi });
|
|
27
|
+
const baseDir = outputFolder || path_1.resolve(process.cwd(), `tmp/${contractName}`);
|
|
28
|
+
const outputPath = path_1.resolve(baseDir, dirName || '.', contractName);
|
|
29
|
+
await promises_1.mkdir(outputPath, { recursive: true });
|
|
30
|
+
await promises_1.writeFile(path_1.resolve(outputPath, 'abi.ts'), abiFile);
|
|
31
|
+
await promises_1.writeFile(path_1.resolve(outputPath, 'index.ts'), indexFile);
|
|
32
|
+
await promises_1.writeFile(path_1.resolve(outputPath, 'types.ts'), typesFile);
|
|
33
|
+
};
|
|
34
|
+
exports.generateFilesForContract = generateFilesForContract;
|
|
35
|
+
const generateProject = async (projectPath) => {
|
|
36
|
+
const configFile = await config_1.getConfigFile(projectPath);
|
|
37
|
+
const { contractsDir, outputDir, contracts } = configFile;
|
|
38
|
+
const outputFolder = path_1.resolve(projectPath, outputDir);
|
|
39
|
+
const provider = await native_bin_1.createClarityBin();
|
|
40
|
+
// this needs to be serial
|
|
41
|
+
for (const contract of contracts) {
|
|
42
|
+
const contractFile = path_1.resolve(projectPath, contractsDir, contract.file);
|
|
43
|
+
const dirName = path_1.dirname(contract.file);
|
|
44
|
+
await exports.generateFilesForContract({
|
|
45
|
+
contractFile,
|
|
46
|
+
outputFolder: outputFolder,
|
|
47
|
+
provider,
|
|
48
|
+
contractAddress: contract.address,
|
|
49
|
+
dirName,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const indexFile = files_1.generateProjectIndexFile(configFile);
|
|
53
|
+
const indexPath = path_1.resolve(outputFolder, 'index.ts');
|
|
54
|
+
await promises_1.writeFile(indexPath, indexFile);
|
|
55
|
+
};
|
|
56
|
+
exports.generateProject = generateProject;
|
package/package.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
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": "0.
|
|
5
|
+
"version": "0.3.0",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"files": [
|
|
9
9
|
"dist",
|
|
10
10
|
"src",
|
|
11
|
-
"
|
|
11
|
+
"oclif.manifest.json"
|
|
12
12
|
],
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=10"
|
|
@@ -18,10 +18,11 @@
|
|
|
18
18
|
"start": "ts-node-script src/start.ts",
|
|
19
19
|
"compile": "ncc build src/index.ts --no-source-map-register -e @oclif/command -e @oclif/errors",
|
|
20
20
|
"build-single-file": "yarn compile && oclif-dev readme",
|
|
21
|
-
"build": "
|
|
21
|
+
"build": "rm -rf dist && tsc -b",
|
|
22
22
|
"test": "tsdx test",
|
|
23
23
|
"lint": "tsdx lint",
|
|
24
|
-
"typecheck": "tsc --noEmit"
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"prepublishOnly": "yarn build"
|
|
25
26
|
},
|
|
26
27
|
"bin": {
|
|
27
28
|
"clarigen": "./bin/run"
|
|
@@ -37,25 +38,26 @@
|
|
|
37
38
|
"trailingComma": "es5"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
|
-
"@oclif/config": "^1.17.0",
|
|
41
41
|
"@oclif/dev-cli": "^1.26.0",
|
|
42
42
|
"@oclif/errors": "^1.3.4",
|
|
43
43
|
"@vercel/ncc": "0.27.0",
|
|
44
|
-
"chokidar": "3.5.1",
|
|
45
44
|
"oclif": "^1.16.1",
|
|
46
45
|
"ts-node": "^9.1.1"
|
|
47
46
|
},
|
|
48
47
|
"dependencies": {
|
|
49
|
-
"@clarigen/core": "
|
|
50
|
-
"@clarigen/native-bin": "
|
|
48
|
+
"@clarigen/core": "0.2.3",
|
|
49
|
+
"@clarigen/native-bin": "0.2.7",
|
|
51
50
|
"@ltd/j-toml": "1.12.2",
|
|
52
51
|
"@oclif/command": "^1.8.0",
|
|
52
|
+
"@oclif/config": "^1.17.0",
|
|
53
|
+
"@oclif/plugin-help": "3.2.3",
|
|
53
54
|
"@stacks/wallet-sdk": "1.0.0-wallet-sdk.4",
|
|
54
55
|
"chalk": "4.1.0",
|
|
56
|
+
"chokidar": "3.5.1",
|
|
55
57
|
"ora": "5.4.0"
|
|
56
58
|
},
|
|
57
59
|
"publishConfig": {
|
|
58
60
|
"access": "public"
|
|
59
61
|
},
|
|
60
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "1a82667ab26f312b401cbbd84aca4d1879e7e1a6"
|
|
61
63
|
}
|
package/src/clarinet-config.ts
CHANGED
|
@@ -24,12 +24,9 @@ export async function getClarinetDevConfig(
|
|
|
24
24
|
): Promise<ClarinetDevConfig> {
|
|
25
25
|
const baseConfigPath = resolve(folder, 'settings', 'Devnet.toml');
|
|
26
26
|
const configContents = await readFile(baseConfigPath, { encoding: 'utf-8' });
|
|
27
|
-
const config = (parse(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
'\n',
|
|
31
|
-
false
|
|
32
|
-
) as unknown) as ClarinetDevConfig;
|
|
27
|
+
const config = (parse(configContents, 1.0, '\n', true, {
|
|
28
|
+
longer: true,
|
|
29
|
+
}) as unknown) as ClarinetDevConfig;
|
|
33
30
|
return config;
|
|
34
31
|
}
|
|
35
32
|
|
|
@@ -49,7 +46,7 @@ export async function getClarinetConfig(folder: string) {
|
|
|
49
46
|
configContents,
|
|
50
47
|
1.0,
|
|
51
48
|
'\n',
|
|
52
|
-
|
|
49
|
+
true
|
|
53
50
|
) as unknown) as ClarinetConfig;
|
|
54
51
|
return config;
|
|
55
52
|
}
|
package/src/commands/contract.ts
CHANGED
package/src/commands/index.ts
CHANGED
|
@@ -1,3 +1,67 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Command, flags } from '@oclif/command';
|
|
2
|
+
import { generateProject } from '../utils';
|
|
3
|
+
import { getConfigFile } from '../config';
|
|
4
|
+
import { watch } from 'chokidar';
|
|
5
|
+
import { basename } from 'path';
|
|
6
|
+
import { red, green } from 'chalk';
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
8
|
+
const ora = require('ora');
|
|
2
9
|
|
|
3
|
-
export
|
|
10
|
+
export class Generate extends Command {
|
|
11
|
+
static description = `Generate project files`;
|
|
12
|
+
static strict = true;
|
|
13
|
+
static hidden = false;
|
|
14
|
+
|
|
15
|
+
static flags = {
|
|
16
|
+
help: flags.help({ char: 'h' }),
|
|
17
|
+
watch: flags.boolean({
|
|
18
|
+
char: 'w',
|
|
19
|
+
description: 'Watch for changes to your contracts',
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
static args = [];
|
|
24
|
+
|
|
25
|
+
async run() {
|
|
26
|
+
const { flags } = this.parse(Generate);
|
|
27
|
+
const cwd = process.cwd();
|
|
28
|
+
|
|
29
|
+
if (flags.watch) {
|
|
30
|
+
const spinner = ora('Generating files').start();
|
|
31
|
+
const { contractsDir } = await getConfigFile(cwd);
|
|
32
|
+
const watcher = watch([contractsDir], {
|
|
33
|
+
cwd,
|
|
34
|
+
});
|
|
35
|
+
try {
|
|
36
|
+
await generateProject(cwd);
|
|
37
|
+
spinner.succeed(`Finished generating files. Watching for changes.`);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
40
|
+
spinner.fail(`Error generating files.\n${(error as any).message}`);
|
|
41
|
+
}
|
|
42
|
+
watcher.on('change', async (path) => {
|
|
43
|
+
const file = basename(path);
|
|
44
|
+
spinner.clear();
|
|
45
|
+
spinner.start(`Change detected for ${green(file)}, generating.`);
|
|
46
|
+
try {
|
|
47
|
+
await generateProject(cwd);
|
|
48
|
+
spinner.succeed(
|
|
49
|
+
`Finished generating files for ${green(
|
|
50
|
+
file
|
|
51
|
+
)}. Watching for changes.`
|
|
52
|
+
);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
55
|
+
const msg = (error as any).message;
|
|
56
|
+
spinner.fail(`Error after saving ${red(file)}.\n${msg}`);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
process.on('SIGINT', async () => {
|
|
60
|
+
await watcher.close();
|
|
61
|
+
process.exit();
|
|
62
|
+
});
|
|
63
|
+
} else {
|
|
64
|
+
await generateProject(cwd);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
package/src/generate/files.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
getContractNameFromPath,
|
|
9
9
|
} from '@clarigen/core';
|
|
10
10
|
import { makeTypes } from './declaration';
|
|
11
|
-
import { ConfigContract, ConfigFile } from '
|
|
11
|
+
import { ConfigContract, ConfigFile } from '../config';
|
|
12
12
|
import { dirname, resolve, join } from 'path';
|
|
13
13
|
|
|
14
14
|
export const generateInterface = async ({
|
|
@@ -31,7 +31,10 @@ export const generateInterface = async ({
|
|
|
31
31
|
'--costs',
|
|
32
32
|
'--assets',
|
|
33
33
|
]);
|
|
34
|
-
if (
|
|
34
|
+
if (
|
|
35
|
+
receipt.stderr &&
|
|
36
|
+
!receipt.stderr.includes('Used unimplemented cost function')
|
|
37
|
+
) {
|
|
35
38
|
throw new Error(`Error on ${contractFile}:
|
|
36
39
|
${receipt.stderr}
|
|
37
40
|
`);
|
|
@@ -133,8 +136,19 @@ export const generateProjectIndexFile = (config: ConfigFile) => {
|
|
|
133
136
|
|
|
134
137
|
let accounts = '';
|
|
135
138
|
if ('accounts' in config) {
|
|
139
|
+
const accountLines = Object.keys(config.accounts).map((key) => {
|
|
140
|
+
const account = config.accounts[key];
|
|
141
|
+
return `"${key}": {
|
|
142
|
+
mnemonic: "${account.mnemonic}",
|
|
143
|
+
balance: ${account.balance.toString()}n,
|
|
144
|
+
address: "${account.address}",
|
|
145
|
+
},`;
|
|
146
|
+
});
|
|
147
|
+
|
|
136
148
|
accounts = `\n\n// prettier-ignore
|
|
137
|
-
export const accounts =
|
|
149
|
+
export const accounts = {
|
|
150
|
+
${accountLines.join('\n ')}
|
|
151
|
+
};`;
|
|
138
152
|
}
|
|
139
153
|
|
|
140
154
|
config.contracts.forEach((contract) => {
|
package/src/index.ts
CHANGED
package/CHANGELOG.md
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# @clarigen/cli
|
|
2
|
-
|
|
3
|
-
## 0.2.0
|
|
4
|
-
### Minor Changes
|
|
5
|
-
|
|
6
|
-
- fd1b36b: This version contains a number of big changes!
|
|
7
|
-
|
|
8
|
-
My favorite addition is the addition of a `@clarigen/native-bin` package. This removes the need to manually build and specify your local version of the `clarity-cli` binary. Most of this code was taken from the `@blockstack/clarity-native-bin` library. Users on Apple Silicon will also automatically download a pre-built binary (which was not previously available).
|
|
9
|
-
|
|
10
|
-
These changes should really improve DX for project setup, as well as the ability to run Clarigen in CI.
|
|
11
|
-
|
|
12
|
-
Other changes:
|
|
13
|
-
|
|
14
|
-
- **Breaking change** JS types for functions that return `uint` or `int` types now use the `BigInt` native JavaScript type.
|
|
15
|
-
- Although this is a breaking change, this is not a major update. Clarigen is still 0.x and is not in wide use.
|
|
16
|
-
- **Breaking change**: Projects that have a `clarinet` configuration now look for the `Devnet.toml` file (instead of `Development.toml`)
|
|
17
|
-
- Clarity type conversion (between hex and JS) has been consolidated into the `core` library
|
|
18
|
-
- Bug fixes for boolean type conversion for function parameters
|
|
19
|
-
- Added `get-stx-balance` test utility function
|
|
20
|
-
- Added util for getting boot contract identifiers
|
|
21
|
-
- `clarity-cli` is now launched in testnet mode by default
|
|
22
|
-
- Added changesets for better release management
|
|
23
|
-
- Added Github Actions CI to this package
|
|
24
|
-
|
|
25
|
-
### Patch Changes
|
|
26
|
-
|
|
27
|
-
- Updated dependencies [fd1b36b]
|
|
28
|
-
- @clarigen/core@0.2.0
|
|
29
|
-
- @clarigen/native-bin@0.2.0
|
package/src/commands/generate.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Command, flags } from '@oclif/command';
|
|
2
|
-
import { generateProject } from '../utils';
|
|
3
|
-
import { getConfigFile } from '../config';
|
|
4
|
-
import { watch } from 'chokidar';
|
|
5
|
-
import { basename } from 'path';
|
|
6
|
-
import { red, green } from 'chalk';
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
8
|
-
const ora = require('ora');
|
|
9
|
-
|
|
10
|
-
export class Generate extends Command {
|
|
11
|
-
static description = `Generate project files`;
|
|
12
|
-
static strict = true;
|
|
13
|
-
|
|
14
|
-
static flags = {
|
|
15
|
-
help: flags.help({ char: 'h' }),
|
|
16
|
-
watch: flags.boolean({
|
|
17
|
-
char: 'w',
|
|
18
|
-
description: 'Watch for changes to your contracts',
|
|
19
|
-
}),
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
static args = [];
|
|
23
|
-
|
|
24
|
-
async run() {
|
|
25
|
-
const { flags } = this.parse(Generate);
|
|
26
|
-
const cwd = process.cwd();
|
|
27
|
-
|
|
28
|
-
if (flags.watch) {
|
|
29
|
-
const spinner = ora('Generating files').start();
|
|
30
|
-
const { contractsDir } = await getConfigFile(cwd);
|
|
31
|
-
const watcher = watch([contractsDir], {
|
|
32
|
-
cwd,
|
|
33
|
-
});
|
|
34
|
-
try {
|
|
35
|
-
await generateProject(cwd);
|
|
36
|
-
spinner.succeed(`Finished generating files. Watching for changes.`);
|
|
37
|
-
} catch (error: any) {
|
|
38
|
-
spinner.fail(`Error generating files.\n${error.message}`);
|
|
39
|
-
}
|
|
40
|
-
watcher.on('change', async (path) => {
|
|
41
|
-
const file = basename(path);
|
|
42
|
-
spinner.clear();
|
|
43
|
-
spinner.start(`Change detected for ${green(file)}, generating.`);
|
|
44
|
-
try {
|
|
45
|
-
await generateProject(cwd);
|
|
46
|
-
spinner.succeed(
|
|
47
|
-
`Finished generating files for ${green(
|
|
48
|
-
file
|
|
49
|
-
)}. Watching for changes.`
|
|
50
|
-
);
|
|
51
|
-
} catch (error: any) {
|
|
52
|
-
spinner.fail(`Error after saving ${red(file)}.\n${error.message}`);
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
process.on('SIGINT', async () => {
|
|
56
|
-
await watcher.close();
|
|
57
|
-
process.exit();
|
|
58
|
-
});
|
|
59
|
-
} else {
|
|
60
|
-
await generateProject(cwd);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|