movehat 0.0.1-alpha.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 (170) hide show
  1. package/README.md +236 -0
  2. package/bin/movehat.js +21 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +93 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/compile.d.ts +2 -0
  8. package/dist/commands/compile.d.ts.map +1 -0
  9. package/dist/commands/compile.js +71 -0
  10. package/dist/commands/compile.js.map +1 -0
  11. package/dist/commands/fork/create.d.ts +11 -0
  12. package/dist/commands/fork/create.d.ts.map +1 -0
  13. package/dist/commands/fork/create.js +56 -0
  14. package/dist/commands/fork/create.js.map +1 -0
  15. package/dist/commands/fork/fund.d.ts +12 -0
  16. package/dist/commands/fork/fund.d.ts.map +1 -0
  17. package/dist/commands/fork/fund.js +42 -0
  18. package/dist/commands/fork/fund.js.map +1 -0
  19. package/dist/commands/fork/list.d.ts +5 -0
  20. package/dist/commands/fork/list.d.ts.map +1 -0
  21. package/dist/commands/fork/list.js +61 -0
  22. package/dist/commands/fork/list.js.map +1 -0
  23. package/dist/commands/fork/serve.d.ts +10 -0
  24. package/dist/commands/fork/serve.d.ts.map +1 -0
  25. package/dist/commands/fork/serve.js +64 -0
  26. package/dist/commands/fork/serve.js.map +1 -0
  27. package/dist/commands/fork/view-resource.d.ts +11 -0
  28. package/dist/commands/fork/view-resource.d.ts.map +1 -0
  29. package/dist/commands/fork/view-resource.js +34 -0
  30. package/dist/commands/fork/view-resource.js.map +1 -0
  31. package/dist/commands/init.d.ts +2 -0
  32. package/dist/commands/init.d.ts.map +1 -0
  33. package/dist/commands/init.js +90 -0
  34. package/dist/commands/init.js.map +1 -0
  35. package/dist/commands/run.d.ts +2 -0
  36. package/dist/commands/run.d.ts.map +1 -0
  37. package/dist/commands/run.js +51 -0
  38. package/dist/commands/run.js.map +1 -0
  39. package/dist/commands/test.d.ts +2 -0
  40. package/dist/commands/test.d.ts.map +1 -0
  41. package/dist/commands/test.js +35 -0
  42. package/dist/commands/test.js.map +1 -0
  43. package/dist/core/config.d.ts +15 -0
  44. package/dist/core/config.d.ts.map +1 -0
  45. package/dist/core/config.js +121 -0
  46. package/dist/core/config.js.map +1 -0
  47. package/dist/core/contract.d.ts +20 -0
  48. package/dist/core/contract.d.ts.map +1 -0
  49. package/dist/core/contract.js +59 -0
  50. package/dist/core/contract.js.map +1 -0
  51. package/dist/core/deployments.d.ts +32 -0
  52. package/dist/core/deployments.d.ts.map +1 -0
  53. package/dist/core/deployments.js +122 -0
  54. package/dist/core/deployments.js.map +1 -0
  55. package/dist/core/shell.d.ts +25 -0
  56. package/dist/core/shell.d.ts.map +1 -0
  57. package/dist/core/shell.js +56 -0
  58. package/dist/core/shell.js.map +1 -0
  59. package/dist/errors.d.ts +12 -0
  60. package/dist/errors.d.ts.map +1 -0
  61. package/dist/errors.js +24 -0
  62. package/dist/errors.js.map +1 -0
  63. package/dist/fork/api.d.ts +33 -0
  64. package/dist/fork/api.d.ts.map +1 -0
  65. package/dist/fork/api.js +98 -0
  66. package/dist/fork/api.js.map +1 -0
  67. package/dist/fork/manager.d.ts +52 -0
  68. package/dist/fork/manager.d.ts.map +1 -0
  69. package/dist/fork/manager.js +221 -0
  70. package/dist/fork/manager.js.map +1 -0
  71. package/dist/fork/server.d.ts +55 -0
  72. package/dist/fork/server.d.ts.map +1 -0
  73. package/dist/fork/server.js +274 -0
  74. package/dist/fork/server.js.map +1 -0
  75. package/dist/fork/storage.d.ts +63 -0
  76. package/dist/fork/storage.d.ts.map +1 -0
  77. package/dist/fork/storage.js +183 -0
  78. package/dist/fork/storage.js.map +1 -0
  79. package/dist/fork/test.d.ts +75 -0
  80. package/dist/fork/test.d.ts.map +1 -0
  81. package/dist/fork/test.js +157 -0
  82. package/dist/fork/test.js.map +1 -0
  83. package/dist/helpers/assertions.d.ts +7 -0
  84. package/dist/helpers/assertions.d.ts.map +1 -0
  85. package/dist/helpers/assertions.js +17 -0
  86. package/dist/helpers/assertions.js.map +1 -0
  87. package/dist/helpers/banner.d.ts +3 -0
  88. package/dist/helpers/banner.d.ts.map +1 -0
  89. package/dist/helpers/banner.js +38 -0
  90. package/dist/helpers/banner.js.map +1 -0
  91. package/dist/helpers/index.d.ts +11 -0
  92. package/dist/helpers/index.d.ts.map +1 -0
  93. package/dist/helpers/index.js +7 -0
  94. package/dist/helpers/index.js.map +1 -0
  95. package/dist/helpers/setup.d.ts +10 -0
  96. package/dist/helpers/setup.d.ts.map +1 -0
  97. package/dist/helpers/setup.js +28 -0
  98. package/dist/helpers/setup.js.map +1 -0
  99. package/dist/index.d.ts +11 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +12 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/runtime.d.ts +26 -0
  104. package/dist/runtime.d.ts.map +1 -0
  105. package/dist/runtime.js +247 -0
  106. package/dist/runtime.js.map +1 -0
  107. package/dist/templates/.env.example +9 -0
  108. package/dist/templates/.mocharc.json +8 -0
  109. package/dist/templates/README.md +92 -0
  110. package/dist/templates/move/Counter.move +64 -0
  111. package/dist/templates/move/Move.toml +16 -0
  112. package/dist/templates/movehat.config.ts +37 -0
  113. package/dist/templates/package.json +24 -0
  114. package/dist/templates/scripts/deploy-counter.ts +48 -0
  115. package/dist/templates/tests/Counter.test.ts +75 -0
  116. package/dist/templates/tsconfig.json +15 -0
  117. package/dist/templates/types/movehat.d.ts +104 -0
  118. package/dist/types/config.d.ts +35 -0
  119. package/dist/types/config.d.ts.map +1 -0
  120. package/dist/types/config.js +2 -0
  121. package/dist/types/config.js.map +1 -0
  122. package/dist/types/fork.d.ts +37 -0
  123. package/dist/types/fork.d.ts.map +1 -0
  124. package/dist/types/fork.js +5 -0
  125. package/dist/types/fork.js.map +1 -0
  126. package/dist/types/runtime.d.ts +28 -0
  127. package/dist/types/runtime.d.ts.map +1 -0
  128. package/dist/types/runtime.js +2 -0
  129. package/dist/types/runtime.js.map +1 -0
  130. package/package.json +66 -0
  131. package/src/cli.ts +106 -0
  132. package/src/commands/compile.ts +84 -0
  133. package/src/commands/fork/create.ts +70 -0
  134. package/src/commands/fork/fund.ts +57 -0
  135. package/src/commands/fork/list.ts +67 -0
  136. package/src/commands/fork/serve.ts +77 -0
  137. package/src/commands/fork/view-resource.ts +46 -0
  138. package/src/commands/init.ts +150 -0
  139. package/src/commands/run.ts +59 -0
  140. package/src/commands/test.ts +42 -0
  141. package/src/core/config.ts +151 -0
  142. package/src/core/contract.ts +97 -0
  143. package/src/core/deployments.ts +164 -0
  144. package/src/core/shell.ts +66 -0
  145. package/src/errors.ts +21 -0
  146. package/src/fork/api.ts +117 -0
  147. package/src/fork/manager.ts +264 -0
  148. package/src/fork/server.ts +311 -0
  149. package/src/fork/storage.ts +224 -0
  150. package/src/fork/test.ts +195 -0
  151. package/src/helpers/assertions.ts +29 -0
  152. package/src/helpers/banner.ts +47 -0
  153. package/src/helpers/index.ts +26 -0
  154. package/src/helpers/setup.ts +49 -0
  155. package/src/index.ts +17 -0
  156. package/src/runtime.ts +322 -0
  157. package/src/templates/.env.example +9 -0
  158. package/src/templates/.mocharc.json +8 -0
  159. package/src/templates/README.md +92 -0
  160. package/src/templates/move/Counter.move +64 -0
  161. package/src/templates/move/Move.toml +16 -0
  162. package/src/templates/movehat.config.ts +37 -0
  163. package/src/templates/package.json +24 -0
  164. package/src/templates/scripts/deploy-counter.ts +48 -0
  165. package/src/templates/tests/Counter.test.ts +75 -0
  166. package/src/templates/tsconfig.json +15 -0
  167. package/src/templates/types/movehat.d.ts +104 -0
  168. package/src/types/config.ts +36 -0
  169. package/src/types/fork.ts +41 -0
  170. package/src/types/runtime.ts +49 -0
@@ -0,0 +1,26 @@
1
+ import { MovehatRuntime } from "./types/runtime.js";
2
+ import { MovehatUserConfig } from "./types/config.js";
3
+ export interface InitRuntimeOptions {
4
+ network?: string;
5
+ accountIndex?: number;
6
+ configOverride?: Partial<MovehatUserConfig>;
7
+ }
8
+ /**
9
+ * Initialize the Movehat Runtime Environment
10
+ * This function loads the configuration and creates the runtime context
11
+ */
12
+ export declare function initRuntime(options?: InitRuntimeOptions): Promise<MovehatRuntime>;
13
+ /**
14
+ * Get the current Movehat Runtime Environment
15
+ * Throws error if runtime hasn't been initialized
16
+ */
17
+ export declare function getRuntime(): MovehatRuntime;
18
+ /**
19
+ * Get or initialize the Movehat Runtime Environment
20
+ * This is a convenience function that initializes if needed
21
+ */
22
+ export declare function getMovehat(): Promise<MovehatRuntime>;
23
+ export declare const mh: {
24
+ readonly runtime: MovehatRuntime;
25
+ };
26
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,cAAc,EAAe,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAetD,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,cAAc,CAAC,CA+PzB;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,cAAc,CAO3C;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC,CAK1D;AAGD,eAAO,MAAM,EAAE;;CAId,CAAC"}
@@ -0,0 +1,247 @@
1
+ import { Account, Aptos, AptosConfig, Ed25519PrivateKey, } from "@aptos-labs/ts-sdk";
2
+ import { loadUserConfig, resolveNetworkConfig } from "./core/config.js";
3
+ import { getContract } from "./core/contract.js";
4
+ import { saveDeployment, loadDeployment, getAllDeployments, getDeployedAddress, validateSafeName, } from "./core/deployments.js";
5
+ import { ModuleAlreadyDeployedError } from "./errors.js";
6
+ let cachedRuntime = null;
7
+ /**
8
+ * Initialize the Movehat Runtime Environment
9
+ * This function loads the configuration and creates the runtime context
10
+ */
11
+ export async function initRuntime(options = {}) {
12
+ // Load user config from movehat.config.ts
13
+ const userConfig = await loadUserConfig();
14
+ // Apply config override if provided
15
+ const mergedUserConfig = options.configOverride
16
+ ? { ...userConfig, ...options.configOverride }
17
+ : userConfig;
18
+ // Resolve configuration for selected network
19
+ const config = await resolveNetworkConfig(mergedUserConfig, options.network);
20
+ // Setup Aptos client
21
+ const aptosConfig = new AptosConfig({
22
+ network: config.network,
23
+ fullnode: config.rpc,
24
+ });
25
+ const aptos = new Aptos(aptosConfig);
26
+ // Setup accounts
27
+ const accountIndex = options.accountIndex || 0;
28
+ const accounts = config.allAccounts.map((pk) => {
29
+ const privateKey = new Ed25519PrivateKey(pk);
30
+ return Account.fromPrivateKey({ privateKey });
31
+ });
32
+ // Primary account (accounts[0] or selected index)
33
+ const account = accounts[accountIndex];
34
+ if (!account) {
35
+ throw new Error(`Account index ${accountIndex} not found. Only ${accounts.length} accounts configured.`);
36
+ }
37
+ // Update config.account with derived address
38
+ config.account = account.accountAddress.toString();
39
+ // Network info
40
+ const network = {
41
+ name: config.network,
42
+ rpc: config.rpc,
43
+ };
44
+ // Helper functions
45
+ const getContractHelper = (address, moduleName) => {
46
+ return getContract(aptos, address, moduleName);
47
+ };
48
+ const deployContract = async (moduleName, options) => {
49
+ // Validate moduleName early
50
+ validateSafeName(moduleName, "module");
51
+ const { exec } = await import("child_process");
52
+ const { promisify } = await import("util");
53
+ const { existsSync, mkdirSync, writeFileSync, chmodSync } = await import("fs");
54
+ const { join } = await import("path");
55
+ const { homedir } = await import("os");
56
+ const yaml = await import("js-yaml");
57
+ const { validateAndEscapePath, validateAndEscapeProfile } = await import("./core/shell.js");
58
+ const execAsync = promisify(exec);
59
+ // Check if --redeploy flag was passed via CLI
60
+ const forceRedeploy = process.env.MH_CLI_REDEPLOY === 'true';
61
+ // Check if already deployed
62
+ const existingDeployment = loadDeployment(config.network, moduleName);
63
+ if (existingDeployment && !forceRedeploy) {
64
+ // Build detailed error message with all deployment info
65
+ const errorDetails = [
66
+ `Module "${moduleName}" is already deployed on ${config.network}`,
67
+ `Address: ${existingDeployment.address}`,
68
+ `Deployed at: ${new Date(existingDeployment.timestamp).toLocaleString()}`,
69
+ existingDeployment.txHash ? `Transaction: ${existingDeployment.txHash}` : null,
70
+ `\nTo redeploy, run with the --redeploy flag:`,
71
+ `movehat run <script> --network ${config.network} --redeploy`,
72
+ ].filter(Boolean).join('\n');
73
+ // Log formatted error message for user
74
+ const formattedMessage = [
75
+ `\nāŒ Module "${moduleName}" is already deployed on ${config.network}`,
76
+ ` Address: ${existingDeployment.address}`,
77
+ ` Deployed at: ${new Date(existingDeployment.timestamp).toLocaleString()}`,
78
+ existingDeployment.txHash ? ` Transaction: ${existingDeployment.txHash}` : null,
79
+ `\nšŸ’” To redeploy, run with the --redeploy flag:`,
80
+ ` movehat run <script> --network ${config.network} --redeploy\n`,
81
+ ].filter(Boolean).join('\n');
82
+ console.error(formattedMessage);
83
+ // Throw custom error with complete context for programmatic handling
84
+ throw new ModuleAlreadyDeployedError(errorDetails, moduleName, config.network, existingDeployment.address, existingDeployment.timestamp, existingDeployment.txHash);
85
+ }
86
+ if (forceRedeploy && existingDeployment) {
87
+ console.log(`šŸ”„ Redeploying module "${moduleName}" on ${config.network}...`);
88
+ }
89
+ const dir = options?.packageDir || config.moveDir;
90
+ const profile = config.profile || "default";
91
+ // Validate and escape to prevent command injection
92
+ const safeDir = validateAndEscapePath(dir, "package directory");
93
+ const safeProfile = validateAndEscapeProfile(profile);
94
+ console.log(`šŸ“¦ Publishing module "${moduleName}" from ${dir}...`);
95
+ try {
96
+ // Ensure Movement CLI config exists
97
+ const aptosConfigDir = join(homedir(), ".aptos");
98
+ const aptosConfigPath = join(aptosConfigDir, "config.yaml");
99
+ if (!existsSync(aptosConfigPath)) {
100
+ console.log("āš™ļø Creating Movement CLI configuration...");
101
+ if (!existsSync(aptosConfigDir)) {
102
+ mkdirSync(aptosConfigDir, { recursive: true });
103
+ }
104
+ // Create minimal config.yaml using js-yaml to prevent YAML injection
105
+ const configData = {
106
+ profiles: {
107
+ [profile]: {
108
+ private_key: config.privateKey,
109
+ public_key: account.publicKey.toString(),
110
+ account: account.accountAddress.toString(),
111
+ rest_url: config.rpc,
112
+ },
113
+ },
114
+ };
115
+ const configContent = yaml.dump(configData);
116
+ writeFileSync(aptosConfigPath, configContent, "utf-8");
117
+ // Restrict file permissions to owner only (600) for security
118
+ // This prevents other users from reading the private key
119
+ try {
120
+ chmodSync(aptosConfigPath, 0o600);
121
+ }
122
+ catch (error) {
123
+ // chmod may fail on Windows, but that's okay
124
+ // Windows has different permission model (ACLs)
125
+ console.warn("āš ļø Could not set file permissions (this is normal on Windows)");
126
+ }
127
+ }
128
+ // Build first
129
+ console.log("šŸ”Ø Building package...");
130
+ const buildCmd = `movement move build --package-dir ${safeDir}`;
131
+ const { stdout: buildOut } = await execAsync(buildCmd);
132
+ if (buildOut)
133
+ console.log(buildOut.trim());
134
+ // Publish
135
+ console.log("šŸ“¤ Publishing to blockchain...");
136
+ const publishCmd = `movement move publish --profile ${safeProfile} --package-dir ${safeDir} --assume-yes`;
137
+ const { stdout: publishOut } = await execAsync(publishCmd);
138
+ if (publishOut)
139
+ console.log(publishOut.trim());
140
+ // Extract transaction hash from output
141
+ // Look for patterns like "Transaction hash: 0x..." or "Txn: 0x..." or just a 64-char hex
142
+ // The regex tries to match with context first, then falls back to any 64-char hex
143
+ let txHash;
144
+ const txHashMatchWithContext = publishOut.match(/(?:transaction\s*(?:hash)?|txn\s*(?:hash)?|hash):\s*(0x[a-fA-F0-9]{64})\b/i);
145
+ if (txHashMatchWithContext) {
146
+ txHash = txHashMatchWithContext[1];
147
+ }
148
+ else {
149
+ // Fallback: try to find any 64-char hex string (exactly, not more)
150
+ const txHashMatch = publishOut.match(/\b(0x[a-fA-F0-9]{64})\b/);
151
+ if (txHashMatch) {
152
+ txHash = txHashMatch[1];
153
+ }
154
+ }
155
+ console.log(`āœ… Module published successfully!`);
156
+ // Create deployment info
157
+ const deployment = {
158
+ address: account.accountAddress.toString(),
159
+ moduleName,
160
+ network: config.network,
161
+ deployer: account.accountAddress.toString(),
162
+ timestamp: Date.now(),
163
+ txHash,
164
+ };
165
+ // Save deployment
166
+ saveDeployment(deployment);
167
+ return deployment;
168
+ }
169
+ catch (error) {
170
+ console.error(`āŒ Failed to publish module: ${error.message}`);
171
+ throw error;
172
+ }
173
+ };
174
+ const getDeployment = (moduleName) => {
175
+ return loadDeployment(config.network, moduleName);
176
+ };
177
+ const getDeployments = () => {
178
+ return getAllDeployments(config.network);
179
+ };
180
+ const getDeploymentAddress = (moduleName) => {
181
+ return getDeployedAddress(config.network, moduleName);
182
+ };
183
+ const createAccount = () => {
184
+ return Account.generate();
185
+ };
186
+ const getAccountHelper = (privateKeyHex) => {
187
+ const pk = new Ed25519PrivateKey(privateKeyHex);
188
+ return Account.fromPrivateKey({ privateKey: pk });
189
+ };
190
+ const getAccountByIndex = (index) => {
191
+ if (index < 0 || index >= accounts.length) {
192
+ throw new Error(`Account index ${index} out of range. Available accounts: 0-${accounts.length - 1}`);
193
+ }
194
+ return accounts[index];
195
+ };
196
+ const switchNetwork = async (networkName) => {
197
+ // Clear cache and reinitialize with new network
198
+ cachedRuntime = null;
199
+ await initRuntime({ ...options, network: networkName });
200
+ };
201
+ // Build runtime object
202
+ const runtime = {
203
+ config,
204
+ network,
205
+ aptos,
206
+ account,
207
+ accounts,
208
+ getContract: getContractHelper,
209
+ deployContract,
210
+ getDeployment,
211
+ getDeployments,
212
+ getDeploymentAddress,
213
+ createAccount,
214
+ getAccount: getAccountHelper,
215
+ getAccountByIndex,
216
+ switchNetwork,
217
+ };
218
+ cachedRuntime = runtime;
219
+ return runtime;
220
+ }
221
+ /**
222
+ * Get the current Movehat Runtime Environment
223
+ * Throws error if runtime hasn't been initialized
224
+ */
225
+ export function getRuntime() {
226
+ if (!cachedRuntime) {
227
+ throw new Error("Movehat Runtime not initialized. Call initRuntime() first or use getMovehat().");
228
+ }
229
+ return cachedRuntime;
230
+ }
231
+ /**
232
+ * Get or initialize the Movehat Runtime Environment
233
+ * This is a convenience function that initializes if needed
234
+ */
235
+ export async function getMovehat() {
236
+ if (cachedRuntime) {
237
+ return cachedRuntime;
238
+ }
239
+ return initRuntime();
240
+ }
241
+ // Export a default instance getter for convenience
242
+ export const mh = {
243
+ get runtime() {
244
+ return getRuntime();
245
+ },
246
+ };
247
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ # Private Key (used for all networks - Hardhat-style)
2
+ # This is your wallet's private key that will be used to deploy and interact with contracts
3
+ PRIVATE_KEY=your_private_key_here
4
+
5
+ # Optional: Override RPC URL (useful for custom endpoints)
6
+ # MOVEMENT_RPC_URL=https://custom-testnet.movementnetwork.xyz/v1
7
+
8
+ # Optional: Override default network from config
9
+ # MH_DEFAULT_NETWORK=testnet
@@ -0,0 +1,8 @@
1
+ {
2
+ "node-option": ["import=tsx"],
3
+ "extensions": ["ts"],
4
+ "spec": ["tests/**/*.test.ts"],
5
+ "timeout": 30000,
6
+ "color": true,
7
+ "reporter": "spec"
8
+ }
@@ -0,0 +1,92 @@
1
+ # {{PROJECT_NAME}}
2
+
3
+ A Move smart contract project built with Movehat.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js v18+
8
+ - [Movement CLI](https://docs.movementnetwork.xyz/devs/movementCLI)
9
+
10
+ ## Getting Started
11
+
12
+ ### 1. Install dependencies
13
+
14
+ ```bash
15
+ npm install
16
+ ```
17
+
18
+ ### 2. Configure environment
19
+
20
+ Copy `.env.example` to `.env` and fill in your credentials:
21
+
22
+ ```bash
23
+ cp .env.example .env
24
+ ```
25
+
26
+ Edit `.env`:
27
+ ```
28
+ MH_PRIVATE_KEY=your_private_key_here
29
+ MH_ACCOUNT=your_account_address_here
30
+ MH_NETWORK=testnet
31
+ ```
32
+
33
+ ### 3. Update Move.toml
34
+
35
+ Edit `move/Move.toml` and set the `counter` address to your account address:
36
+
37
+ ```toml
38
+ [addresses]
39
+ counter = "0xYOUR_ACCOUNT_ADDRESS"
40
+ ```
41
+
42
+ ### 4. Compile contracts
43
+
44
+ ```bash
45
+ npm run compile
46
+ ```
47
+
48
+ ### 5. Deploy
49
+
50
+ ```bash
51
+ npx tsx scripts/deploy-counter.ts
52
+ ```
53
+
54
+ Or use the Movement CLI directly:
55
+ ```bash
56
+ movement move publish --package-dir ./move --profile default --assume-yes
57
+ ```
58
+
59
+ ### 6. Run tests
60
+
61
+ ```bash
62
+ npm test
63
+ ```
64
+
65
+ ## Project Structure
66
+
67
+ ```
68
+ {{PROJECT_NAME}}/
69
+ ā”œā”€ā”€ move/ # Move smart contracts
70
+ │ ā”œā”€ā”€ sources/
71
+ │ │ └── Counter.move
72
+ │ └── Move.toml
73
+ ā”œā”€ā”€ scripts/ # Deployment scripts
74
+ │ └── deploy-counter.ts
75
+ ā”œā”€ā”€ tests/ # Integration tests
76
+ │ └── Counter.test.ts
77
+ ā”œā”€ā”€ movehat.config.ts # Movehat configuration
78
+ └── .env # Environment variables (git-ignored)
79
+ ```
80
+
81
+ ## Available Commands
82
+
83
+ - `npm run compile` - Compile Move contracts
84
+ - `npm test` - Run integration tests
85
+ - `npm run test:watch` - Run tests in watch mode
86
+ - `npx tsx scripts/deploy-counter.ts` - Deploy and initialize counter
87
+
88
+ ## Learn More
89
+
90
+ - [Movement Documentation](https://docs.movementnetwork.xyz)
91
+ - [Aptos Move Book](https://move-language.github.io/move/)
92
+ - [Movehat GitHub](https://github.com/gilbertsahumada/movehat)
@@ -0,0 +1,64 @@
1
+ module counter::counter {
2
+ use std::signer;
3
+ use aptos_framework::event;
4
+ use aptos_framework::account;
5
+
6
+ struct Counter has key {
7
+ value: u64,
8
+ increment_events: event::EventHandle<IncrementEvent>,
9
+ }
10
+
11
+ struct IncrementEvent has drop, store {
12
+ old_value: u64,
13
+ new_value: u64,
14
+ }
15
+
16
+ /// Initialize counter for an account
17
+ public entry fun init(account: &signer) {
18
+ let account_addr = signer::address_of(account);
19
+
20
+ if (!exists<Counter>(account_addr)) {
21
+ move_to(account, Counter {
22
+ value: 0,
23
+ increment_events: account::new_event_handle<IncrementEvent>(account),
24
+ });
25
+ }
26
+ }
27
+
28
+ /// Increment the counter
29
+ public entry fun increment(account: &signer) acquires Counter {
30
+ let account_addr = signer::address_of(account);
31
+ assert!(exists<Counter>(account_addr), 1);
32
+
33
+ let counter = borrow_global_mut<Counter>(account_addr);
34
+ let old_value = counter.value;
35
+ counter.value = old_value + 1;
36
+
37
+ event::emit_event(&mut counter.increment_events, IncrementEvent {
38
+ old_value,
39
+ new_value: counter.value,
40
+ });
41
+ }
42
+
43
+ /// Get counter value
44
+ #[view]
45
+ public fun get(addr: address): u64 acquires Counter {
46
+ assert!(exists<Counter>(addr), 1);
47
+ borrow_global<Counter>(addr).value
48
+ }
49
+
50
+ #[test(account = @0x1)]
51
+ public fun test_increment(account: &signer) acquires Counter {
52
+ let addr = signer::address_of(account);
53
+ aptos_framework::account::create_account_for_test(addr);
54
+
55
+ init(account);
56
+ assert!(get(addr) == 0, 0);
57
+
58
+ increment(account);
59
+ assert!(get(addr) == 1, 1);
60
+
61
+ increment(account);
62
+ assert!(get(addr) == 2, 2);
63
+ }
64
+ }
@@ -0,0 +1,16 @@
1
+ [package]
2
+ name = "{{PROJECT_NAME}}"
3
+ version = "1.0.0"
4
+ authors = []
5
+
6
+ [addresses]
7
+ counter = "_"
8
+
9
+ [dev-addresses]
10
+
11
+ [dependencies.AptosFramework]
12
+ git = "https://github.com/movementlabsxyz/aptos-core.git"
13
+ rev = "movement"
14
+ subdir = "aptos-move/framework/aptos-framework"
15
+
16
+ [dev-dependencies]
@@ -0,0 +1,37 @@
1
+ import dotenv from "dotenv";
2
+ dotenv.config();
3
+
4
+ export default {
5
+ // Default network to use when no --network flag is provided
6
+ defaultNetwork: "testnet",
7
+
8
+ // Network configurations
9
+ networks: {
10
+ testnet: {
11
+ url: process.env.MOVEMENT_RPC_URL || "https://testnet.movementnetwork.xyz/v1",
12
+ chainId: "testnet",
13
+ },
14
+ mainnet: {
15
+ url: "https://mainnet.movementnetwork.xyz/v1",
16
+ chainId: "mainnet",
17
+ },
18
+ local: {
19
+ url: "http://localhost:8080/v1",
20
+ chainId: "local",
21
+ },
22
+ },
23
+
24
+ // Global accounts configuration (Hardhat-style)
25
+ // Uses PRIVATE_KEY from .env by default
26
+ // You can also specify accounts here directly:
27
+ // accounts: ["0x1234..."],
28
+ accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [],
29
+
30
+ // Global settings
31
+ moveDir: "./move",
32
+
33
+ // Named addresses (can be overridden per-network in network config)
34
+ namedAddresses: {
35
+ // Example: counter: "0x1234...",
36
+ },
37
+ };
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "{{projectName}}",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "scripts": {
6
+ "test": "mocha",
7
+ "test:watch": "mocha --watch",
8
+ "deploy": "movehat run scripts/deploy-counter.ts"
9
+ },
10
+ "dependencies": {
11
+ "movehat": "^0.0.1-alpha.0",
12
+ "@aptos-labs/ts-sdk": "^5.1.5",
13
+ "dotenv": "^17.2.3"
14
+ },
15
+ "devDependencies": {
16
+ "@types/chai": "^5.2.3",
17
+ "@types/mocha": "^10.0.10",
18
+ "@types/node": "^24.10.1",
19
+ "chai": "^6.2.1",
20
+ "mocha": "^11.7.5",
21
+ "tsx": "^4.7.0",
22
+ "typescript": "^5.9.3"
23
+ }
24
+ }
@@ -0,0 +1,48 @@
1
+ import { getMovehat, ModuleAlreadyDeployedError } from "movehat";
2
+
3
+ async function main() {
4
+ console.log("šŸš€ Deploying Counter contract...\n");
5
+
6
+ // Get the Movehat Runtime Environment
7
+ const mh = await getMovehat();
8
+
9
+ console.log(`āœ… Runtime initialized`);
10
+ console.log(` Account: ${mh.account.accountAddress.toString()}`);
11
+ console.log(` Network: ${mh.network.name}`);
12
+ console.log(` RPC: ${mh.network.rpc}\n`);
13
+
14
+ // Deploy (publish) the module
15
+ // Automatically checks if already deployed and suggests --redeploy if needed
16
+ const deployment = await mh.deployContract("counter");
17
+
18
+ console.log(`\nāœ… Module deployed at: ${deployment.address}::counter`);
19
+ if (deployment.txHash) {
20
+ console.log(` Transaction: ${deployment.txHash}`);
21
+ }
22
+
23
+ // Get contract instance
24
+ const counter = mh.getContract(deployment.address, "counter");
25
+
26
+ // Initialize the counter
27
+ console.log("\nšŸ“ Initializing counter...");
28
+ const txResult = await counter.call(mh.account, "init", []);
29
+
30
+ console.log(`āœ… Transaction hash: ${txResult.hash}`);
31
+ console.log(`āœ… Counter initialized successfully!`);
32
+
33
+ // Verify
34
+ const value = await counter.view<number>("get", [
35
+ mh.account.accountAddress.toString()
36
+ ]);
37
+
38
+ console.log(`\nšŸ“Š Initial counter value: ${value}`);
39
+ }
40
+
41
+ main().catch((error) => {
42
+ // ModuleAlreadyDeployedError is already logged with full details by deployContract()
43
+ // For other errors, show the message
44
+ if (!(error instanceof ModuleAlreadyDeployedError)) {
45
+ console.error("āŒ Deployment failed:", error?.message || error);
46
+ }
47
+ process.exit(1);
48
+ });
@@ -0,0 +1,75 @@
1
+ import { describe, it, before, after } from "mocha";
2
+ import { expect } from "chai";
3
+ import { getMovehat, type MovehatRuntime } from "movehat";
4
+ import type { MoveContract } from "movehat/helpers";
5
+ import { assertTransactionSuccess, snapshot } from "movehat/helpers";
6
+
7
+ describe("Counter Contract", () => {
8
+ let mh: MovehatRuntime;
9
+ let counter: MoveContract;
10
+
11
+ before(async function () {
12
+ this.timeout(30000);
13
+
14
+ // Initialize Movehat Runtime Environment
15
+ mh = await getMovehat();
16
+
17
+ console.log(`\nāœ… Testing on ${mh.network.name}`);
18
+ console.log(` Account: ${mh.account.accountAddress.toString()}\n`);
19
+
20
+ // Get counter contract instance
21
+ counter = mh.getContract(
22
+ mh.account.accountAddress.toString(),
23
+ "counter"
24
+ );
25
+ });
26
+
27
+ describe("Counter functionality", () => {
28
+ it("should initialize counter", async function () {
29
+ this.timeout(30000);
30
+
31
+ const txResult = await counter.call(mh.account, "init", []);
32
+ assertTransactionSuccess(txResult);
33
+
34
+ const value = await counter.view<number>("get", [
35
+ mh.account.accountAddress.toString()
36
+ ]);
37
+
38
+ expect(value).to.equal(0);
39
+ console.log(` āœ“ Counter initialized with value: ${value}`);
40
+ });
41
+
42
+ it("should increment counter", async function () {
43
+ this.timeout(30000);
44
+
45
+ const initialValue = await counter.view<number>("get", [
46
+ mh.account.accountAddress.toString()
47
+ ]);
48
+
49
+ const txResult = await counter.call(mh.account, "increment", []);
50
+ assertTransactionSuccess(txResult);
51
+
52
+ const newValue = await counter.view<number>("get", [
53
+ mh.account.accountAddress.toString()
54
+ ]);
55
+
56
+ expect(newValue).to.equal(initialValue + 1);
57
+ console.log(` āœ“ Counter incremented: ${initialValue} → ${newValue}`);
58
+ });
59
+ });
60
+
61
+ // Optional: Create a snapshot after tests for debugging
62
+ // Uncomment to enable
63
+ /*
64
+ after(async function () {
65
+ this.timeout(30000);
66
+
67
+ const snapshotPath = await snapshot({
68
+ name: 'counter-test-final'
69
+ });
70
+
71
+ console.log(`\nšŸ“ø Snapshot created: ${snapshotPath}`);
72
+ console.log(` Use 'aptos move sim view-resource --session ${snapshotPath}' to inspect state\n`);
73
+ });
74
+ */
75
+ });