mobilestacks 0.1.7 → 0.1.8

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.
Files changed (69) hide show
  1. package/dist/cli/index.d.ts +3 -0
  2. package/dist/cli/index.d.ts.map +1 -0
  3. package/dist/cli/index.js +107 -0
  4. package/dist/cli/init.d.ts +2 -0
  5. package/dist/cli/init.d.ts.map +1 -0
  6. package/dist/cli/init.js +83 -0
  7. package/dist/config/config-loading.d.ts +3 -0
  8. package/dist/config/config-loading.d.ts.map +1 -0
  9. package/dist/config/config-loading.js +35 -0
  10. package/dist/core/dsl.d.ts +30 -0
  11. package/dist/core/dsl.d.ts.map +1 -0
  12. package/dist/core/dsl.js +68 -0
  13. package/dist/core/dsl.test.d.ts +2 -0
  14. package/dist/core/dsl.test.d.ts.map +1 -0
  15. package/dist/core/dsl.test.js +50 -0
  16. package/dist/core/env.d.ts +6 -0
  17. package/dist/core/env.d.ts.map +1 -0
  18. package/dist/core/env.js +13 -0
  19. package/dist/core/extender.d.ts +12 -0
  20. package/dist/core/extender.d.ts.map +1 -0
  21. package/dist/core/extender.js +25 -0
  22. package/dist/core/runtime-environment.d.ts +16 -0
  23. package/dist/core/runtime-environment.d.ts.map +1 -0
  24. package/dist/core/runtime-environment.js +72 -0
  25. package/dist/core/simnet.d.ts +17 -0
  26. package/dist/core/simnet.d.ts.map +1 -0
  27. package/dist/core/simnet.js +46 -0
  28. package/dist/core/tasks-definitions.d.ts +28 -0
  29. package/dist/core/tasks-definitions.d.ts.map +1 -0
  30. package/dist/core/tasks-definitions.js +24 -0
  31. package/dist/index.d.ts +5 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +26 -0
  34. package/dist/src/cli/init.js +3 -3
  35. package/dist/src/tasks/deploy-contract.js +3 -1
  36. package/dist/tasks/call-contract-function.d.ts +2 -0
  37. package/dist/tasks/call-contract-function.d.ts.map +1 -0
  38. package/dist/tasks/call-contract-function.js +36 -0
  39. package/dist/tasks/deploy-contract.d.ts +2 -0
  40. package/dist/tasks/deploy-contract.d.ts.map +1 -0
  41. package/dist/tasks/deploy-contract.js +51 -0
  42. package/dist/tasks/example-task.d.ts +2 -0
  43. package/dist/tasks/example-task.d.ts.map +1 -0
  44. package/dist/tasks/example-task.js +8 -0
  45. package/dist/tasks/faucet-request.d.ts +2 -0
  46. package/dist/tasks/faucet-request.d.ts.map +1 -0
  47. package/dist/tasks/faucet-request.js +26 -0
  48. package/dist/tasks/get-balance.d.ts +2 -0
  49. package/dist/tasks/get-balance.d.ts.map +1 -0
  50. package/dist/tasks/get-balance.js +38 -0
  51. package/dist/tasks/get-contract-info.d.ts +2 -0
  52. package/dist/tasks/get-contract-info.d.ts.map +1 -0
  53. package/dist/tasks/get-contract-info.js +23 -0
  54. package/dist/tasks/get-tx-history.d.ts +2 -0
  55. package/dist/tasks/get-tx-history.d.ts.map +1 -0
  56. package/dist/tasks/get-tx-history.js +43 -0
  57. package/dist/tasks/list-accounts.d.ts +2 -0
  58. package/dist/tasks/list-accounts.d.ts.map +1 -0
  59. package/dist/tasks/list-accounts.js +26 -0
  60. package/dist/tasks/send-stx.d.ts +2 -0
  61. package/dist/tasks/send-stx.d.ts.map +1 -0
  62. package/dist/tasks/send-stx.js +38 -0
  63. package/dist/tasks/verify-contract.d.ts +2 -0
  64. package/dist/tasks/verify-contract.d.ts.map +1 -0
  65. package/dist/tasks/verify-contract.js +38 -0
  66. package/dist/types/config.d.ts +100 -0
  67. package/dist/types/config.d.ts.map +1 -0
  68. package/dist/types/config.js +23 -0
  69. package/package.json +2 -2
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const commander_1 = require("commander");
9
+ const config_loading_1 = require("../config/config-loading");
10
+ const runtime_environment_1 = require("../core/runtime-environment");
11
+ const tasks_definitions_1 = require("../core/tasks-definitions");
12
+ const init_1 = require("./init");
13
+ const inquirer_1 = __importDefault(require("inquirer"));
14
+ // Import all user tasks
15
+ const fs_1 = __importDefault(require("fs"));
16
+ const path_1 = __importDefault(require("path"));
17
+ // Auto-load all tasks in src/tasks
18
+ const tasksDir = path_1.default.join(__dirname, '../tasks');
19
+ fs_1.default.readdirSync(tasksDir)
20
+ .filter(f => (f.endsWith('.ts') || f.endsWith('.js')) && !f.endsWith('.d.ts') && !f.includes('.test.'))
21
+ .forEach(f => {
22
+ require(path_1.default.join(tasksDir, f));
23
+ });
24
+ const program = new commander_1.Command();
25
+ program
26
+ .name('mobilestacks')
27
+ .description('Professional Task Runner for Stacks')
28
+ .version('0.1.0');
29
+ // Init command for project scaffolding
30
+ program
31
+ .command('init')
32
+ .description('Scaffold a new mobilestacks project and config')
33
+ .action(async () => {
34
+ await (0, init_1.runInit)();
35
+ process.exit(0);
36
+ });
37
+ // List all tasks if no command is given
38
+ program.action(() => {
39
+ console.log(chalk_1.default.bold.blue('\nMobilestacks - Professional Task Runner for Stacks\n'));
40
+ console.log(chalk_1.default.white('USAGE: ') + chalk_1.default.green('mobilestacks <task> [options]\n'));
41
+ console.log(chalk_1.default.bold('Available tasks:'));
42
+ tasks_definitions_1.TaskDefinitions.getInstance().getAllTasks().forEach(task => {
43
+ const params = task.params.map(p => chalk_1.default.yellow(`--${p.name}`)).join(' ');
44
+ console.log(' ' + chalk_1.default.cyan(task.name) + ' ' + params);
45
+ console.log(' ' + chalk_1.default.gray(task.description));
46
+ });
47
+ console.log('\n' + chalk_1.default.white('Use ') + chalk_1.default.green('mobilestacks <task> --help') + chalk_1.default.white(' for more info on a task.'));
48
+ console.log(chalk_1.default.white('\nExample:'));
49
+ console.log(' ' + chalk_1.default.green('mobilestacks deploy-contract --contractName my-contract --file ./contracts/my-contract.clar --network testnet'));
50
+ console.log(chalk_1.default.white('\nDocs: ') + chalk_1.default.underline('https://github.com/your-org/mobilestacks#readme'));
51
+ program.help({ error: false });
52
+ });
53
+ // Dynamically add all registered tasks
54
+ tasks_definitions_1.TaskDefinitions.getInstance().getAllTasks().forEach(task => {
55
+ const cmd = program.command(task.name)
56
+ .description(task.description);
57
+ task.params.forEach(param => {
58
+ const optStr = `--${param.name} <value>`;
59
+ if (param.required !== false) {
60
+ cmd.option(optStr, param.description);
61
+ }
62
+ else {
63
+ cmd.option(optStr, param.description, param.defaultValue);
64
+ }
65
+ });
66
+ cmd.action(async (opts) => {
67
+ try {
68
+ // Prompt for missing required params
69
+ const missing = task.params.filter(p => p.required !== false && !opts[p.name]);
70
+ if (missing.length > 0) {
71
+ const answers = await inquirer_1.default.prompt(missing.map(p => ({
72
+ type: p.type === 'boolean' ? 'confirm' : 'input',
73
+ name: p.name,
74
+ message: p.description,
75
+ default: p.defaultValue
76
+ })));
77
+ Object.assign(opts, answers);
78
+ }
79
+ // Type conversion
80
+ task.params.forEach(p => {
81
+ if (opts[p.name] && p.type === 'number')
82
+ opts[p.name] = Number(opts[p.name]);
83
+ if (opts[p.name] && p.type === 'boolean')
84
+ opts[p.name] = Boolean(opts[p.name]);
85
+ });
86
+ const config = (0, config_loading_1.loadConfig)();
87
+ const env = new runtime_environment_1.RuntimeEnvironment(config);
88
+ const result = await task.action(opts, env);
89
+ if (typeof result === 'object') {
90
+ console.log(chalk_1.default.greenBright('Success!'));
91
+ console.dir(result, { depth: null, colors: true });
92
+ }
93
+ else {
94
+ console.log(chalk_1.default.greenBright(result));
95
+ }
96
+ }
97
+ catch (err) {
98
+ const error = err;
99
+ console.error(chalk_1.default.redBright('Task failed:'), error.message || error);
100
+ if (error && typeof error === 'object' && 'stack' in error && error.stack) {
101
+ console.error(chalk_1.default.gray(error.stack));
102
+ }
103
+ process.exit(1);
104
+ }
105
+ });
106
+ });
107
+ program.parse(process.argv);
@@ -0,0 +1,2 @@
1
+ export declare function runInit(): Promise<void>;
2
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAIA,wBAAsB,OAAO,kBAoF5B"}
@@ -0,0 +1,83 @@
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
+ exports.runInit = runInit;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const inquirer_1 = __importDefault(require("inquirer"));
10
+ async function runInit() {
11
+ console.log('Welcome to mobilestacks project initialization!');
12
+ const answers = await inquirer_1.default.prompt([
13
+ {
14
+ type: 'input',
15
+ name: 'projectName',
16
+ message: 'Project name:',
17
+ default: path_1.default.basename(process.cwd()),
18
+ },
19
+ {
20
+ type: 'input',
21
+ name: 'mainnetUrl',
22
+ message: 'Stacks mainnet node URL:',
23
+ default: 'https://api.mainnet.hiro.so',
24
+ },
25
+ {
26
+ type: 'input',
27
+ name: 'testnetUrl',
28
+ message: 'Stacks testnet node URL:',
29
+ default: 'https://api.testnet.hiro.so',
30
+ },
31
+ {
32
+ type: 'input',
33
+ name: 'derivationPath',
34
+ message: "Derivation path (default: m/44'/5757'/0'/0/0):",
35
+ default: "m/44'/5757'/0'/0/0",
36
+ },
37
+ ]);
38
+ // ── Config file: references env vars, never embeds secrets ──
39
+ const config = `import 'dotenv/config';
40
+
41
+ export default {
42
+ networks: {
43
+ mainnet: { url: process.env.STACKS_MAINNET_URL || ${JSON.stringify(answers.mainnetUrl)}, name: 'mainnet' },
44
+ testnet: { url: process.env.STACKS_TESTNET_URL || ${JSON.stringify(answers.testnetUrl)}, name: 'testnet' },
45
+ },
46
+ defaultNetwork: 'testnet',
47
+ wallet: {
48
+ // Secrets are read from environment variables — never hard-code them here.
49
+ privateKey: process.env.MOBILESTACKS_PRIVATE_KEY || '',
50
+ seedPhrase: process.env.MOBILESTACKS_SEED_PHRASE || '',
51
+ derivationPath: ${JSON.stringify(answers.derivationPath)},
52
+ },
53
+ };
54
+ `;
55
+ fs_1.default.writeFileSync(path_1.default.join(process.cwd(), 'mobilestacks.config.ts'), config);
56
+ // ── .env file (if it doesn't exist yet) ──
57
+ const envPath = path_1.default.join(process.cwd(), '.env');
58
+ if (!fs_1.default.existsSync(envPath)) {
59
+ const envContent = `# Mobilestacks secrets — NEVER commit this file!\nMOBILESTACKS_PRIVATE_KEY=\nMOBILESTACKS_SEED_PHRASE=\nSTACKS_MAINNET_URL=${answers.mainnetUrl}\nSTACKS_TESTNET_URL=${answers.testnetUrl}\n`;
60
+ fs_1.default.writeFileSync(envPath, envContent, { mode: 0o600 }); // owner-only permissions
61
+ }
62
+ // ── Scaffold example contract ──
63
+ const contractsDir = path_1.default.join(process.cwd(), 'contracts');
64
+ if (!fs_1.default.existsSync(contractsDir))
65
+ fs_1.default.mkdirSync(contractsDir);
66
+ fs_1.default.writeFileSync(path_1.default.join(contractsDir, 'sample-contract.clar'), '(define-public (hello-world)\n (ok "Hello, Stacks!"))\n');
67
+ // ── Scaffold example user task ──
68
+ const tasksDir = path_1.default.join(process.cwd(), 'src', 'tasks');
69
+ if (!fs_1.default.existsSync(tasksDir))
70
+ fs_1.default.mkdirSync(tasksDir, { recursive: true });
71
+ fs_1.default.writeFileSync(path_1.default.join(tasksDir, 'example-task.ts'), "import { task } from 'mobilestacks';\n\ntask('example', 'An example user task for onboarding')\n .addParam('name', 'Your name', { type: 'string', required: false, defaultValue: 'World' })\n .setAction(async (args: Record<string, string>) => {\n return `Hello, ${args.name}! Welcome to mobilestacks.`;\n });\n");
72
+ // ── Security notice ──
73
+ console.log('\n✅ Created:');
74
+ console.log(' • mobilestacks.config.ts (reads secrets from env vars)');
75
+ console.log(' • .env (store your secrets here)');
76
+ console.log(' • contracts/sample-contract.clar');
77
+ console.log(' • src/tasks/example-task.ts');
78
+ console.log('\n⚠️ SECURITY WARNING:');
79
+ console.log(' Your wallet secrets belong in the .env file, NOT in source code.');
80
+ console.log(' • .env is already listed in .gitignore — never remove that entry.');
81
+ console.log(' • Set MOBILESTACKS_PRIVATE_KEY or MOBILESTACKS_SEED_PHRASE in .env');
82
+ console.log(' • See .env.example for the full list of supported variables.\n');
83
+ }
@@ -0,0 +1,3 @@
1
+ import { MobilestacksConfig } from '../types/config';
2
+ export declare function loadConfig(configPath?: string, cliOverrides?: Record<string, unknown>): MobilestacksConfig;
3
+ //# sourceMappingURL=config-loading.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-loading.d.ts","sourceRoot":"","sources":["../../src/config/config-loading.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAK/E,wBAAgB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,kBAAkB,CAyB9G"}
@@ -0,0 +1,35 @@
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
+ exports.loadConfig = loadConfig;
7
+ const config_1 = require("../types/config");
8
+ const path_1 = __importDefault(require("path"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const env_1 = require("../core/env");
11
+ function loadConfig(configPath, cliOverrides = {}) {
12
+ const configFile = configPath || path_1.default.resolve(process.cwd(), 'mobilestacks.config.ts');
13
+ if (!fs_1.default.existsSync(configFile)) {
14
+ throw new Error(`Config file not found: ${configFile}`);
15
+ }
16
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
17
+ require('ts-node').register();
18
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
19
+ const userConfig = require(configFile);
20
+ let config = userConfig.default || userConfig;
21
+ // .env override
22
+ if (env_1.env.privateKey)
23
+ config.wallet.privateKey = env_1.env.privateKey;
24
+ if (env_1.env.mainnetUrl)
25
+ config.networks.mainnet.url = env_1.env.mainnetUrl;
26
+ if (env_1.env.testnetUrl)
27
+ config.networks.testnet.url = env_1.env.testnetUrl;
28
+ // CLI overrides
29
+ config = { ...config, ...cliOverrides };
30
+ const parsed = config_1.MobilestacksConfigSchema.safeParse(config);
31
+ if (!parsed.success) {
32
+ throw new Error('Invalid mobilestacks.config.ts: ' + JSON.stringify(parsed.error.format(), null, 2));
33
+ }
34
+ return parsed.data;
35
+ }
@@ -0,0 +1,30 @@
1
+ import { TaskDefinition, TaskParamType } from './tasks-definitions';
2
+ import { ZodSchema } from 'zod';
3
+ import { RuntimeEnvironment } from './runtime-environment';
4
+ import { extendEnvironment } from './extender';
5
+ declare function task(name: string, description: string): {
6
+ addParam(paramName: string, paramDesc: string, options?: {
7
+ type?: TaskParamType;
8
+ required?: boolean;
9
+ defaultValue?: unknown;
10
+ schema?: ZodSchema;
11
+ }): /*elided*/ any;
12
+ setAction(action: (args: Record<string, unknown>, env: RuntimeEnvironment) => Promise<unknown>): TaskDefinition;
13
+ };
14
+ declare function subtask(name: string, description: string, parentTaskName?: string): {
15
+ addParam(paramName: string, paramDesc: string, options?: {
16
+ type?: TaskParamType;
17
+ required?: boolean;
18
+ defaultValue?: unknown;
19
+ schema?: ZodSchema;
20
+ }): /*elided*/ any;
21
+ setAction(action: (args: Record<string, unknown>, env: RuntimeEnvironment) => Promise<unknown>): TaskDefinition;
22
+ };
23
+ export type WorkflowStep = {
24
+ taskName: string;
25
+ args?: Record<string, unknown>;
26
+ };
27
+ export type Workflow = WorkflowStep[];
28
+ export declare function runWorkflow(workflow: Workflow, env: RuntimeEnvironment): Promise<void>;
29
+ export { task, subtask, extendEnvironment };
30
+ //# sourceMappingURL=dsl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsl.d.ts","sourceRoot":"","sources":["../../src/core/dsl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,cAAc,EAAa,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAChG,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,iBAAS,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;wBAI9B,MAAM,aACN,MAAM,YACP;QAAE,IAAI,CAAC,EAAE,aAAa,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAA;KAAE;sBAYlF,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,kBAAkB,KAAK,OAAO,CAAC,OAAO,CAAC;EAuBjG;AAED,iBAAS,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM;wBAvC1D,MAAM,aACN,MAAM,YACP;QAAE,IAAI,CAAC,EAAE,aAAa,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,SAAS,CAAA;KAAE;sBAYlF,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,kBAAkB,KAAK,OAAO,CAAC,OAAO,CAAC;EAkCjG;AAGD,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC;AAChF,MAAM,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;AAEtC,wBAAsB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,kBAAkB,iBAO5E;AAED,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extendEnvironment = void 0;
4
+ exports.runWorkflow = runWorkflow;
5
+ exports.task = task;
6
+ exports.subtask = subtask;
7
+ const tasks_definitions_1 = require("./tasks-definitions");
8
+ const extender_1 = require("./extender");
9
+ Object.defineProperty(exports, "extendEnvironment", { enumerable: true, get: function () { return extender_1.extendEnvironment; } });
10
+ function task(name, description) {
11
+ const params = [];
12
+ return {
13
+ addParam(paramName, paramDesc, options) {
14
+ params.push({
15
+ name: paramName,
16
+ description: paramDesc,
17
+ type: options?.type || 'string',
18
+ required: options?.required !== false, // default true
19
+ defaultValue: options?.defaultValue,
20
+ schema: options?.schema,
21
+ });
22
+ return this;
23
+ },
24
+ setAction(action) {
25
+ const def = {
26
+ name,
27
+ description,
28
+ params,
29
+ action: async (args, env) => {
30
+ // Validate args against schemas if present
31
+ for (const param of params) {
32
+ if (param.schema && args[param.name] !== undefined) {
33
+ try {
34
+ param.schema.parse(args[param.name]);
35
+ }
36
+ catch (error) {
37
+ throw new Error(`Invalid value for parameter '${param.name}': ${error}`);
38
+ }
39
+ }
40
+ }
41
+ return action(args, env);
42
+ },
43
+ };
44
+ tasks_definitions_1.TaskDefinitions.getInstance().addTask(def);
45
+ return def;
46
+ },
47
+ };
48
+ }
49
+ function subtask(name, description, parentTaskName) {
50
+ // Register as a subtask with a parent if provided
51
+ const sub = task(name, description);
52
+ if (parentTaskName) {
53
+ // Attach parent info for future use (e.g., dependency graph, CLI grouping)
54
+ const def = tasks_definitions_1.TaskDefinitions.getInstance().getTask(name);
55
+ if (def)
56
+ def.parent = parentTaskName;
57
+ }
58
+ return sub;
59
+ }
60
+ async function runWorkflow(workflow, env) {
61
+ for (const step of workflow) {
62
+ const def = tasks_definitions_1.TaskDefinitions.getInstance().getTask(step.taskName);
63
+ if (!def)
64
+ throw new Error(`Task not found: ${step.taskName}`);
65
+ // eslint-disable-next-line no-await-in-loop
66
+ await def.action(step.args || {}, env);
67
+ }
68
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dsl.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsl.test.d.ts","sourceRoot":"","sources":["../../src/core/dsl.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const dsl_1 = require("./dsl");
5
+ const tasks_definitions_1 = require("./tasks-definitions");
6
+ const zod_1 = require("zod");
7
+ const extender_1 = require("./extender");
8
+ (0, vitest_1.describe)('DSL', () => {
9
+ (0, vitest_1.beforeEach)(() => {
10
+ // Clear tasks before each test
11
+ tasks_definitions_1.TaskDefinitions.getInstance()._tasks = [];
12
+ });
13
+ (0, vitest_1.it)('should register a task with generic parameters', () => {
14
+ (0, dsl_1.task)('test-task', 'A test task')
15
+ .addParam('p1', 'param 1')
16
+ .setAction(async () => { return 'done'; });
17
+ const def = tasks_definitions_1.TaskDefinitions.getInstance().getTask('test-task');
18
+ (0, vitest_1.expect)(def).toBeDefined();
19
+ (0, vitest_1.expect)(def?.name).toBe('test-task');
20
+ (0, vitest_1.expect)(def?.params.length).toBe(1);
21
+ });
22
+ (0, vitest_1.it)('should validate Zod schema', async () => {
23
+ (0, dsl_1.task)('zod-task', 'Task with validation')
24
+ .addParam('age', 'Age param', { schema: zod_1.z.number().min(18) })
25
+ .setAction(async (args) => {
26
+ return args.age;
27
+ });
28
+ const def = tasks_definitions_1.TaskDefinitions.getInstance().getTask('zod-task');
29
+ (0, vitest_1.expect)(def).toBeDefined();
30
+ // Mock environment
31
+ const env = {};
32
+ // Valid call
33
+ const result = await def?.action({ age: 20 }, env);
34
+ (0, vitest_1.expect)(result).toBe(20);
35
+ // Invalid call
36
+ await (0, vitest_1.expect)(def?.action({ age: 10 }, env)).rejects.toThrow('Invalid value for parameter \'age\'');
37
+ });
38
+ (0, vitest_1.it)('should support environment extensions', () => {
39
+ // Clear extensions
40
+ extender_1.Extender.getInstance()._extensions = [];
41
+ (0, extender_1.extendEnvironment)((env) => {
42
+ env['foo'] = 'bar';
43
+ });
44
+ const extensions = extender_1.Extender.getInstance().getExtensions();
45
+ (0, vitest_1.expect)(extensions.length).toBe(1);
46
+ const mockEnv = {};
47
+ extensions[0](mockEnv);
48
+ (0, vitest_1.expect)(mockEnv['foo']).toBe('bar');
49
+ });
50
+ });
@@ -0,0 +1,6 @@
1
+ export declare const env: {
2
+ privateKey: string | undefined;
3
+ mainnetUrl: string | undefined;
4
+ testnetUrl: string | undefined;
5
+ };
6
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/core/env.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,GAAG;;;;CAIf,CAAC"}
@@ -0,0 +1,13 @@
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
+ exports.env = void 0;
7
+ const dotenv_1 = __importDefault(require("dotenv"));
8
+ dotenv_1.default.config();
9
+ exports.env = {
10
+ privateKey: process.env.STACKS_PRIVATE_KEY,
11
+ mainnetUrl: process.env.STACKS_MAINNET_URL,
12
+ testnetUrl: process.env.STACKS_TESTNET_URL,
13
+ };
@@ -0,0 +1,12 @@
1
+ import { RuntimeEnvironment } from './runtime-environment';
2
+ export type ExtensionFunc = (env: RuntimeEnvironment) => void;
3
+ export declare class Extender {
4
+ private static _instance;
5
+ private _extensions;
6
+ private constructor();
7
+ static getInstance(): Extender;
8
+ addExtension(func: ExtensionFunc): void;
9
+ getExtensions(): ExtensionFunc[];
10
+ }
11
+ export declare function extendEnvironment(func: ExtensionFunc): void;
12
+ //# sourceMappingURL=extender.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extender.d.ts","sourceRoot":"","sources":["../../src/core/extender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAE9D,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAW;IACnC,OAAO,CAAC,WAAW,CAAuB;IAE1C,OAAO;WAEO,WAAW,IAAI,QAAQ;IAO9B,YAAY,CAAC,IAAI,EAAE,aAAa;IAIhC,aAAa,IAAI,aAAa,EAAE;CAGxC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,QAEpD"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Extender = void 0;
4
+ exports.extendEnvironment = extendEnvironment;
5
+ class Extender {
6
+ constructor() {
7
+ this._extensions = [];
8
+ }
9
+ static getInstance() {
10
+ if (!Extender._instance) {
11
+ Extender._instance = new Extender();
12
+ }
13
+ return Extender._instance;
14
+ }
15
+ addExtension(func) {
16
+ this._extensions.push(func);
17
+ }
18
+ getExtensions() {
19
+ return this._extensions;
20
+ }
21
+ }
22
+ exports.Extender = Extender;
23
+ function extendEnvironment(func) {
24
+ Extender.getInstance().addExtension(func);
25
+ }
@@ -0,0 +1,16 @@
1
+ import 'dotenv/config';
2
+ import { MobilestacksConfig } from '../types/config';
3
+ import { StacksNetwork } from '@stacks/network';
4
+ export declare class RuntimeEnvironment {
5
+ config: MobilestacksConfig;
6
+ network: StacksNetwork;
7
+ wallet: {
8
+ privateKey: string;
9
+ address: string;
10
+ accountIndex?: number;
11
+ };
12
+ stacks: Record<string, unknown>;
13
+ [key: string]: unknown;
14
+ constructor(config: MobilestacksConfig);
15
+ }
16
+ //# sourceMappingURL=runtime-environment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-environment.d.ts","sourceRoot":"","sources":["../../src/core/runtime-environment.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAiB,MAAM,iBAAiB,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAiB,MAAM,iBAAiB,CAAC;AAG/D,qBAAa,kBAAkB;IACtB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAG;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;gBAEX,MAAM,EAAE,kBAAkB;CAkEvC"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RuntimeEnvironment = void 0;
4
+ require("dotenv/config");
5
+ const transactions_1 = require("@stacks/transactions");
6
+ const wallet_sdk_1 = require("@stacks/wallet-sdk");
7
+ const network_1 = require("@stacks/network");
8
+ const extender_1 = require("./extender");
9
+ class RuntimeEnvironment {
10
+ constructor(config) {
11
+ this.config = config;
12
+ const networkName = config.defaultNetwork;
13
+ const networkConfig = config.networks[networkName];
14
+ if (!networkConfig) {
15
+ throw new Error(`Network config not found for: ${networkName}`);
16
+ }
17
+ // Instantiate proper StacksNetwork
18
+ if (networkName === 'mainnet' || networkName === 'testnet') {
19
+ this.network = (0, network_1.createNetwork)({
20
+ network: networkName,
21
+ client: { baseUrl: networkConfig.url }
22
+ });
23
+ }
24
+ else {
25
+ // Default to testnet structure for custom networks
26
+ this.network = (0, network_1.createNetwork)({
27
+ network: 'testnet',
28
+ client: { baseUrl: networkConfig.url }
29
+ });
30
+ }
31
+ // ── Resolve wallet secrets (env vars take priority over config) ──
32
+ const privateKey = process.env.MOBILESTACKS_PRIVATE_KEY ||
33
+ process.env.STACKS_PRIVATE_KEY ||
34
+ config.wallet.privateKey ||
35
+ '';
36
+ const seedPhrase = process.env.MOBILESTACKS_SEED_PHRASE ||
37
+ process.env.STACKS_SEED_PHRASE ||
38
+ config.wallet.seedPhrase ||
39
+ '';
40
+ if (privateKey) {
41
+ const address = (0, transactions_1.getAddressFromPrivateKey)(privateKey, networkName === 'mainnet' ? 'mainnet' : 'testnet');
42
+ this.wallet = { privateKey, address };
43
+ }
44
+ else if (seedPhrase) {
45
+ const derivPath = config.wallet.derivationPath || "m/44'/5757'/0'/0/0";
46
+ (0, wallet_sdk_1.generateWallet)({ secretKey: seedPhrase, password: '' }).then(wallet => {
47
+ const index = parseInt(derivPath.split('/').pop() || '0', 10);
48
+ const account = wallet.accounts[index] || wallet.accounts[0];
49
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
50
+ const { getStxAddress } = require('@stacks/wallet-sdk/dist/models/account');
51
+ const address = getStxAddress(account, this.network.transactionVersion);
52
+ this.wallet = {
53
+ privateKey: account.stxPrivateKey,
54
+ address,
55
+ accountIndex: account.index,
56
+ };
57
+ }).catch(() => {
58
+ throw new Error('Failed to generate wallet from seed phrase');
59
+ });
60
+ }
61
+ else {
62
+ // No secrets anywhere — warn but don't crash (devnet may not need a wallet)
63
+ console.warn('⚠️ No wallet secret found. Set MOBILESTACKS_PRIVATE_KEY or MOBILESTACKS_SEED_PHRASE in your .env file.');
64
+ }
65
+ this.stacks = {};
66
+ // Apply extensions
67
+ for (const extension of extender_1.Extender.getInstance().getExtensions()) {
68
+ extension(this);
69
+ }
70
+ }
71
+ }
72
+ exports.RuntimeEnvironment = RuntimeEnvironment;
@@ -0,0 +1,17 @@
1
+ import { initSimnet } from '@hirosystems/clarinet-sdk';
2
+ import { ClarityValue } from '@stacks/transactions';
3
+ type SimnetInstance = Awaited<ReturnType<typeof initSimnet>>;
4
+ export declare class Simnet {
5
+ private static _instance;
6
+ simnet: SimnetInstance;
7
+ accounts: Map<string, string>;
8
+ private constructor();
9
+ static init(): Promise<Simnet>;
10
+ getDeployer(): string;
11
+ getAccount(name: string): string;
12
+ callPublic(contract: string, func: string, args: ClarityValue[], sender: string): import("@hirosystems/clarinet-sdk").ParsedTransactionResult;
13
+ callReadOnly(contract: string, func: string, args: ClarityValue[], sender: string): import("@hirosystems/clarinet-sdk").ParsedTransactionResult;
14
+ mineBlock(txs: Parameters<SimnetInstance['mineBlock']>[0]): Promise<import("@hirosystems/clarinet-sdk").ParsedTransactionResult[]>;
15
+ }
16
+ export {};
17
+ //# sourceMappingURL=simnet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simnet.d.ts","sourceRoot":"","sources":["../../src/core/simnet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAKpD,KAAK,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC;AAE7D,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAS;IAC1B,MAAM,EAAG,cAAc,CAAC;IACxB,QAAQ,EAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEtC,OAAO;WAEa,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAiBpC,WAAW,IAAI,MAAM;IAMrB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAMhC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM;IAI/E,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM;IAI3E,SAAS,CAAC,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;CAGvE"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Simnet = void 0;
4
+ const clarinet_sdk_1 = require("@hirosystems/clarinet-sdk");
5
+ class Simnet {
6
+ constructor() { }
7
+ static async init() {
8
+ if (!Simnet._instance) {
9
+ Simnet._instance = new Simnet();
10
+ // Initialize SDK - auto-detects Clarinet.toml from CWD
11
+ try {
12
+ console.log('Initializing Simnet...');
13
+ Simnet._instance.simnet = await (0, clarinet_sdk_1.initSimnet)();
14
+ // Get accounts
15
+ Simnet._instance.accounts = Simnet._instance.simnet.getAccounts();
16
+ }
17
+ catch (error) {
18
+ console.error('Failed to initialize Simnet:', error);
19
+ throw error;
20
+ }
21
+ }
22
+ return Simnet._instance;
23
+ }
24
+ getDeployer() {
25
+ const deployer = this.accounts.get('deployer');
26
+ if (!deployer)
27
+ throw new Error('Deployer account not found');
28
+ return deployer;
29
+ }
30
+ getAccount(name) {
31
+ const acc = this.accounts.get(name);
32
+ if (!acc)
33
+ throw new Error(`Account ${name} not found`);
34
+ return acc;
35
+ }
36
+ callPublic(contract, func, args, sender) {
37
+ return this.simnet.callPublicFn(contract, func, args, sender);
38
+ }
39
+ callReadOnly(contract, func, args, sender) {
40
+ return this.simnet.callReadOnlyFn(contract, func, args, sender);
41
+ }
42
+ async mineBlock(txs) {
43
+ return this.simnet.mineBlock(txs);
44
+ }
45
+ }
46
+ exports.Simnet = Simnet;