@clarigen/cli 1.0.0-next.9 → 2.0.1
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 +1 -31
- package/dist/index.cjs +1304 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +432 -0
- package/dist/index.js +1239 -17
- package/dist/index.js.map +1 -0
- package/dist/run-cli.cjs +1451 -0
- package/dist/run-cli.cjs.map +1 -0
- package/dist/run-cli.d.ts +1 -0
- package/dist/run-cli.js +1455 -0
- package/dist/run-cli.js.map +1 -0
- package/package.json +36 -51
- package/bin/run +0 -7
- package/dist/clarinet-config.js +0 -70
- package/dist/commands/index.js +0 -65
- package/dist/config.js +0 -54
- package/dist/generate/declaration.js +0 -120
- package/dist/generate/files.js +0 -147
- package/dist/start.js +0 -9
- package/dist/utils.js +0 -53
- package/src/clarinet-config.ts +0 -127
- package/src/commands/index.ts +0 -67
- package/src/config.ts +0 -78
- package/src/generate/declaration.ts +0 -116
- package/src/generate/files.ts +0 -181
- package/src/index.ts +0 -5
- package/src/start.ts +0 -5
- package/src/utils.ts +0 -78
package/dist/generate/files.js
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
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 path_1 = require("path");
|
|
7
|
-
const __1 = require("..");
|
|
8
|
-
const generateInterface = async ({ provider, contractFile, contractAddress, contractName, }) => {
|
|
9
|
-
const receipt = await provider.runCommand([
|
|
10
|
-
'launch',
|
|
11
|
-
`${contractAddress}.${contractName}`,
|
|
12
|
-
contractFile,
|
|
13
|
-
provider.dbFilePath,
|
|
14
|
-
'--output_analysis',
|
|
15
|
-
'--costs',
|
|
16
|
-
'--assets',
|
|
17
|
-
]);
|
|
18
|
-
if ((0, native_bin_1.hasStdErr)(receipt.stderr)) {
|
|
19
|
-
throw new Error(`Error on ${contractFile}:
|
|
20
|
-
${receipt.stderr}
|
|
21
|
-
`);
|
|
22
|
-
}
|
|
23
|
-
const output = JSON.parse(receipt.stdout);
|
|
24
|
-
if (output.error) {
|
|
25
|
-
const { initialization } = output.error;
|
|
26
|
-
if (initialization?.includes('\nNear:\n')) {
|
|
27
|
-
const [error, trace] = initialization.split('\nNear:\n');
|
|
28
|
-
let startLine = '';
|
|
29
|
-
const matcher = /start_line: (\d+),/;
|
|
30
|
-
const matches = matcher.exec(trace);
|
|
31
|
-
if (matches)
|
|
32
|
-
startLine = matches[1];
|
|
33
|
-
throw new Error(`Error on ${contractFile}:
|
|
34
|
-
${error}
|
|
35
|
-
${startLine ? `Near line ${startLine}` : ''}
|
|
36
|
-
Raw trace:
|
|
37
|
-
${trace}
|
|
38
|
-
`);
|
|
39
|
-
}
|
|
40
|
-
throw new Error(`Error on ${contractFile}:
|
|
41
|
-
${JSON.stringify(output.error, null, 2)}
|
|
42
|
-
`);
|
|
43
|
-
}
|
|
44
|
-
const abi = output.analysis;
|
|
45
|
-
return abi;
|
|
46
|
-
};
|
|
47
|
-
exports.generateInterface = generateInterface;
|
|
48
|
-
const generateInterfaceFile = ({ contractName, abi, }) => {
|
|
49
|
-
const variableName = (0, core_1.toCamelCase)(contractName, true);
|
|
50
|
-
const { clarity_version, ...rest } = abi;
|
|
51
|
-
const abiString = JSON.stringify(rest, null, 2);
|
|
52
|
-
const fileContents = `import { ClarityAbi } from '@clarigen/core';
|
|
53
|
-
|
|
54
|
-
// prettier-ignore
|
|
55
|
-
export const ${variableName}Interface: ClarityAbi = ${abiString};
|
|
56
|
-
`;
|
|
57
|
-
return fileContents;
|
|
58
|
-
};
|
|
59
|
-
exports.generateInterfaceFile = generateInterfaceFile;
|
|
60
|
-
const generateIndexFile = ({ contractFile, contractAddress, contractName, }) => {
|
|
61
|
-
const contractTitle = (0, core_1.toCamelCase)(contractName, true);
|
|
62
|
-
const varName = (0, core_1.toCamelCase)(contractName);
|
|
63
|
-
const contractType = `${contractTitle}Contract`;
|
|
64
|
-
const interfaceVar = `${contractTitle}Interface`;
|
|
65
|
-
const fileContents = `import { pureProxy, Contract } from '@clarigen/core';
|
|
66
|
-
import type { ${contractType} } from './types';
|
|
67
|
-
import { ${interfaceVar} } from './abi';
|
|
68
|
-
export type { ${contractType} } from './types';
|
|
69
|
-
|
|
70
|
-
export function ${varName}Contract(contractAddress: string, contractName: string) {
|
|
71
|
-
return pureProxy<${contractType}>({
|
|
72
|
-
abi: ${interfaceVar},
|
|
73
|
-
contractAddress,
|
|
74
|
-
contractName,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export const ${varName}Info: Contract<${contractType}> = {
|
|
79
|
-
contract: ${varName}Contract,
|
|
80
|
-
address: '${contractAddress}',
|
|
81
|
-
contractFile: '${contractFile}',
|
|
82
|
-
name: '${contractName}',
|
|
83
|
-
abi: ${interfaceVar},
|
|
84
|
-
};
|
|
85
|
-
`;
|
|
86
|
-
return fileContents;
|
|
87
|
-
};
|
|
88
|
-
exports.generateIndexFile = generateIndexFile;
|
|
89
|
-
const generateTypesFile = (abi, contractName) => {
|
|
90
|
-
const name = (0, core_1.toCamelCase)(contractName, true);
|
|
91
|
-
const typings = (0, __1.makePureTypes)(abi);
|
|
92
|
-
const fileContents = `import { ClarityTypes, ContractCalls } from '@clarigen/core';
|
|
93
|
-
|
|
94
|
-
// prettier-ignore
|
|
95
|
-
export interface ${name}Contract {
|
|
96
|
-
${typings}
|
|
97
|
-
}
|
|
98
|
-
`;
|
|
99
|
-
return fileContents;
|
|
100
|
-
};
|
|
101
|
-
exports.generateTypesFile = generateTypesFile;
|
|
102
|
-
const generateProjectIndexFile = (config) => {
|
|
103
|
-
const imports = [
|
|
104
|
-
"import type { ContractInstances } from '@clarigen/core';",
|
|
105
|
-
];
|
|
106
|
-
const exports = [];
|
|
107
|
-
const contractMap = [];
|
|
108
|
-
let accounts = '';
|
|
109
|
-
if ('accounts' in config) {
|
|
110
|
-
const accountLines = Object.keys(config.accounts).map((key) => {
|
|
111
|
-
const account = config.accounts[key];
|
|
112
|
-
return `"${key}": {
|
|
113
|
-
mnemonic: "${account.mnemonic}",
|
|
114
|
-
balance: ${account.balance.toString()}n,
|
|
115
|
-
address: "${account.address}",
|
|
116
|
-
},`;
|
|
117
|
-
});
|
|
118
|
-
accounts = `\n\n// prettier-ignore
|
|
119
|
-
export const accounts = {
|
|
120
|
-
${accountLines.join('\n ')}
|
|
121
|
-
};`;
|
|
122
|
-
}
|
|
123
|
-
config.contracts.forEach((contract) => {
|
|
124
|
-
const contractName = contract.name;
|
|
125
|
-
const contractVar = (0, core_1.toCamelCase)(contractName);
|
|
126
|
-
const contractInfo = `${contractVar}Info`;
|
|
127
|
-
const contractInterface = `${(0, core_1.toCamelCase)(contractName, true)}Contract`;
|
|
128
|
-
const dirName = (0, path_1.dirname)(contract.file);
|
|
129
|
-
const importPath = `'./${(0, path_1.join)(dirName || '.', contractName)}'`;
|
|
130
|
-
const _import = `import { ${contractInfo} } from ${importPath};`;
|
|
131
|
-
imports.push(_import);
|
|
132
|
-
const _export = `export type { ${contractInterface} } from ${importPath};`;
|
|
133
|
-
exports.push(_export);
|
|
134
|
-
const map = `${contractVar}: ${contractInfo},`;
|
|
135
|
-
contractMap.push(map);
|
|
136
|
-
});
|
|
137
|
-
const contractsType = `\nexport type Contracts = ContractInstances<typeof contracts>;\n`;
|
|
138
|
-
const file = `${imports.join('\n')}
|
|
139
|
-
${exports.join('\n')}
|
|
140
|
-
${contractsType}
|
|
141
|
-
export const contracts = {
|
|
142
|
-
${contractMap.join('\n ')}
|
|
143
|
-
};${accounts}
|
|
144
|
-
`;
|
|
145
|
-
return file;
|
|
146
|
-
};
|
|
147
|
-
exports.generateProjectIndexFile = generateProjectIndexFile;
|
package/dist/start.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
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
|
-
(0, index_1.run)().then(flush_1.default, errors_1.handle);
|
package/dist/utils.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
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 native_bin_1 = require("@clarigen/native-bin");
|
|
6
|
-
const path_1 = require("path");
|
|
7
|
-
const promises_1 = require("fs/promises");
|
|
8
|
-
const config_1 = require("./config");
|
|
9
|
-
const generateFilesForContract = async ({ contractFile: _contractFile, outputFolder, provider, contractAddress, dirName, contractName, }) => {
|
|
10
|
-
const contractFile = (0, path_1.resolve)(process.cwd(), _contractFile);
|
|
11
|
-
const abi = await (0, files_1.generateInterface)({
|
|
12
|
-
contractFile,
|
|
13
|
-
provider,
|
|
14
|
-
contractAddress,
|
|
15
|
-
contractName,
|
|
16
|
-
});
|
|
17
|
-
const typesFile = (0, files_1.generateTypesFile)(abi, contractName);
|
|
18
|
-
const indexFile = (0, files_1.generateIndexFile)({
|
|
19
|
-
contractFile: (0, path_1.relative)(process.cwd(), contractFile),
|
|
20
|
-
contractAddress: contractAddress,
|
|
21
|
-
contractName,
|
|
22
|
-
});
|
|
23
|
-
const abiFile = (0, files_1.generateInterfaceFile)({ contractName, abi });
|
|
24
|
-
const outputPath = (0, path_1.resolve)(outputFolder, dirName || '.', contractName);
|
|
25
|
-
await (0, promises_1.mkdir)(outputPath, { recursive: true });
|
|
26
|
-
await (0, promises_1.writeFile)((0, path_1.resolve)(outputPath, 'abi.ts'), abiFile);
|
|
27
|
-
await (0, promises_1.writeFile)((0, path_1.resolve)(outputPath, 'index.ts'), indexFile);
|
|
28
|
-
await (0, promises_1.writeFile)((0, path_1.resolve)(outputPath, 'types.ts'), typesFile);
|
|
29
|
-
};
|
|
30
|
-
exports.generateFilesForContract = generateFilesForContract;
|
|
31
|
-
const generateProject = async (projectPath) => {
|
|
32
|
-
const configFile = await (0, config_1.getProjectConfig)(projectPath);
|
|
33
|
-
const { contractsDir, outputDir, contracts } = configFile;
|
|
34
|
-
const outputFolder = (0, path_1.resolve)(projectPath, outputDir);
|
|
35
|
-
const provider = await (0, native_bin_1.createClarityBin)();
|
|
36
|
-
// this needs to be serial
|
|
37
|
-
for (const contract of contracts) {
|
|
38
|
-
const contractFile = (0, path_1.resolve)(projectPath, contractsDir, contract.file);
|
|
39
|
-
const dirName = (0, path_1.dirname)(contract.file);
|
|
40
|
-
await (0, exports.generateFilesForContract)({
|
|
41
|
-
contractFile,
|
|
42
|
-
outputFolder: outputFolder,
|
|
43
|
-
provider,
|
|
44
|
-
contractAddress: contract.address,
|
|
45
|
-
dirName,
|
|
46
|
-
contractName: contract.name,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
const indexFile = (0, files_1.generateProjectIndexFile)(configFile);
|
|
50
|
-
const indexPath = (0, path_1.resolve)(outputFolder, 'index.ts');
|
|
51
|
-
await (0, promises_1.writeFile)(indexPath, indexFile);
|
|
52
|
-
};
|
|
53
|
-
exports.generateProject = generateProject;
|
package/src/clarinet-config.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { parse } from '@ltd/j-toml';
|
|
2
|
-
import { resolve } from 'path';
|
|
3
|
-
import { readFile } from 'fs/promises';
|
|
4
|
-
import { ConfigContract } from './config';
|
|
5
|
-
import {
|
|
6
|
-
generateWallet,
|
|
7
|
-
getStxAddressFromAccount,
|
|
8
|
-
} from 'micro-stacks/wallet-sdk';
|
|
9
|
-
import { array as toposort } from 'toposort';
|
|
10
|
-
import { StacksNetworkVersion } from 'micro-stacks/crypto';
|
|
11
|
-
|
|
12
|
-
interface ClarinetConfigAccount {
|
|
13
|
-
mnemonic: string;
|
|
14
|
-
balance: bigint;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface ClarinetDevConfig {
|
|
18
|
-
network: {
|
|
19
|
-
name: string;
|
|
20
|
-
};
|
|
21
|
-
accounts: {
|
|
22
|
-
deployer: ClarinetConfigAccount;
|
|
23
|
-
[key: string]: ClarinetConfigAccount;
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function getClarinetDevConfig(
|
|
28
|
-
folder: string
|
|
29
|
-
): Promise<ClarinetDevConfig> {
|
|
30
|
-
const baseConfigPath = resolve(folder, 'settings', 'Devnet.toml');
|
|
31
|
-
const configContents = await readFile(baseConfigPath, { encoding: 'utf-8' });
|
|
32
|
-
const config = (parse(configContents, 1.0, '\n', true, {
|
|
33
|
-
longer: true,
|
|
34
|
-
}) as unknown) as ClarinetDevConfig;
|
|
35
|
-
return config;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface ClarinetContract {
|
|
39
|
-
path: string;
|
|
40
|
-
depends_on: string[];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface ClarinetContracts {
|
|
44
|
-
[name: string]: ClarinetContract;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export interface ClarinetConfig {
|
|
48
|
-
contracts: ClarinetContracts;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export async function getClarinetConfig(folder: string) {
|
|
52
|
-
const baseConfigPath = resolve(folder, 'Clarinet.toml');
|
|
53
|
-
const configContents = await readFile(baseConfigPath, { encoding: 'utf-8' });
|
|
54
|
-
const config = (parse(
|
|
55
|
-
configContents,
|
|
56
|
-
1.0,
|
|
57
|
-
'\n',
|
|
58
|
-
true
|
|
59
|
-
) as unknown) as ClarinetConfig;
|
|
60
|
-
return config;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export async function getContractsFromClarinet(
|
|
64
|
-
folder: string,
|
|
65
|
-
accounts: ClarinetAccounts
|
|
66
|
-
): Promise<ConfigContract[]> {
|
|
67
|
-
const clarinetConfig = await getClarinetConfig(folder);
|
|
68
|
-
const deployerAddress = accounts.deployer.address;
|
|
69
|
-
const sortedContracts = sortClarinetContracts(clarinetConfig.contracts);
|
|
70
|
-
const contracts: ConfigContract[] = sortedContracts.map((contractName) => {
|
|
71
|
-
const info = clarinetConfig.contracts[contractName];
|
|
72
|
-
const file = info.path.replace(/^contracts\//, '');
|
|
73
|
-
return {
|
|
74
|
-
file,
|
|
75
|
-
address: deployerAddress,
|
|
76
|
-
name: contractName,
|
|
77
|
-
};
|
|
78
|
-
});
|
|
79
|
-
return contracts;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function sortClarinetContracts(contractsConfig: ClarinetContracts) {
|
|
83
|
-
const edges: [string, string][] = [];
|
|
84
|
-
const nodes: string[] = [];
|
|
85
|
-
Object.entries(contractsConfig).forEach(([contractName, info]) => {
|
|
86
|
-
nodes.push(contractName);
|
|
87
|
-
info.depends_on.forEach((dependency) =>
|
|
88
|
-
edges.push([contractName, dependency])
|
|
89
|
-
);
|
|
90
|
-
});
|
|
91
|
-
const sorted = toposort(nodes, edges).reverse();
|
|
92
|
-
return sorted;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export interface ClarinetAccount extends ClarinetConfigAccount {
|
|
96
|
-
address: string;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export interface ClarinetAccounts {
|
|
100
|
-
deployer: ClarinetAccount;
|
|
101
|
-
[name: string]: ClarinetAccount;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export async function getClarinetAccounts(
|
|
105
|
-
folder: string
|
|
106
|
-
): Promise<ClarinetAccounts> {
|
|
107
|
-
const devConfig = await getClarinetDevConfig(folder);
|
|
108
|
-
const accountEntries = await Promise.all(
|
|
109
|
-
Object.entries(devConfig.accounts).map(async ([key, info]) => {
|
|
110
|
-
const wallet = await generateWallet(info.mnemonic, 'password');
|
|
111
|
-
const [account] = wallet.accounts;
|
|
112
|
-
const address = getStxAddressFromAccount(
|
|
113
|
-
account,
|
|
114
|
-
StacksNetworkVersion.testnetP2PKH
|
|
115
|
-
);
|
|
116
|
-
return [
|
|
117
|
-
key,
|
|
118
|
-
{
|
|
119
|
-
...info,
|
|
120
|
-
address,
|
|
121
|
-
},
|
|
122
|
-
];
|
|
123
|
-
})
|
|
124
|
-
);
|
|
125
|
-
const accounts: ClarinetAccounts = Object.fromEntries(accountEntries);
|
|
126
|
-
return accounts;
|
|
127
|
-
}
|
package/src/commands/index.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { Command, flags } from '@oclif/command';
|
|
2
|
-
import { generateProject } from '../utils';
|
|
3
|
-
import { getProjectConfig } 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
|
-
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 getProjectConfig(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/config.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { resolve, join, relative } from 'path';
|
|
2
|
-
import { readFile, access } from 'fs/promises';
|
|
3
|
-
import { constants } from 'fs';
|
|
4
|
-
import {
|
|
5
|
-
ClarinetAccounts,
|
|
6
|
-
getClarinetAccounts,
|
|
7
|
-
getContractsFromClarinet,
|
|
8
|
-
} from './clarinet-config';
|
|
9
|
-
|
|
10
|
-
export interface ConfigContract {
|
|
11
|
-
address: string;
|
|
12
|
-
file: string;
|
|
13
|
-
name: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface ConfigFileContents {
|
|
17
|
-
outputDir: string;
|
|
18
|
-
clarinet: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface ConfigFile extends ConfigFileContents {
|
|
22
|
-
contractsDir: string;
|
|
23
|
-
contracts: ConfigContract[];
|
|
24
|
-
accounts: ClarinetAccounts;
|
|
25
|
-
clarinet: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const defaultConfigFile: ConfigFileContents = {
|
|
29
|
-
outputDir: 'src/clarigen',
|
|
30
|
-
clarinet: '.',
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export function configFilePath(rootPath: string) {
|
|
34
|
-
return resolve(rootPath, 'clarigen.config.json');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export async function configFileExists(configPath: string): Promise<boolean> {
|
|
38
|
-
try {
|
|
39
|
-
await access(configPath, constants.R_OK);
|
|
40
|
-
return true;
|
|
41
|
-
} catch (error) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export async function getConfigFile(
|
|
47
|
-
rootPath: string
|
|
48
|
-
): Promise<ConfigFileContents> {
|
|
49
|
-
const fullPath = configFilePath(rootPath);
|
|
50
|
-
const exists = await configFileExists(fullPath);
|
|
51
|
-
if (exists) {
|
|
52
|
-
const configContents = await readFile(fullPath, { encoding: 'utf-8' });
|
|
53
|
-
const configFile: ConfigFileContents = JSON.parse(configContents);
|
|
54
|
-
return {
|
|
55
|
-
...defaultConfigFile,
|
|
56
|
-
...configFile,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return defaultConfigFile;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export async function getProjectConfig(rootPath: string): Promise<ConfigFile> {
|
|
63
|
-
const configFile = await getConfigFile(rootPath);
|
|
64
|
-
const clarinetPath = resolve(rootPath, configFile.clarinet || '.');
|
|
65
|
-
const accounts = await getClarinetAccounts(clarinetPath);
|
|
66
|
-
const contracts = await getContractsFromClarinet(clarinetPath, accounts);
|
|
67
|
-
const contractsDir = relative(
|
|
68
|
-
process.cwd(),
|
|
69
|
-
join(configFile.clarinet, 'contracts')
|
|
70
|
-
);
|
|
71
|
-
return {
|
|
72
|
-
...configFile,
|
|
73
|
-
contracts,
|
|
74
|
-
contractsDir,
|
|
75
|
-
accounts,
|
|
76
|
-
clarinet: configFile.clarinet || '.',
|
|
77
|
-
};
|
|
78
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isClarityAbiBuffer,
|
|
3
|
-
isClarityAbiList,
|
|
4
|
-
isClarityAbiOptional,
|
|
5
|
-
isClarityAbiPrimitive,
|
|
6
|
-
isClarityAbiResponse,
|
|
7
|
-
isClarityAbiStringAscii,
|
|
8
|
-
isClarityAbiStringUtf8,
|
|
9
|
-
isClarityAbiTuple,
|
|
10
|
-
} from 'micro-stacks/transactions';
|
|
11
|
-
import { ClarityAbiFunction, ClarityAbiType } from 'micro-stacks/clarity';
|
|
12
|
-
import { toCamelCase, ClarityAbi } from '@clarigen/core';
|
|
13
|
-
import { check } from 'reserved-words';
|
|
14
|
-
|
|
15
|
-
export const jsTypeFromAbiType = (
|
|
16
|
-
val: ClarityAbiType,
|
|
17
|
-
isArgument = false
|
|
18
|
-
): string => {
|
|
19
|
-
if (isClarityAbiPrimitive(val)) {
|
|
20
|
-
if (val === 'uint128') {
|
|
21
|
-
if (isArgument) return 'number | bigint';
|
|
22
|
-
return 'bigint';
|
|
23
|
-
} else if (val === 'int128') {
|
|
24
|
-
if (isArgument) return 'number | bigint';
|
|
25
|
-
return 'bigint';
|
|
26
|
-
} else if (val === 'bool') {
|
|
27
|
-
return 'boolean';
|
|
28
|
-
} else if (val === 'principal') {
|
|
29
|
-
return 'string';
|
|
30
|
-
} else if (val === 'none') {
|
|
31
|
-
return 'null';
|
|
32
|
-
} else if (val === 'trait_reference') {
|
|
33
|
-
return 'string';
|
|
34
|
-
} else {
|
|
35
|
-
throw new Error(
|
|
36
|
-
`Unexpected Clarity ABI type primitive: ${JSON.stringify(val)}`
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
} else if (isClarityAbiBuffer(val)) {
|
|
40
|
-
return 'Uint8Array';
|
|
41
|
-
} else if (isClarityAbiResponse(val)) {
|
|
42
|
-
const ok: any = jsTypeFromAbiType(val.response.ok);
|
|
43
|
-
const err: any = jsTypeFromAbiType(val.response.error);
|
|
44
|
-
return `ClarityTypes.Response<${ok}, ${err}>`;
|
|
45
|
-
} else if (isClarityAbiOptional(val)) {
|
|
46
|
-
const innerType = jsTypeFromAbiType(val.optional);
|
|
47
|
-
return `${innerType} | null`;
|
|
48
|
-
} else if (isClarityAbiTuple(val)) {
|
|
49
|
-
const tupleDefs: string[] = [];
|
|
50
|
-
val.tuple.forEach(({ name, type }) => {
|
|
51
|
-
const innerType = jsTypeFromAbiType(type);
|
|
52
|
-
tupleDefs.push(`"${name}": ${innerType}`);
|
|
53
|
-
});
|
|
54
|
-
return `{
|
|
55
|
-
${tupleDefs.join(';\n ')}
|
|
56
|
-
}`;
|
|
57
|
-
} else if (isClarityAbiList(val)) {
|
|
58
|
-
const innerType: any = jsTypeFromAbiType(val.list.type);
|
|
59
|
-
return `${innerType}[]`;
|
|
60
|
-
} else if (isClarityAbiStringAscii(val)) {
|
|
61
|
-
return 'string';
|
|
62
|
-
} else if (isClarityAbiStringUtf8(val)) {
|
|
63
|
-
return 'string';
|
|
64
|
-
} else if (val === 'trait_reference') {
|
|
65
|
-
return 'string';
|
|
66
|
-
} else {
|
|
67
|
-
throw new Error(`Unexpected Clarity ABI type: ${JSON.stringify(val)}`);
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
// Check if it's a reserved word, and then camelCase
|
|
72
|
-
function getArgName(name: string) {
|
|
73
|
-
const camel = toCamelCase(name);
|
|
74
|
-
const prefix = check(camel, 6) ? '_' : '';
|
|
75
|
-
return `${prefix}${camel}`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const accessToReturnType = {
|
|
79
|
-
public: 'Public',
|
|
80
|
-
read_only: 'ReadOnly',
|
|
81
|
-
private: 'Private',
|
|
82
|
-
} as const;
|
|
83
|
-
|
|
84
|
-
export function makePureTypes(abi: ClarityAbi) {
|
|
85
|
-
let typings = '';
|
|
86
|
-
abi.functions.forEach((func, index) => {
|
|
87
|
-
let functionLine = `${toCamelCase(func.name)}: `;
|
|
88
|
-
const args = func.args.map((arg) => {
|
|
89
|
-
return `${getArgName(arg.name)}: ${jsTypeFromAbiType(arg.type, true)}`;
|
|
90
|
-
});
|
|
91
|
-
functionLine += `(${args.join(', ')}) => `;
|
|
92
|
-
const funcType = accessToReturnType[func.access];
|
|
93
|
-
functionLine += `ContractCalls.${funcType}<`;
|
|
94
|
-
if (func.access === 'public') {
|
|
95
|
-
const { type } = func.outputs;
|
|
96
|
-
if (!isClarityAbiResponse(type))
|
|
97
|
-
throw new Error('Expected response type for public function');
|
|
98
|
-
const ok = jsTypeFromAbiType(type.response.ok);
|
|
99
|
-
const err = jsTypeFromAbiType(type.response.error);
|
|
100
|
-
functionLine += `${ok}, ${err}>;`;
|
|
101
|
-
} else {
|
|
102
|
-
const returnType = jsTypeFromAbiType(func.outputs.type);
|
|
103
|
-
functionLine += `${returnType}>;`;
|
|
104
|
-
}
|
|
105
|
-
typings += `${index === 0 ? '' : '\n'} ${functionLine}`;
|
|
106
|
-
});
|
|
107
|
-
abi.maps.forEach((map) => {
|
|
108
|
-
let functionLine = `${toCamelCase(map.name)}: `;
|
|
109
|
-
const keyType = jsTypeFromAbiType(map.key, true);
|
|
110
|
-
const arg = `key: ${keyType}`;
|
|
111
|
-
const valType = jsTypeFromAbiType(map.value);
|
|
112
|
-
functionLine += `(${arg}) => ContractCalls.Map<${keyType}, ${valType}>;`;
|
|
113
|
-
typings += `\n ${functionLine}`;
|
|
114
|
-
});
|
|
115
|
-
return typings;
|
|
116
|
-
}
|