mobilestacks 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.
Files changed (96) hide show
  1. package/Clarinet.toml +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +188 -0
  4. package/contracts/sample-contract.clar +2 -0
  5. package/dist/mobilestacks.config.d.ts +20 -0
  6. package/dist/mobilestacks.config.d.ts.map +1 -0
  7. package/dist/mobilestacks.config.js +23 -0
  8. package/dist/src/cli/index.d.ts +3 -0
  9. package/dist/src/cli/index.d.ts.map +1 -0
  10. package/dist/src/cli/index.js +102 -0
  11. package/dist/src/cli/init.d.ts +2 -0
  12. package/dist/src/cli/init.d.ts.map +1 -0
  13. package/dist/src/cli/init.js +55 -0
  14. package/dist/src/config/config-loading.d.ts +3 -0
  15. package/dist/src/config/config-loading.d.ts.map +1 -0
  16. package/dist/src/config/config-loading.js +29 -0
  17. package/dist/src/core/dsl.d.ts +30 -0
  18. package/dist/src/core/dsl.d.ts.map +1 -0
  19. package/dist/src/core/dsl.js +62 -0
  20. package/dist/src/core/dsl.test.d.ts +2 -0
  21. package/dist/src/core/dsl.test.d.ts.map +1 -0
  22. package/dist/src/core/dsl.test.js +48 -0
  23. package/dist/src/core/env.d.ts +6 -0
  24. package/dist/src/core/env.d.ts.map +1 -0
  25. package/dist/src/core/env.js +7 -0
  26. package/dist/src/core/extender.d.ts +12 -0
  27. package/dist/src/core/extender.d.ts.map +1 -0
  28. package/dist/src/core/extender.js +20 -0
  29. package/dist/src/core/runtime-environment.d.ts +15 -0
  30. package/dist/src/core/runtime-environment.d.ts.map +1 -0
  31. package/dist/src/core/runtime-environment.js +65 -0
  32. package/dist/src/core/simnet.d.ts +17 -0
  33. package/dist/src/core/simnet.d.ts.map +1 -0
  34. package/dist/src/core/simnet.js +42 -0
  35. package/dist/src/core/tasks-definitions.d.ts +28 -0
  36. package/dist/src/core/tasks-definitions.d.ts.map +1 -0
  37. package/dist/src/core/tasks-definitions.js +21 -0
  38. package/dist/src/index.d.ts +5 -0
  39. package/dist/src/index.d.ts.map +1 -0
  40. package/dist/src/index.js +4 -0
  41. package/dist/src/tasks/call-contract-function.d.ts +2 -0
  42. package/dist/src/tasks/call-contract-function.d.ts.map +1 -0
  43. package/dist/src/tasks/call-contract-function.js +31 -0
  44. package/dist/src/tasks/deploy-contract.d.ts +2 -0
  45. package/dist/src/tasks/deploy-contract.d.ts.map +1 -0
  46. package/dist/src/tasks/deploy-contract.js +44 -0
  47. package/dist/src/tasks/example-task.d.ts +2 -0
  48. package/dist/src/tasks/example-task.d.ts.map +1 -0
  49. package/dist/src/tasks/example-task.js +6 -0
  50. package/dist/src/tasks/faucet-request.d.ts +2 -0
  51. package/dist/src/tasks/faucet-request.d.ts.map +1 -0
  52. package/dist/src/tasks/faucet-request.js +21 -0
  53. package/dist/src/tasks/get-balance.d.ts +2 -0
  54. package/dist/src/tasks/get-balance.d.ts.map +1 -0
  55. package/dist/src/tasks/get-balance.js +33 -0
  56. package/dist/src/tasks/get-contract-info.d.ts +2 -0
  57. package/dist/src/tasks/get-contract-info.d.ts.map +1 -0
  58. package/dist/src/tasks/get-contract-info.js +18 -0
  59. package/dist/src/tasks/get-tx-history.d.ts +2 -0
  60. package/dist/src/tasks/get-tx-history.d.ts.map +1 -0
  61. package/dist/src/tasks/get-tx-history.js +38 -0
  62. package/dist/src/tasks/list-accounts.d.ts +2 -0
  63. package/dist/src/tasks/list-accounts.d.ts.map +1 -0
  64. package/dist/src/tasks/list-accounts.js +24 -0
  65. package/dist/src/tasks/send-stx.d.ts +2 -0
  66. package/dist/src/tasks/send-stx.d.ts.map +1 -0
  67. package/dist/src/tasks/send-stx.js +36 -0
  68. package/dist/src/tasks/verify-contract.d.ts +2 -0
  69. package/dist/src/tasks/verify-contract.d.ts.map +1 -0
  70. package/dist/src/tasks/verify-contract.js +33 -0
  71. package/dist/src/types/config.d.ts +120 -0
  72. package/dist/src/types/config.d.ts.map +1 -0
  73. package/dist/src/types/config.js +19 -0
  74. package/package.json +70 -0
  75. package/src/cli/index.ts +105 -0
  76. package/src/cli/init.ts +57 -0
  77. package/src/config/config-loading.ts +31 -0
  78. package/src/core/dsl.test.ts +63 -0
  79. package/src/core/dsl.ts +73 -0
  80. package/src/core/env.ts +8 -0
  81. package/src/core/extender.ts +29 -0
  82. package/src/core/runtime-environment.ts +74 -0
  83. package/src/core/simnet.ts +56 -0
  84. package/src/core/tasks-definitions.ts +47 -0
  85. package/src/index.ts +4 -0
  86. package/src/tasks/call-contract-function.ts +31 -0
  87. package/src/tasks/deploy-contract.ts +49 -0
  88. package/src/tasks/example-task.ts +7 -0
  89. package/src/tasks/faucet-request.ts +21 -0
  90. package/src/tasks/get-balance.ts +34 -0
  91. package/src/tasks/get-contract-info.ts +18 -0
  92. package/src/tasks/get-tx-history.ts +39 -0
  93. package/src/tasks/list-accounts.ts +27 -0
  94. package/src/tasks/send-stx.ts +39 -0
  95. package/src/tasks/verify-contract.ts +33 -0
  96. package/src/types/config.ts +30 -0
@@ -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,20 @@
1
+ export class Extender {
2
+ constructor() {
3
+ this._extensions = [];
4
+ }
5
+ static getInstance() {
6
+ if (!Extender._instance) {
7
+ Extender._instance = new Extender();
8
+ }
9
+ return Extender._instance;
10
+ }
11
+ addExtension(func) {
12
+ this._extensions.push(func);
13
+ }
14
+ getExtensions() {
15
+ return this._extensions;
16
+ }
17
+ }
18
+ export function extendEnvironment(func) {
19
+ Extender.getInstance().addExtension(func);
20
+ }
@@ -0,0 +1,15 @@
1
+ import { MobilestacksConfig } from '../types/config';
2
+ import { StacksNetwork } from '@stacks/network';
3
+ export declare class RuntimeEnvironment {
4
+ config: MobilestacksConfig;
5
+ network: StacksNetwork;
6
+ wallet: {
7
+ privateKey: string;
8
+ address: string;
9
+ accountIndex?: number;
10
+ };
11
+ stacks: Record<string, unknown>;
12
+ [key: string]: unknown;
13
+ constructor(config: MobilestacksConfig);
14
+ }
15
+ //# 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,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;CA4DvC"}
@@ -0,0 +1,65 @@
1
+ import { getAddressFromPrivateKey } from '@stacks/transactions';
2
+ import { generateWallet } from '@stacks/wallet-sdk';
3
+ import { createNetwork } from '@stacks/network';
4
+ import { Extender } from './extender';
5
+ export class RuntimeEnvironment {
6
+ constructor(config) {
7
+ this.config = config;
8
+ const networkName = config.defaultNetwork;
9
+ const networkConfig = config.networks[networkName];
10
+ if (!networkConfig) {
11
+ throw new Error(`Network config not found for: ${networkName}`);
12
+ }
13
+ // Instantiate proper StacksNetwork
14
+ if (networkName === 'mainnet' || networkName === 'testnet') {
15
+ this.network = createNetwork({
16
+ network: networkName,
17
+ client: { baseUrl: networkConfig.url }
18
+ });
19
+ }
20
+ else {
21
+ // Default to testnet structure for custom networks
22
+ this.network = createNetwork({
23
+ network: 'testnet',
24
+ client: { baseUrl: networkConfig.url }
25
+ });
26
+ }
27
+ // Wallet: support privateKey, seedPhrase+derivationPath, or both (prefer privateKey)
28
+ if (config.wallet.privateKey) {
29
+ // Derive address from privateKey
30
+ const address = getAddressFromPrivateKey(config.wallet.privateKey, networkName === 'mainnet' ? 'mainnet' : 'testnet');
31
+ this.wallet = {
32
+ privateKey: config.wallet.privateKey,
33
+ address,
34
+ };
35
+ }
36
+ else if (config.wallet.seedPhrase) {
37
+ const path = config.wallet.derivationPath || "m/44'/5757'/0'/0/0"; // Stacks main path
38
+ // generateWallet requires a password param
39
+ generateWallet({ secretKey: config.wallet.seedPhrase, password: '' }).then(wallet => {
40
+ const index = parseInt(path.split('/').pop() || '0', 10);
41
+ const account = wallet.accounts[index] || wallet.accounts[0];
42
+ // Use getStxAddress to get the address
43
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
44
+ const { getStxAddress } = require('@stacks/wallet-sdk/dist/models/account');
45
+ // network.addressVersion has singleSig/multiSig lines.
46
+ const address = getStxAddress(account, this.network.transactionVersion);
47
+ this.wallet = {
48
+ privateKey: account.stxPrivateKey,
49
+ address,
50
+ accountIndex: account.index,
51
+ };
52
+ }).catch(() => {
53
+ throw new Error('Failed to generate wallet from seed phrase');
54
+ });
55
+ }
56
+ else {
57
+ throw new Error('No privateKey or seedPhrase provided in wallet config');
58
+ }
59
+ this.stacks = {};
60
+ // Apply extensions
61
+ for (const extension of Extender.getInstance().getExtensions()) {
62
+ extension(this);
63
+ }
64
+ }
65
+ }
@@ -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,42 @@
1
+ import { initSimnet } from '@hirosystems/clarinet-sdk';
2
+ export class Simnet {
3
+ constructor() { }
4
+ static async init() {
5
+ if (!Simnet._instance) {
6
+ Simnet._instance = new Simnet();
7
+ // Initialize SDK - auto-detects Clarinet.toml from CWD
8
+ try {
9
+ console.log('Initializing Simnet...');
10
+ Simnet._instance.simnet = await initSimnet();
11
+ // Get accounts
12
+ Simnet._instance.accounts = Simnet._instance.simnet.getAccounts();
13
+ }
14
+ catch (error) {
15
+ console.error('Failed to initialize Simnet:', error);
16
+ throw error;
17
+ }
18
+ }
19
+ return Simnet._instance;
20
+ }
21
+ getDeployer() {
22
+ const deployer = this.accounts.get('deployer');
23
+ if (!deployer)
24
+ throw new Error('Deployer account not found');
25
+ return deployer;
26
+ }
27
+ getAccount(name) {
28
+ const acc = this.accounts.get(name);
29
+ if (!acc)
30
+ throw new Error(`Account ${name} not found`);
31
+ return acc;
32
+ }
33
+ callPublic(contract, func, args, sender) {
34
+ return this.simnet.callPublicFn(contract, func, args, sender);
35
+ }
36
+ callReadOnly(contract, func, args, sender) {
37
+ return this.simnet.callReadOnlyFn(contract, func, args, sender);
38
+ }
39
+ async mineBlock(txs) {
40
+ return this.simnet.mineBlock(txs);
41
+ }
42
+ }
@@ -0,0 +1,28 @@
1
+ import { ZodSchema } from 'zod';
2
+ import { RuntimeEnvironment } from './runtime-environment';
3
+ export type TaskParamType = 'string' | 'number' | 'boolean';
4
+ export interface TaskParam {
5
+ name: string;
6
+ description: string;
7
+ type?: TaskParamType;
8
+ required?: boolean;
9
+ defaultValue?: unknown;
10
+ schema?: ZodSchema;
11
+ }
12
+ export interface TaskDefinition {
13
+ name: string;
14
+ description: string;
15
+ params: TaskParam[];
16
+ action: (args: Record<string, unknown>, env: RuntimeEnvironment) => Promise<unknown>;
17
+ }
18
+ declare class TaskDefinitions {
19
+ private static _instance;
20
+ private _tasks;
21
+ private constructor();
22
+ static getInstance(): TaskDefinitions;
23
+ addTask(task: TaskDefinition): void;
24
+ getTask(name: string): TaskDefinition | undefined;
25
+ getAllTasks(): TaskDefinition[];
26
+ }
27
+ export { TaskDefinitions };
28
+ //# sourceMappingURL=tasks-definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tasks-definitions.d.ts","sourceRoot":"","sources":["../../../src/core/tasks-definitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC5D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,kBAAkB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CACtF;AAED,cAAM,eAAe;IACnB,OAAO,CAAC,MAAM,CAAC,SAAS,CAAkB;IAC1C,OAAO,CAAC,MAAM,CAAwB;IAEtC,OAAO;WAEO,WAAW,IAAI,eAAe;IAOrC,OAAO,CAAC,IAAI,EAAE,cAAc;IAI5B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIjD,WAAW,IAAI,cAAc,EAAE;CAGvC;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,21 @@
1
+ class TaskDefinitions {
2
+ constructor() {
3
+ this._tasks = [];
4
+ }
5
+ static getInstance() {
6
+ if (!TaskDefinitions._instance) {
7
+ TaskDefinitions._instance = new TaskDefinitions();
8
+ }
9
+ return TaskDefinitions._instance;
10
+ }
11
+ addTask(task) {
12
+ this._tasks.push(task);
13
+ }
14
+ getTask(name) {
15
+ return this._tasks.find((t) => t.name === name);
16
+ }
17
+ getAllTasks() {
18
+ return this._tasks;
19
+ }
20
+ }
21
+ export { TaskDefinitions };
@@ -0,0 +1,5 @@
1
+ export { task, subtask, extendEnvironment } from './core/dsl';
2
+ export { Simnet } from './core/simnet';
3
+ export { RuntimeEnvironment } from './core/runtime-environment';
4
+ export * from './core/tasks-definitions';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { task, subtask, extendEnvironment } from './core/dsl';
2
+ export { Simnet } from './core/simnet';
3
+ export { RuntimeEnvironment } from './core/runtime-environment';
4
+ export * from './core/tasks-definitions';
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=call-contract-function.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call-contract-function.d.ts","sourceRoot":"","sources":["../../../src/tasks/call-contract-function.ts"],"names":[],"mappings":""}
@@ -0,0 +1,31 @@
1
+ import { task } from '../core/dsl';
2
+ import fetch from 'node-fetch';
3
+ task('call-contract-function', 'Call a public function on a deployed Clarity contract')
4
+ .addParam('contractAddress', 'Deployed contract address (STX...)', { type: 'string', required: true })
5
+ .addParam('contractName', 'Contract name', { type: 'string', required: true })
6
+ .addParam('functionName', 'Function name', { type: 'string', required: true })
7
+ .addParam('args', 'Comma-separated function arguments', { type: 'string', required: false, defaultValue: '' })
8
+ .addParam('network', 'Network (mainnet|testnet)', { type: 'string', required: false, defaultValue: 'testnet' })
9
+ .setAction(async (args) => {
10
+ const contractAddress = args.contractAddress;
11
+ const contractName = args.contractName;
12
+ const functionName = args.functionName;
13
+ const fnArgs = args.args;
14
+ const network = args.network;
15
+ const apiUrl = network === 'mainnet'
16
+ ? 'https://stacks-node-api.mainnet.stacks.co'
17
+ : 'https://stacks-node-api.testnet.stacks.co';
18
+ const url = `${apiUrl}/v2/contracts/call-read/${contractAddress}/${contractName}/${functionName}`;
19
+ const body = fnArgs
20
+ ? { arguments: fnArgs.split(',').map((a) => a.trim()) }
21
+ : { arguments: [] };
22
+ const res = await fetch(url, {
23
+ method: 'POST',
24
+ headers: { 'Content-Type': 'application/json' },
25
+ body: JSON.stringify(body)
26
+ });
27
+ if (!res.ok)
28
+ throw new Error(`Failed to call contract function: ${res.statusText}`);
29
+ const result = await res.json();
30
+ return result;
31
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=deploy-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-contract.d.ts","sourceRoot":"","sources":["../../../src/tasks/deploy-contract.ts"],"names":[],"mappings":""}
@@ -0,0 +1,44 @@
1
+ import { task } from '../core/dsl';
2
+ import { makeContractDeploy, broadcastTransaction, } from '@stacks/transactions';
3
+ import { createNetwork } from '@stacks/network';
4
+ import fs from 'fs';
5
+ function maskAddress(address) {
6
+ return address ? address.slice(0, 6) + '...' + address.slice(-4) : '';
7
+ }
8
+ function containsSecret(obj) {
9
+ const str = JSON.stringify(obj);
10
+ return /[A-Za-z0-9]{32,}/.test(str); // crude check for long secrets
11
+ }
12
+ // Deploy a Clarity contract to Stacks mainnet or testnet
13
+ task('deploy-contract', 'Deploy a Clarity smart contract to Stacks blockchain')
14
+ .addParam('contractName', 'Name of the contract', { type: 'string', required: true })
15
+ .addParam('file', 'Path to Clarity contract file', { type: 'string', required: true })
16
+ .addParam('network', 'Network to deploy to (mainnet|testnet)', { type: 'string', required: false, defaultValue: 'testnet' })
17
+ .setAction(async (args, env) => {
18
+ const contractName = args.contractName;
19
+ const file = args.file;
20
+ const network = args.network;
21
+ const codeBody = fs.readFileSync(file, 'utf8');
22
+ // Switch network if needed
23
+ if (network === 'mainnet') {
24
+ env.network = createNetwork({ network: 'mainnet', client: { baseUrl: env.config.networks.mainnet.url } });
25
+ }
26
+ else {
27
+ env.network = createNetwork({ network: 'testnet', client: { baseUrl: env.config.networks.testnet.url } });
28
+ }
29
+ const tx = await makeContractDeploy({
30
+ contractName,
31
+ codeBody,
32
+ senderKey: env.wallet.privateKey,
33
+ network: env.network,
34
+ });
35
+ const result = await broadcastTransaction({ transaction: tx, network: env.network });
36
+ if (containsSecret(result)) {
37
+ console.warn('[mobilestacks] Warning: Output may contain sensitive data.');
38
+ }
39
+ // Mask any address fields if present
40
+ if (result && result.txid) {
41
+ result.txid = maskAddress(result.txid);
42
+ }
43
+ return result;
44
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=example-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"example-task.d.ts","sourceRoot":"","sources":["../../../src/tasks/example-task.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import { task } from '../core/dsl';
2
+ task('example', 'An example user task for onboarding')
3
+ .addParam('name', 'Your name', { type: 'string', required: false, defaultValue: 'World' })
4
+ .setAction(async (args) => {
5
+ return `Hello, ${args.name}! Welcome to mobilestacks.`;
6
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=faucet-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faucet-request.d.ts","sourceRoot":"","sources":["../../../src/tasks/faucet-request.ts"],"names":[],"mappings":""}
@@ -0,0 +1,21 @@
1
+ import { task } from '../core/dsl';
2
+ import fetch from 'node-fetch';
3
+ task('faucet-request', 'Request STX from the testnet faucet')
4
+ .addParam('address', 'STX address to fund', { type: 'string', required: true })
5
+ .setAction(async (args, env) => {
6
+ if (env.network.client.baseUrl && env.network.client.baseUrl.includes('testnet')) {
7
+ const url = `https://stacks-node-api.testnet.stacks.co/extended/v1/faucet/stx`; // Default testnet faucet
8
+ const res = await fetch(url, {
9
+ method: 'POST',
10
+ headers: { 'Content-Type': 'application/json' },
11
+ body: JSON.stringify({ address: args.address })
12
+ });
13
+ if (!res.ok) {
14
+ throw new Error(`Faucet request failed: ${res.statusText}`);
15
+ }
16
+ return await res.json();
17
+ }
18
+ else {
19
+ throw new Error('Faucet is only available on testnet.');
20
+ }
21
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=get-balance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-balance.d.ts","sourceRoot":"","sources":["../../../src/tasks/get-balance.ts"],"names":[],"mappings":""}
@@ -0,0 +1,33 @@
1
+ import { task } from '../core/dsl';
2
+ import fetch from 'node-fetch';
3
+ function maskAddress(address) {
4
+ return address ? address.slice(0, 6) + '...' + address.slice(-4) : '';
5
+ }
6
+ function containsSecret(obj) {
7
+ const str = JSON.stringify(obj);
8
+ return /[A-Za-z0-9]{32,}/.test(str); // crude check for long secrets
9
+ }
10
+ task('get-balance', 'Get STX balance for the configured wallet address or a provided address')
11
+ .addParam('address', 'STX address to check (optional, defaults to wallet main address)', { type: 'string', required: false })
12
+ .setAction(async (args, env) => {
13
+ const address = args.address || env.wallet.address;
14
+ if (!address)
15
+ throw new Error('No wallet address found.');
16
+ const network = env.network;
17
+ const apiUrl = network.client.baseUrl;
18
+ const url = `${apiUrl}/extended/v1/address/${address}/balances`;
19
+ const res = await fetch(url);
20
+ if (!res.ok)
21
+ throw new Error(`Failed to fetch balance: ${res.statusText}`);
22
+ const data = await res.json();
23
+ const result = {
24
+ address: maskAddress(address),
25
+ stx: data.stx.balance,
26
+ locked: data.stx.locked,
27
+ unlock_height: data.stx.unlock_height
28
+ };
29
+ if (containsSecret(result)) {
30
+ console.warn('[mobilestacks] Warning: Output may contain sensitive data.');
31
+ }
32
+ return result;
33
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=get-contract-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-contract-info.d.ts","sourceRoot":"","sources":["../../../src/tasks/get-contract-info.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { task } from '../core/dsl';
2
+ import fetch from 'node-fetch';
3
+ task('get-contract-info', 'Get contract attributes and details from Stacks blockchain')
4
+ .addParam('contractAddress', 'Deployed contract address (STX...)', { type: 'string', required: true })
5
+ .addParam('contractName', 'Contract name', { type: 'string', required: true })
6
+ .addParam('network', 'Network (mainnet|testnet)', { type: 'string', required: false, defaultValue: 'testnet' })
7
+ .setAction(async (args) => {
8
+ const { contractAddress, contractName, network } = args;
9
+ const apiUrl = network === 'mainnet'
10
+ ? 'https://stacks-node-api.mainnet.stacks.co'
11
+ : 'https://stacks-node-api.testnet.stacks.co';
12
+ const url = `${apiUrl}/extended/v1/contract/${contractAddress}/${contractName}`;
13
+ const res = await fetch(url);
14
+ if (!res.ok)
15
+ throw new Error(`Failed to fetch contract info: ${res.statusText}`);
16
+ const info = await res.json();
17
+ return info;
18
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=get-tx-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-tx-history.d.ts","sourceRoot":"","sources":["../../../src/tasks/get-tx-history.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { task } from '../core/dsl';
2
+ import fetch from 'node-fetch';
3
+ function maskAddress(address) {
4
+ return address ? address.slice(0, 6) + '...' + address.slice(-4) : '';
5
+ }
6
+ function containsSecret(obj) {
7
+ const str = JSON.stringify(obj);
8
+ return /[A-Za-z0-9]{32,}/.test(str); // crude check for long secrets
9
+ }
10
+ task('get-tx-history', 'Get transaction history for the configured wallet address')
11
+ .addParam('limit', 'Number of transactions to fetch', { type: 'number', required: false, defaultValue: 10 })
12
+ .setAction(async (args, env) => {
13
+ const address = env.wallet.address;
14
+ if (!address)
15
+ throw new Error('No wallet address found.');
16
+ const network = env.network;
17
+ const apiUrl = network.client.baseUrl;
18
+ const url = `${apiUrl}/extended/v1/address/${address}/transactions?limit=${args.limit}`;
19
+ const res = await fetch(url);
20
+ if (!res.ok)
21
+ throw new Error(`Failed to fetch tx history: ${res.statusText}`);
22
+ const data = await res.json();
23
+ const txs = data.results.map((tx) => ({
24
+ tx_id: tx.tx_id,
25
+ type: tx.tx_type,
26
+ status: tx.tx_status,
27
+ fee_rate: tx.fee_rate,
28
+ block_height: tx.block_height
29
+ }));
30
+ // Mask address in logs and warn if secrets detected
31
+ if (containsSecret(txs)) {
32
+ console.warn('[mobilestacks] Warning: Output may contain sensitive data.');
33
+ }
34
+ return {
35
+ address: maskAddress(address),
36
+ transactions: txs
37
+ };
38
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=list-accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-accounts.d.ts","sourceRoot":"","sources":["../../../src/tasks/list-accounts.ts"],"names":[],"mappings":""}
@@ -0,0 +1,24 @@
1
+ import { task } from '../core/dsl';
2
+ import { generateWallet } from '@stacks/wallet-sdk';
3
+ function maskAddress(address) {
4
+ return address ? address.slice(0, 6) + '...' + address.slice(-4) : '';
5
+ }
6
+ function containsSecret(obj) {
7
+ const str = JSON.stringify(obj);
8
+ return /[A-Za-z0-9]{32,}/.test(str); // crude check for long secrets
9
+ }
10
+ task('list-accounts', 'List all accounts derived from the configured seed phrase')
11
+ .setAction(async (args, env) => {
12
+ if (!env.config.wallet.seedPhrase) {
13
+ throw new Error('No seed phrase configured.');
14
+ }
15
+ const wallet = await generateWallet({ secretKey: env.config.wallet.seedPhrase, password: '' });
16
+ const result = wallet.accounts.map((a) => ({
17
+ address: maskAddress(a.address || a.stxAddress),
18
+ index: a.index
19
+ }));
20
+ if (containsSecret(result)) {
21
+ console.warn('[mobilestacks] Warning: Output may contain sensitive data.');
22
+ }
23
+ return result;
24
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=send-stx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-stx.d.ts","sourceRoot":"","sources":["../../../src/tasks/send-stx.ts"],"names":[],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { task } from '../core/dsl';
2
+ import { broadcastTransaction, makeSTXTokenTransfer } from '@stacks/transactions';
3
+ function maskAddress(address) {
4
+ return address ? address.slice(0, 6) + '...' + address.slice(-4) : '';
5
+ }
6
+ function containsSecret(obj) {
7
+ const str = JSON.stringify(obj);
8
+ return /[A-Za-z0-9]{32,}/.test(str); // crude check for long secrets
9
+ }
10
+ // This task sends STX to an address using the loaded SRE (env)
11
+ task('send-stx', 'Sends STX to an address')
12
+ .addParam('to', 'Recipient STX address', { type: 'string', required: true })
13
+ .addParam('amount', 'Amount in microSTX', { type: 'number', required: true })
14
+ .addParam('memo', 'Optional memo', { type: 'string', required: false, defaultValue: '' })
15
+ .setAction(async (args, env) => {
16
+ const to = args.to;
17
+ const amount = args.amount;
18
+ const memo = args.memo;
19
+ const { wallet, network } = env;
20
+ const tx = await makeSTXTokenTransfer({
21
+ recipient: to,
22
+ amount: BigInt(amount),
23
+ senderKey: wallet.privateKey,
24
+ network,
25
+ memo: memo || undefined
26
+ });
27
+ const result = await broadcastTransaction({ transaction: tx, network });
28
+ if (containsSecret(result)) {
29
+ console.warn('[mobilestacks] Warning: Output may contain sensitive data.');
30
+ }
31
+ // Mask any address fields if present
32
+ if (result && result.txid) {
33
+ result.txid = maskAddress(result.txid);
34
+ }
35
+ return result;
36
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=verify-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-contract.d.ts","sourceRoot":"","sources":["../../../src/tasks/verify-contract.ts"],"names":[],"mappings":""}
@@ -0,0 +1,33 @@
1
+ import { task } from '../core/dsl';
2
+ import fetch from 'node-fetch';
3
+ import fs from 'fs';
4
+ task('verify-contract', 'Verify a deployed Clarity contract on the Stacks explorer')
5
+ .addParam('contractAddress', 'Deployed contract address (STX...)', { type: 'string', required: true })
6
+ .addParam('contractName', 'Contract name', { type: 'string', required: true })
7
+ .addParam('source', 'Path to contract source file', { type: 'string', required: true })
8
+ .addParam('network', 'Network (mainnet|testnet)', { type: 'string', required: false, defaultValue: 'testnet' })
9
+ .setAction(async (args) => {
10
+ const contractAddress = args.contractAddress;
11
+ const contractName = args.contractName;
12
+ const source = args.source;
13
+ const network = args.network;
14
+ const codeBody = fs.readFileSync(source, 'utf8');
15
+ const apiUrl = network === 'mainnet'
16
+ ? 'https://stacks-node-api.mainnet.stacks.co'
17
+ : 'https://stacks-node-api.testnet.stacks.co';
18
+ // Fetch contract source from chain
19
+ const url = `${apiUrl}/extended/v1/contract/source/${contractAddress}/${contractName}`;
20
+ const res = await fetch(url);
21
+ if (!res.ok)
22
+ throw new Error(`Failed to fetch on-chain contract source: ${res.statusText}`);
23
+ const onChain = await res.json();
24
+ const verified = onChain.source_code && onChain.source_code.trim() === codeBody.trim();
25
+ const explorer = network === 'mainnet'
26
+ ? `https://explorer.stacks.co/txid/${contractAddress}.${contractName}`
27
+ : `https://explorer.stacks.co/txid/${contractAddress}.${contractName}?chain=testnet`;
28
+ return {
29
+ verified,
30
+ message: verified ? 'Contract source matches on-chain code!' : 'Source does NOT match on-chain code!',
31
+ explorer
32
+ };
33
+ });