@kasarlabs/scarb-mcp 0.1.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/LICENSE +21 -0
- package/README.md +34 -0
- package/bin/scarb-mcp.js +14 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +71 -0
- package/build/index.js.map +1 -0
- package/build/lib/types/index.d.ts +39 -0
- package/build/lib/types/index.js +2 -0
- package/build/lib/types/index.js.map +1 -0
- package/build/lib/utils/common.d.ts +3 -0
- package/build/lib/utils/common.js +33 -0
- package/build/lib/utils/common.js.map +1 -0
- package/build/lib/utils/index.d.ts +25 -0
- package/build/lib/utils/index.js +153 -0
- package/build/lib/utils/index.js.map +1 -0
- package/build/lib/utils/path.d.ts +2 -0
- package/build/lib/utils/path.js +44 -0
- package/build/lib/utils/path.js.map +1 -0
- package/build/lib/utils/preparation.d.ts +23 -0
- package/build/lib/utils/preparation.js +140 -0
- package/build/lib/utils/preparation.js.map +1 -0
- package/build/lib/utils/utils.d.ts +7 -0
- package/build/lib/utils/utils.js +55 -0
- package/build/lib/utils/utils.js.map +1 -0
- package/build/lib/utils/workspace.d.ts +48 -0
- package/build/lib/utils/workspace.js +121 -0
- package/build/lib/utils/workspace.js.map +1 -0
- package/build/schemas/index.d.ts +92 -0
- package/build/schemas/index.js +71 -0
- package/build/schemas/index.js.map +1 -0
- package/build/tools/build.d.ts +3 -0
- package/build/tools/build.js +22 -0
- package/build/tools/build.js.map +1 -0
- package/build/tools/execute.d.ts +23 -0
- package/build/tools/execute.js +34 -0
- package/build/tools/execute.js.map +1 -0
- package/build/tools/init.d.ts +15 -0
- package/build/tools/init.js +23 -0
- package/build/tools/init.js.map +1 -0
- package/build/tools/install.d.ts +19 -0
- package/build/tools/install.js +56 -0
- package/build/tools/install.js.map +1 -0
- package/build/tools/prove.d.ts +28 -0
- package/build/tools/prove.js +41 -0
- package/build/tools/prove.js.map +1 -0
- package/build/tools/verify.d.ts +20 -0
- package/build/tools/verify.js +25 -0
- package/build/tools/verify.js.map +1 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kasar Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Snak - Scarb Plugin
|
|
2
|
+
|
|
3
|
+
The Scarb Plugin provides comprehensive tools for managing Scarb projects, the build toolchain for Cairo and Starknet smart contracts.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
This plugin adds the following tools:
|
|
8
|
+
|
|
9
|
+
- **install_scarb**: Install Scarb Cairo toolchain with optional version specification.
|
|
10
|
+
- **init_project**: Initialize a new Scarb project with specified name and options.
|
|
11
|
+
- **build_project**: Build a Scarb project with specified build options.
|
|
12
|
+
- **execute_program**: Execute a Cairo program with optional function and arguments.
|
|
13
|
+
- **prove_program**: Generate a proof for a Cairo program execution using Stone prover.
|
|
14
|
+
- **verify_program**: Verify a proof generated for a Cairo program.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
The Scarb Plugin is used internally by the Starknet Agent and doesn't need to be called directly. When the agent is initialized, it automatically registers these tools, making them available for use.
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
|
|
22
|
+
When asking the agent to perform Scarb-related tasks, it will use the appropriate tool from this plugin:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
"Install Scarb version 2.5.0" // Uses install_scarb
|
|
26
|
+
"Initialize a new Cairo project called my_project" // Uses init_project
|
|
27
|
+
"Build my Scarb project" // Uses build_project
|
|
28
|
+
"Execute the main function in my Cairo program" // Uses execute_program
|
|
29
|
+
"Generate a proof for my Cairo program" // Uses prove_program
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Development
|
|
33
|
+
|
|
34
|
+
To extend this plugin, add new tools in the `src/tools` directory and register them in the `registerTools` function in `src/index.ts`.
|
package/bin/scarb-mcp.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { dirname, join } from 'path';
|
|
5
|
+
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
const buildPath = join(__dirname, '..', 'build', 'index.js');
|
|
8
|
+
|
|
9
|
+
if (!existsSync(buildPath)) {
|
|
10
|
+
console.error('Build not found. Run: npm run build');
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
await import(buildPath);
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import * as dotenv from 'dotenv';
|
|
5
|
+
import { registerToolsWithServer } from '@kasarlabs/ask-starknet-core';
|
|
6
|
+
import { initProject } from './tools/init.js';
|
|
7
|
+
import { buildProject } from './tools/build.js';
|
|
8
|
+
import { executeProgram } from './tools/execute.js';
|
|
9
|
+
import { installScarb } from './tools/install.js';
|
|
10
|
+
import { proveProgram } from './tools/prove.js';
|
|
11
|
+
import { verifyProgram } from './tools/verify.js';
|
|
12
|
+
import { installScarbSchema, initProjectSchema, buildProjectSchema, executeProgramSchema, proveProgramSchema, verifyProgramSchema, } from './schemas/index.js';
|
|
13
|
+
dotenv.config();
|
|
14
|
+
const server = new McpServer({
|
|
15
|
+
name: 'starknet-scarb-mcp',
|
|
16
|
+
version: '0.0.1',
|
|
17
|
+
});
|
|
18
|
+
const registerTools = (ScarbToolRegistry) => {
|
|
19
|
+
ScarbToolRegistry.push({
|
|
20
|
+
name: 'install_scarb',
|
|
21
|
+
description: 'Install Scarb Cairo toolchain with optional version specification',
|
|
22
|
+
schema: installScarbSchema,
|
|
23
|
+
execute: installScarb,
|
|
24
|
+
});
|
|
25
|
+
ScarbToolRegistry.push({
|
|
26
|
+
name: 'init_project',
|
|
27
|
+
description: 'Initialize a new Scarb project with specified name and options',
|
|
28
|
+
schema: initProjectSchema,
|
|
29
|
+
execute: initProject,
|
|
30
|
+
});
|
|
31
|
+
ScarbToolRegistry.push({
|
|
32
|
+
name: 'build_project',
|
|
33
|
+
description: 'Build a Scarb project with specified build options',
|
|
34
|
+
schema: buildProjectSchema,
|
|
35
|
+
execute: buildProject,
|
|
36
|
+
});
|
|
37
|
+
ScarbToolRegistry.push({
|
|
38
|
+
name: 'execute_program',
|
|
39
|
+
description: 'Execute a Cairo program with optional function and arguments',
|
|
40
|
+
schema: executeProgramSchema,
|
|
41
|
+
execute: executeProgram,
|
|
42
|
+
});
|
|
43
|
+
ScarbToolRegistry.push({
|
|
44
|
+
name: 'prove_program',
|
|
45
|
+
description: 'Generate a proof for a Cairo program execution using Stone prover',
|
|
46
|
+
schema: proveProgramSchema,
|
|
47
|
+
execute: proveProgram,
|
|
48
|
+
});
|
|
49
|
+
ScarbToolRegistry.push({
|
|
50
|
+
name: 'verify_program',
|
|
51
|
+
description: 'Verify a proof generated for a Cairo program',
|
|
52
|
+
schema: verifyProgramSchema,
|
|
53
|
+
execute: verifyProgram,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
export const RegisterToolInServer = async () => {
|
|
57
|
+
const tools = [];
|
|
58
|
+
registerTools(tools);
|
|
59
|
+
await registerToolsWithServer(server, tools);
|
|
60
|
+
};
|
|
61
|
+
async function main() {
|
|
62
|
+
const transport = new StdioServerTransport();
|
|
63
|
+
await RegisterToolInServer();
|
|
64
|
+
await server.connect(transport);
|
|
65
|
+
console.error('Starknet Scarb MCP Server running on stdio');
|
|
66
|
+
}
|
|
67
|
+
main().catch((error) => {
|
|
68
|
+
console.error('Fatal error in main():', error);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
});
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface ExecuteContractParams {
|
|
2
|
+
projectDir: string;
|
|
3
|
+
formattedExecutable: string;
|
|
4
|
+
arguments?: string;
|
|
5
|
+
target: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ProveProjectParams {
|
|
8
|
+
projectDir: string;
|
|
9
|
+
executionId: string;
|
|
10
|
+
}
|
|
11
|
+
export interface VerifyProjectParams {
|
|
12
|
+
projectDir: string;
|
|
13
|
+
proofPath: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ScarbBaseParams {
|
|
16
|
+
projectName: string;
|
|
17
|
+
filePaths?: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface TomlSection {
|
|
20
|
+
sectionTitle: string;
|
|
21
|
+
valuesObject: Record<string, any>;
|
|
22
|
+
}
|
|
23
|
+
export interface CairoProgram {
|
|
24
|
+
name: string;
|
|
25
|
+
source_code: string;
|
|
26
|
+
}
|
|
27
|
+
export interface Dependency {
|
|
28
|
+
name: string;
|
|
29
|
+
version: string;
|
|
30
|
+
}
|
|
31
|
+
export interface ProjectData {
|
|
32
|
+
id: number;
|
|
33
|
+
name: string;
|
|
34
|
+
type: 'contract' | 'cairo_program';
|
|
35
|
+
programs: CairoProgram[];
|
|
36
|
+
dependencies: Dependency[];
|
|
37
|
+
proof?: string;
|
|
38
|
+
verified?: boolean;
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { ScarbBaseParams, CairoProgram } from '../types/index.js';
|
|
2
|
+
export declare function setupScarbProject(params: ScarbBaseParams): Promise<string>;
|
|
3
|
+
export declare function setupSrc(projectDir: string, programs: CairoProgram[], formattedExecutable?: string): Promise<void>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { checkScarbInstalled } from './index.js';
|
|
2
|
+
import { initProject } from './workspace.js';
|
|
3
|
+
import { isProjectInitialized, getProjectDir, cleanLibCairo, processContractForExecution, importContract, } from './preparation.js';
|
|
4
|
+
export async function setupScarbProject(params) {
|
|
5
|
+
try {
|
|
6
|
+
await checkScarbInstalled();
|
|
7
|
+
const projectDir = await getProjectDir(params.projectName);
|
|
8
|
+
const isInitialized = await isProjectInitialized(projectDir);
|
|
9
|
+
if (!isInitialized) {
|
|
10
|
+
await initProject({ name: params.projectName, projectDir });
|
|
11
|
+
}
|
|
12
|
+
return projectDir;
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new Error(`Error setting up Scarb project: ${error.message}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function setupSrc(projectDir, programs, formattedExecutable) {
|
|
19
|
+
await cleanLibCairo(projectDir);
|
|
20
|
+
if (formattedExecutable) {
|
|
21
|
+
const parts = formattedExecutable.split('::');
|
|
22
|
+
const executableFunctionName = parts[2] || 'main';
|
|
23
|
+
for (const program of programs) {
|
|
24
|
+
await processContractForExecution(program.source_code, program.name, projectDir, executableFunctionName);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
for (const program of programs) {
|
|
29
|
+
await importContract(program.source_code, program.name, projectDir);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/lib/utils/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAEL,oBAAoB,EAEpB,aAAa,EACb,aAAa,EACb,2BAA2B,EAC3B,cAAc,GACf,MAAM,kBAAkB,CAAC;AAO1B,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,mBAAmB,EAAE,CAAC;QAE5B,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAE3D,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,UAAU,CAAC,CAAC;QAC7D,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;QAC9D,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,mCAAmC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAgCD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,UAAkB,EAClB,QAAwB,EACxB,mBAA4B;IAE5B,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC;IAEhC,IAAI,mBAAmB,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,sBAAsB,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;QAElD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,2BAA2B,CAC/B,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,IAAI,EACZ,UAAU,EACV,sBAAsB,CACvB,CAAC;QACJ,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,cAAc,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface TomlSection {
|
|
2
|
+
sectionTitle: string;
|
|
3
|
+
valuesObject: Record<string, any>;
|
|
4
|
+
}
|
|
5
|
+
export interface CairoProgram {
|
|
6
|
+
name: string;
|
|
7
|
+
source_code: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function checkScarbInstalled(): Promise<void>;
|
|
10
|
+
export declare function getScarbVersion(): Promise<string>;
|
|
11
|
+
export declare function createTempProjectDir(projectName: string): Promise<string>;
|
|
12
|
+
export declare function cleanProject(projectDir: string): Promise<void>;
|
|
13
|
+
export declare function writeSourceFiles(projectDir: string, sourceFiles: Record<string, string>): Promise<void>;
|
|
14
|
+
export declare function setupToml(projectDir: string, sections: TomlSection[], dependencies?: Record<string, string>): Promise<void>;
|
|
15
|
+
export declare function buildProject(projectDir: string): Promise<string>;
|
|
16
|
+
export declare function executeProgram(projectDir: string, executableName?: string, executableFunction?: string, args?: string, mode?: 'standalone' | 'bootloader'): Promise<string>;
|
|
17
|
+
export declare function getCompiledFiles(projectDir: string): Promise<{
|
|
18
|
+
sierraFiles: string[];
|
|
19
|
+
casmFiles: string[];
|
|
20
|
+
}>;
|
|
21
|
+
export declare function copyCompiledFiles(projectDir: string, outputDirectory: string): Promise<{
|
|
22
|
+
sierraFilePaths: string[];
|
|
23
|
+
casmFilePaths: string[];
|
|
24
|
+
}>;
|
|
25
|
+
export declare function formatCompilationError(error: any): string[];
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import * as fs from 'fs/promises';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
const execPromise = promisify(exec);
|
|
6
|
+
export async function checkScarbInstalled() {
|
|
7
|
+
try {
|
|
8
|
+
const env = {
|
|
9
|
+
...process.env,
|
|
10
|
+
PATH: `${process.env.HOME}/.local/bin:${process.env.PATH}`,
|
|
11
|
+
};
|
|
12
|
+
await execPromise('scarb --version', { env });
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new Error('Scarb is not installed or not available in PATH');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const execAsync = promisify(exec);
|
|
19
|
+
export async function getScarbVersion() {
|
|
20
|
+
try {
|
|
21
|
+
const env = {
|
|
22
|
+
...process.env,
|
|
23
|
+
PATH: `${process.env.HOME}/.local/bin:${process.env.PATH}`,
|
|
24
|
+
};
|
|
25
|
+
const { stdout } = await execAsync('scarb --version', { env });
|
|
26
|
+
return stdout.trim();
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return 'unknown';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function createTempProjectDir(projectName) {
|
|
33
|
+
const tempDir = await fs.mkdtemp(path.join('/tmp', `scarb-${projectName}-`));
|
|
34
|
+
return tempDir;
|
|
35
|
+
}
|
|
36
|
+
export async function cleanProject(projectDir) {
|
|
37
|
+
try {
|
|
38
|
+
await fs.rm(projectDir, { recursive: true, force: true });
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.warn(`Failed to clean project directory: ${error.message}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export async function writeSourceFiles(projectDir, sourceFiles) {
|
|
45
|
+
const srcDir = path.join(projectDir, 'src');
|
|
46
|
+
await fs.mkdir(srcDir, { recursive: true });
|
|
47
|
+
if (!sourceFiles['lib.cairo']) {
|
|
48
|
+
const libContent = Object.keys(sourceFiles)
|
|
49
|
+
.filter((f) => f.endsWith('.cairo') && f !== 'lib.cairo')
|
|
50
|
+
.map((f) => `mod ${path.basename(f, '.cairo')};`)
|
|
51
|
+
.join('\n');
|
|
52
|
+
await fs.writeFile(path.join(srcDir, 'lib.cairo'), libContent);
|
|
53
|
+
}
|
|
54
|
+
for (const [filename, content] of Object.entries(sourceFiles)) {
|
|
55
|
+
const filePath = path.join(srcDir, filename);
|
|
56
|
+
await fs.writeFile(filePath, content);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export async function setupToml(projectDir, sections, dependencies) {
|
|
60
|
+
const tomlPath = path.join(projectDir, 'Scarb.toml');
|
|
61
|
+
let tomlContent = await fs.readFile(tomlPath, 'utf-8');
|
|
62
|
+
if (dependencies) {
|
|
63
|
+
let dependenciesSection = '\n[dependencies]\n';
|
|
64
|
+
for (const [name, version] of Object.entries(dependencies)) {
|
|
65
|
+
dependenciesSection += `${name} = "${version}"\n`;
|
|
66
|
+
}
|
|
67
|
+
tomlContent += dependenciesSection;
|
|
68
|
+
}
|
|
69
|
+
for (const section of sections) {
|
|
70
|
+
let sectionContent = `\n[${section.sectionTitle}]\n`;
|
|
71
|
+
for (const [key, value] of Object.entries(section.valuesObject)) {
|
|
72
|
+
if (typeof value === 'boolean') {
|
|
73
|
+
sectionContent += `${key} = ${value}\n`;
|
|
74
|
+
}
|
|
75
|
+
else if (typeof value === 'string') {
|
|
76
|
+
sectionContent += `${key} = "${value}"\n`;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
sectionContent += `${key} = ${JSON.stringify(value)}\n`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
tomlContent += sectionContent;
|
|
83
|
+
}
|
|
84
|
+
await fs.writeFile(tomlPath, tomlContent);
|
|
85
|
+
}
|
|
86
|
+
export async function buildProject(projectDir) {
|
|
87
|
+
const { stdout, stderr } = await execPromise('scarb build', {
|
|
88
|
+
cwd: projectDir,
|
|
89
|
+
});
|
|
90
|
+
return JSON.stringify({ output: stdout, errors: stderr });
|
|
91
|
+
}
|
|
92
|
+
export async function executeProgram(projectDir, executableName, executableFunction, args, mode = 'bootloader') {
|
|
93
|
+
let command = 'scarb cairo-run';
|
|
94
|
+
if (executableName) {
|
|
95
|
+
command += ` --package ${executableName}`;
|
|
96
|
+
}
|
|
97
|
+
if (executableFunction) {
|
|
98
|
+
command += ` --function ${executableFunction}`;
|
|
99
|
+
}
|
|
100
|
+
if (args) {
|
|
101
|
+
command += ` -- ${args}`;
|
|
102
|
+
}
|
|
103
|
+
if (mode === 'standalone') {
|
|
104
|
+
command += ' --single-file';
|
|
105
|
+
}
|
|
106
|
+
const { stdout, stderr } = await execPromise(command, { cwd: projectDir });
|
|
107
|
+
return JSON.stringify({ output: stdout, errors: stderr });
|
|
108
|
+
}
|
|
109
|
+
export async function getCompiledFiles(projectDir) {
|
|
110
|
+
const targetDir = path.join(projectDir, 'target', 'dev');
|
|
111
|
+
try {
|
|
112
|
+
const files = await fs.readdir(targetDir);
|
|
113
|
+
const sierraFiles = files
|
|
114
|
+
.filter((f) => f.endsWith('.contract_class.json'))
|
|
115
|
+
.map((f) => path.join(targetDir, f));
|
|
116
|
+
const casmFiles = files
|
|
117
|
+
.filter((f) => f.endsWith('.compiled_contract_class.json'))
|
|
118
|
+
.map((f) => path.join(targetDir, f));
|
|
119
|
+
return { sierraFiles, casmFiles };
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
return { sierraFiles: [], casmFiles: [] };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export async function copyCompiledFiles(projectDir, outputDirectory) {
|
|
126
|
+
const { sierraFiles, casmFiles } = await getCompiledFiles(projectDir);
|
|
127
|
+
await fs.mkdir(outputDirectory, { recursive: true });
|
|
128
|
+
const sierraFilePaths = [];
|
|
129
|
+
const casmFilePaths = [];
|
|
130
|
+
for (const sierraFile of sierraFiles) {
|
|
131
|
+
const filename = path.basename(sierraFile);
|
|
132
|
+
const outputPath = path.join(outputDirectory, filename);
|
|
133
|
+
await fs.copyFile(sierraFile, outputPath);
|
|
134
|
+
sierraFilePaths.push(outputPath);
|
|
135
|
+
}
|
|
136
|
+
for (const casmFile of casmFiles) {
|
|
137
|
+
const filename = path.basename(casmFile);
|
|
138
|
+
const outputPath = path.join(outputDirectory, filename);
|
|
139
|
+
await fs.copyFile(casmFile, outputPath);
|
|
140
|
+
casmFilePaths.push(outputPath);
|
|
141
|
+
}
|
|
142
|
+
return { sierraFilePaths, casmFilePaths };
|
|
143
|
+
}
|
|
144
|
+
export function formatCompilationError(error) {
|
|
145
|
+
if (typeof error === 'string') {
|
|
146
|
+
return [error];
|
|
147
|
+
}
|
|
148
|
+
if (error.message) {
|
|
149
|
+
return [error.message];
|
|
150
|
+
}
|
|
151
|
+
return ['Unknown compilation error'];
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/utils/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
function findUp(filename, startDir = process.cwd()) {
|
|
4
|
+
let currentDir = path.resolve(startDir);
|
|
5
|
+
const { root } = path.parse(currentDir);
|
|
6
|
+
while (true) {
|
|
7
|
+
const filePath = path.join(currentDir, filename);
|
|
8
|
+
if (fs.existsSync(filePath)) {
|
|
9
|
+
return filePath;
|
|
10
|
+
}
|
|
11
|
+
if (currentDir === root) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
currentDir = path.dirname(currentDir);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function getRepoRoot() {
|
|
18
|
+
const rootPackageJsonPath = findUp('lerna.json');
|
|
19
|
+
if (!rootPackageJsonPath) {
|
|
20
|
+
throw new Error('File lerna.json not found');
|
|
21
|
+
}
|
|
22
|
+
return path.dirname(rootPackageJsonPath);
|
|
23
|
+
}
|
|
24
|
+
export function getPluginRoot() {
|
|
25
|
+
const repoRoot = getRepoRoot();
|
|
26
|
+
const pluginPath = path.join(repoRoot, 'plugins', 'scarb');
|
|
27
|
+
if (!fs.existsSync(pluginPath)) {
|
|
28
|
+
throw new Error(`Plugin Scarb not found: ${pluginPath}`);
|
|
29
|
+
}
|
|
30
|
+
return pluginPath;
|
|
31
|
+
}
|
|
32
|
+
export function getWorkspacePath() {
|
|
33
|
+
const workspacePath = path.join(getPluginRoot(), 'src', 'workspace');
|
|
34
|
+
if (!fs.existsSync(workspacePath)) {
|
|
35
|
+
try {
|
|
36
|
+
fs.mkdirSync(workspacePath, { recursive: true });
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new Error(`Failed to create workspace directory: ${workspacePath}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return workspacePath;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../../../src/lib/utils/path.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAQ7B,SAAS,MAAM,CACb,QAAgB,EAChB,WAAmB,OAAO,CAAC,GAAG,EAAE;IAEhC,IAAI,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAExC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QACjD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAMD,SAAS,WAAW;IAClB,MAAM,mBAAmB,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IACjD,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAC3C,CAAC;AAMD,MAAM,UAAU,aAAa;IAC3B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAE3D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,2BAA2B,UAAU,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAMD,MAAM,UAAU,gBAAgB;IAC9B,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,KAAK,EAAE,WAAW,CAAC,CAAC;IAErE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,yCAAyC,aAAa,EAAE,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare function importContract(contractContent: string, contractFileName: string, projectDir: string): Promise<{
|
|
2
|
+
success: boolean;
|
|
3
|
+
filePath: string;
|
|
4
|
+
}>;
|
|
5
|
+
export declare function addSeveralDependancies(projectDir: string): Promise<void>;
|
|
6
|
+
export declare function cleanLibCairo(projectDir: string): Promise<{
|
|
7
|
+
success: boolean;
|
|
8
|
+
message: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function getGeneratedContractFiles(projectDir: string): Promise<{
|
|
11
|
+
sierraFiles: string[];
|
|
12
|
+
casmFiles: string[];
|
|
13
|
+
artifactFile: string;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function addExecutableTag(filePath: string, targetFunction: string): Promise<boolean>;
|
|
16
|
+
export declare function processContractForExecution(contractContent: string, contractFileName: string, projectDir: string, targetFunction: string): Promise<void>;
|
|
17
|
+
export declare const addDependency: (params: {
|
|
18
|
+
package: string;
|
|
19
|
+
version?: string;
|
|
20
|
+
path?: string;
|
|
21
|
+
}) => Promise<string>;
|
|
22
|
+
export declare function isProjectInitialized(projectDir: string): Promise<boolean>;
|
|
23
|
+
export declare function getProjectDir(projectName: string): Promise<string>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import * as fs from 'fs-extra';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import { getWorkspacePath } from './path.js';
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
export async function importContract(contractContent, contractFileName, projectDir) {
|
|
8
|
+
const srcDir = path.join(projectDir, 'src');
|
|
9
|
+
const destContractPath = path.join(srcDir, contractFileName);
|
|
10
|
+
try {
|
|
11
|
+
await fs.writeFile(destContractPath, contractContent);
|
|
12
|
+
const libFilePath = path.join(srcDir, 'lib.cairo');
|
|
13
|
+
let libContent = await fs.readFile(libFilePath, 'utf-8');
|
|
14
|
+
const moduleName = path.basename(contractFileName, '.cairo');
|
|
15
|
+
if (!libContent.includes(`mod ${moduleName};`)) {
|
|
16
|
+
libContent += `\nmod ${moduleName};\n`;
|
|
17
|
+
}
|
|
18
|
+
await fs.writeFile(libFilePath, libContent);
|
|
19
|
+
return {
|
|
20
|
+
success: true,
|
|
21
|
+
filePath: destContractPath,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
throw new Error(`Failed to prepare contract: ${error.message}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function addSeveralDependancies(projectDir) {
|
|
29
|
+
try {
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
throw new Error(`Failed to add several dependencie: ${error.message}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function cleanLibCairo(projectDir) {
|
|
36
|
+
try {
|
|
37
|
+
const srcDir = path.join(projectDir, 'src');
|
|
38
|
+
const libFilePath = path.join(srcDir, 'lib.cairo');
|
|
39
|
+
const defaultLibContent = `// lib.cairo - Module exports for the project`;
|
|
40
|
+
await fs.writeFile(libFilePath, defaultLibContent, 'utf-8');
|
|
41
|
+
return {
|
|
42
|
+
success: true,
|
|
43
|
+
message: 'lib.cairo file cleaned successfully',
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
throw new Error(`Failed to clean lib.cairo: ${error.message}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export async function getGeneratedContractFiles(projectDir) {
|
|
51
|
+
const result = {
|
|
52
|
+
sierraFiles: [],
|
|
53
|
+
casmFiles: [],
|
|
54
|
+
artifactFile: path.join(projectDir, 'target/dev', path.basename(projectDir) + '.starknet_artifacts.json'),
|
|
55
|
+
};
|
|
56
|
+
try {
|
|
57
|
+
const targetDir = path.join(projectDir, 'target/dev');
|
|
58
|
+
const files = (await fs.readdir(targetDir, {
|
|
59
|
+
recursive: true,
|
|
60
|
+
}));
|
|
61
|
+
result.sierraFiles = files
|
|
62
|
+
.filter((file) => typeof file === 'string' && file.endsWith('.contract_class.json'))
|
|
63
|
+
.map((file) => path.join(targetDir, file));
|
|
64
|
+
result.casmFiles = files
|
|
65
|
+
.filter((file) => typeof file === 'string' &&
|
|
66
|
+
file.endsWith('.compiled_contract_class.json'))
|
|
67
|
+
.map((file) => path.join(targetDir, file));
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
throw new Error(`Failed to get generated contract files: ${error.message}`);
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
export async function addExecutableTag(filePath, targetFunction) {
|
|
75
|
+
try {
|
|
76
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
77
|
+
const functionRegex = new RegExp(`(^|\\n)fn\\s+${targetFunction}\\s*\\(`, 'm');
|
|
78
|
+
if (!functionRegex.test(content)) {
|
|
79
|
+
throw new Error(`Target function '${targetFunction}' not found in ${filePath}`);
|
|
80
|
+
}
|
|
81
|
+
const executableRegex = new RegExp(`(^|\\n)#\\[executable\\]\\s*\\n\\s*fn\\s+${targetFunction}\\s*\\(`, 'm');
|
|
82
|
+
if (executableRegex.test(content)) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
const modifiedContent = content.replace(functionRegex, `\n#[executable]\nfn ${targetFunction}(`);
|
|
86
|
+
await fs.writeFile(filePath, modifiedContent);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
throw new Error(`Failed to add executable tag: ${error.message}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
export async function processContractForExecution(contractContent, contractFileName, projectDir, targetFunction) {
|
|
94
|
+
try {
|
|
95
|
+
const result = await importContract(contractContent, contractFileName, projectDir);
|
|
96
|
+
const destContractPath = result.filePath;
|
|
97
|
+
await addExecutableTag(destContractPath, targetFunction);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
throw new Error(`Failed to process contract: ${error.message}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
export const addDependency = async (params) => {
|
|
104
|
+
try {
|
|
105
|
+
const workingDir = params.path || process.cwd();
|
|
106
|
+
let command = `scarb add ${params.package}`;
|
|
107
|
+
if (params.version) {
|
|
108
|
+
command += `@${params.version}`;
|
|
109
|
+
}
|
|
110
|
+
const { stdout, stderr } = await execAsync(command, { cwd: workingDir });
|
|
111
|
+
return JSON.stringify({
|
|
112
|
+
status: 'success',
|
|
113
|
+
message: `Dependency ${params.package} added successfully`,
|
|
114
|
+
output: stdout,
|
|
115
|
+
errors: stderr || undefined,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
throw new Error(`Failed to add dependancie to scarb project: ${error.message}`);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
export async function isProjectInitialized(projectDir) {
|
|
123
|
+
try {
|
|
124
|
+
const scarbTomlPath = path.join(projectDir, 'Scarb.toml');
|
|
125
|
+
await fs.access(scarbTomlPath);
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export async function getProjectDir(projectName) {
|
|
133
|
+
const workspaceDir = getWorkspacePath();
|
|
134
|
+
try {
|
|
135
|
+
await fs.mkdir(workspaceDir, { recursive: true });
|
|
136
|
+
}
|
|
137
|
+
catch (error) { }
|
|
138
|
+
return path.join(workspaceDir, projectName);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=preparation.js.map
|