movehat 0.1.8 → 0.2.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 (445) hide show
  1. package/README.md +2 -2
  2. package/dist/__tests__/deployContract.test.d.ts +2 -0
  3. package/dist/__tests__/deployContract.test.d.ts.map +1 -0
  4. package/dist/__tests__/deployContract.test.js +368 -0
  5. package/dist/__tests__/deployContract.test.js.map +1 -0
  6. package/dist/__tests__/errors.test.d.ts +2 -0
  7. package/dist/__tests__/errors.test.d.ts.map +1 -0
  8. package/dist/__tests__/errors.test.js +46 -0
  9. package/dist/__tests__/errors.test.js.map +1 -0
  10. package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts +24 -0
  11. package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts.map +1 -0
  12. package/dist/__tests__/fixtures/sigint-deploy-harness.js +82 -0
  13. package/dist/__tests__/fixtures/sigint-deploy-harness.js.map +1 -0
  14. package/dist/__tests__/fork/api.test.d.ts +2 -0
  15. package/dist/__tests__/fork/api.test.d.ts.map +1 -0
  16. package/dist/__tests__/fork/api.test.js +110 -0
  17. package/dist/__tests__/fork/api.test.js.map +1 -0
  18. package/dist/__tests__/harness/Harness.createLive.test.d.ts +2 -0
  19. package/dist/__tests__/harness/Harness.createLive.test.d.ts.map +1 -0
  20. package/dist/__tests__/harness/Harness.createLive.test.js +53 -0
  21. package/dist/__tests__/harness/Harness.createLive.test.js.map +1 -0
  22. package/dist/__tests__/harness/Harness.proxy.test.d.ts +2 -0
  23. package/dist/__tests__/harness/Harness.proxy.test.d.ts.map +1 -0
  24. package/dist/__tests__/harness/Harness.proxy.test.js +93 -0
  25. package/dist/__tests__/harness/Harness.proxy.test.js.map +1 -0
  26. package/dist/__tests__/harness/_fixture.d.ts +54 -0
  27. package/dist/__tests__/harness/_fixture.d.ts.map +1 -0
  28. package/dist/__tests__/harness/_fixture.js +69 -0
  29. package/dist/__tests__/harness/_fixture.js.map +1 -0
  30. package/dist/__tests__/harness/codeObject.deploy.test.d.ts +2 -0
  31. package/dist/__tests__/harness/codeObject.deploy.test.d.ts.map +1 -0
  32. package/dist/__tests__/harness/codeObject.deploy.test.js +288 -0
  33. package/dist/__tests__/harness/codeObject.deploy.test.js.map +1 -0
  34. package/dist/__tests__/harness/codeObject.upgrade.test.d.ts +2 -0
  35. package/dist/__tests__/harness/codeObject.upgrade.test.d.ts.map +1 -0
  36. package/dist/__tests__/harness/codeObject.upgrade.test.js +138 -0
  37. package/dist/__tests__/harness/codeObject.upgrade.test.js.map +1 -0
  38. package/dist/__tests__/harness/script.test.d.ts +2 -0
  39. package/dist/__tests__/harness/script.test.d.ts.map +1 -0
  40. package/dist/__tests__/harness/script.test.js +219 -0
  41. package/dist/__tests__/harness/script.test.js.map +1 -0
  42. package/dist/__tests__/harness/view.test.d.ts +2 -0
  43. package/dist/__tests__/harness/view.test.d.ts.map +1 -0
  44. package/dist/__tests__/harness/view.test.js +92 -0
  45. package/dist/__tests__/harness/view.test.js.map +1 -0
  46. package/dist/__tests__/runtime.test.d.ts +2 -0
  47. package/dist/__tests__/runtime.test.d.ts.map +1 -0
  48. package/dist/__tests__/runtime.test.js +141 -0
  49. package/dist/__tests__/runtime.test.js.map +1 -0
  50. package/dist/cli.js +2 -1
  51. package/dist/cli.js.map +1 -1
  52. package/dist/commands/__tests__/compile.test.d.ts +2 -0
  53. package/dist/commands/__tests__/compile.test.d.ts.map +1 -0
  54. package/dist/commands/__tests__/compile.test.js +351 -0
  55. package/dist/commands/__tests__/compile.test.js.map +1 -0
  56. package/dist/commands/__tests__/init.test.d.ts +2 -0
  57. package/dist/commands/__tests__/init.test.d.ts.map +1 -0
  58. package/dist/commands/__tests__/init.test.js +101 -0
  59. package/dist/commands/__tests__/init.test.js.map +1 -0
  60. package/dist/commands/__tests__/run.test.d.ts +2 -0
  61. package/dist/commands/__tests__/run.test.d.ts.map +1 -0
  62. package/dist/commands/__tests__/run.test.js +166 -0
  63. package/dist/commands/__tests__/run.test.js.map +1 -0
  64. package/dist/commands/__tests__/test-move.test.d.ts +2 -0
  65. package/dist/commands/__tests__/test-move.test.d.ts.map +1 -0
  66. package/dist/commands/__tests__/test-move.test.js +59 -0
  67. package/dist/commands/__tests__/test-move.test.js.map +1 -0
  68. package/dist/commands/__tests__/test.test.d.ts +2 -0
  69. package/dist/commands/__tests__/test.test.d.ts.map +1 -0
  70. package/dist/commands/__tests__/test.test.js +168 -0
  71. package/dist/commands/__tests__/test.test.js.map +1 -0
  72. package/dist/commands/__tests__/update.test.d.ts +2 -0
  73. package/dist/commands/__tests__/update.test.d.ts.map +1 -0
  74. package/dist/commands/__tests__/update.test.js +176 -0
  75. package/dist/commands/__tests__/update.test.js.map +1 -0
  76. package/dist/commands/compile.d.ts +7 -1
  77. package/dist/commands/compile.d.ts.map +1 -1
  78. package/dist/commands/compile.js +150 -33
  79. package/dist/commands/compile.js.map +1 -1
  80. package/dist/commands/fork/__tests__/create.test.d.ts +2 -0
  81. package/dist/commands/fork/__tests__/create.test.d.ts.map +1 -0
  82. package/dist/commands/fork/__tests__/create.test.js +108 -0
  83. package/dist/commands/fork/__tests__/create.test.js.map +1 -0
  84. package/dist/commands/fork/__tests__/fund.test.d.ts +2 -0
  85. package/dist/commands/fork/__tests__/fund.test.d.ts.map +1 -0
  86. package/dist/commands/fork/__tests__/fund.test.js +72 -0
  87. package/dist/commands/fork/__tests__/fund.test.js.map +1 -0
  88. package/dist/commands/fork/__tests__/list.test.d.ts +2 -0
  89. package/dist/commands/fork/__tests__/list.test.d.ts.map +1 -0
  90. package/dist/commands/fork/__tests__/list.test.js +119 -0
  91. package/dist/commands/fork/__tests__/list.test.js.map +1 -0
  92. package/dist/commands/fork/__tests__/serve.test.d.ts +2 -0
  93. package/dist/commands/fork/__tests__/serve.test.d.ts.map +1 -0
  94. package/dist/commands/fork/__tests__/serve.test.js +97 -0
  95. package/dist/commands/fork/__tests__/serve.test.js.map +1 -0
  96. package/dist/commands/fork/__tests__/view-resource.test.d.ts +2 -0
  97. package/dist/commands/fork/__tests__/view-resource.test.d.ts.map +1 -0
  98. package/dist/commands/fork/__tests__/view-resource.test.js +77 -0
  99. package/dist/commands/fork/__tests__/view-resource.test.js.map +1 -0
  100. package/dist/commands/fork/create.d.ts +1 -1
  101. package/dist/commands/fork/create.d.ts.map +1 -1
  102. package/dist/commands/fork/create.js +3 -2
  103. package/dist/commands/fork/create.js.map +1 -1
  104. package/dist/commands/fork/fund.d.ts.map +1 -1
  105. package/dist/commands/fork/fund.js +15 -8
  106. package/dist/commands/fork/fund.js.map +1 -1
  107. package/dist/commands/fork/list.d.ts.map +1 -1
  108. package/dist/commands/fork/list.js +2 -1
  109. package/dist/commands/fork/list.js.map +1 -1
  110. package/dist/commands/fork/serve.d.ts +1 -0
  111. package/dist/commands/fork/serve.d.ts.map +1 -1
  112. package/dist/commands/fork/serve.js +4 -2
  113. package/dist/commands/fork/serve.js.map +1 -1
  114. package/dist/commands/fork/view-resource.d.ts.map +1 -1
  115. package/dist/commands/fork/view-resource.js +10 -5
  116. package/dist/commands/fork/view-resource.js.map +1 -1
  117. package/dist/commands/run.d.ts +15 -0
  118. package/dist/commands/run.d.ts.map +1 -1
  119. package/dist/commands/run.js +50 -27
  120. package/dist/commands/run.js.map +1 -1
  121. package/dist/commands/test-move.d.ts.map +1 -1
  122. package/dist/commands/test-move.js +3 -2
  123. package/dist/commands/test-move.js.map +1 -1
  124. package/dist/commands/test.js +52 -46
  125. package/dist/commands/test.js.map +1 -1
  126. package/dist/commands/update.d.ts.map +1 -1
  127. package/dist/commands/update.js +15 -13
  128. package/dist/commands/update.js.map +1 -1
  129. package/dist/core/AccountManager.d.ts +1 -1
  130. package/dist/core/AccountManager.d.ts.map +1 -1
  131. package/dist/core/AccountManager.js +20 -7
  132. package/dist/core/AccountManager.js.map +1 -1
  133. package/dist/core/Publisher.d.ts +31 -0
  134. package/dist/core/Publisher.d.ts.map +1 -0
  135. package/dist/core/Publisher.js +248 -0
  136. package/dist/core/Publisher.js.map +1 -0
  137. package/dist/core/__tests__/AccountManager.test.d.ts +2 -0
  138. package/dist/core/__tests__/AccountManager.test.d.ts.map +1 -0
  139. package/dist/core/__tests__/AccountManager.test.js +239 -0
  140. package/dist/core/__tests__/AccountManager.test.js.map +1 -0
  141. package/dist/core/__tests__/config.test.d.ts +2 -0
  142. package/dist/core/__tests__/config.test.d.ts.map +1 -0
  143. package/dist/core/__tests__/config.test.js +311 -0
  144. package/dist/core/__tests__/config.test.js.map +1 -0
  145. package/dist/core/__tests__/deployments.test.d.ts +2 -0
  146. package/dist/core/__tests__/deployments.test.d.ts.map +1 -0
  147. package/dist/core/__tests__/deployments.test.js +201 -0
  148. package/dist/core/__tests__/deployments.test.js.map +1 -0
  149. package/dist/core/__tests__/shell.test.d.ts +2 -0
  150. package/dist/core/__tests__/shell.test.d.ts.map +1 -0
  151. package/dist/core/__tests__/shell.test.js +107 -0
  152. package/dist/core/__tests__/shell.test.js.map +1 -0
  153. package/dist/core/config.d.ts +13 -1
  154. package/dist/core/config.d.ts.map +1 -1
  155. package/dist/core/config.js +80 -11
  156. package/dist/core/config.js.map +1 -1
  157. package/dist/core/contract.d.ts +1 -1
  158. package/dist/core/contract.d.ts.map +1 -1
  159. package/dist/core/contract.js +15 -4
  160. package/dist/core/contract.js.map +1 -1
  161. package/dist/core/deployments.d.ts +2 -2
  162. package/dist/core/deployments.d.ts.map +1 -1
  163. package/dist/core/deployments.js +8 -6
  164. package/dist/core/deployments.js.map +1 -1
  165. package/dist/core/movementProfile.d.ts +34 -0
  166. package/dist/core/movementProfile.d.ts.map +1 -0
  167. package/dist/core/movementProfile.js +150 -0
  168. package/dist/core/movementProfile.js.map +1 -0
  169. package/dist/core/shell.d.ts +23 -7
  170. package/dist/core/shell.d.ts.map +1 -1
  171. package/dist/core/shell.js +32 -14
  172. package/dist/core/shell.js.map +1 -1
  173. package/dist/errors.d.ts +35 -0
  174. package/dist/errors.d.ts.map +1 -1
  175. package/dist/errors.js +54 -0
  176. package/dist/errors.js.map +1 -1
  177. package/dist/fork/__tests__/manager.test.d.ts +2 -0
  178. package/dist/fork/__tests__/manager.test.d.ts.map +1 -0
  179. package/dist/fork/__tests__/manager.test.js +309 -0
  180. package/dist/fork/__tests__/manager.test.js.map +1 -0
  181. package/dist/fork/__tests__/server.test.d.ts +2 -0
  182. package/dist/fork/__tests__/server.test.d.ts.map +1 -0
  183. package/dist/fork/__tests__/server.test.js +54 -0
  184. package/dist/fork/__tests__/server.test.js.map +1 -0
  185. package/dist/fork/__tests__/storage.test.d.ts +2 -0
  186. package/dist/fork/__tests__/storage.test.d.ts.map +1 -0
  187. package/dist/fork/__tests__/storage.test.js +222 -0
  188. package/dist/fork/__tests__/storage.test.js.map +1 -0
  189. package/dist/fork/__tests__/test.test.d.ts +2 -0
  190. package/dist/fork/__tests__/test.test.d.ts.map +1 -0
  191. package/dist/fork/__tests__/test.test.js +81 -0
  192. package/dist/fork/__tests__/test.test.js.map +1 -0
  193. package/dist/fork/api.d.ts +14 -3
  194. package/dist/fork/api.d.ts.map +1 -1
  195. package/dist/fork/api.js +25 -14
  196. package/dist/fork/api.js.map +1 -1
  197. package/dist/fork/manager.d.ts +23 -9
  198. package/dist/fork/manager.d.ts.map +1 -1
  199. package/dist/fork/manager.js +79 -36
  200. package/dist/fork/manager.js.map +1 -1
  201. package/dist/fork/server.d.ts +11 -3
  202. package/dist/fork/server.d.ts.map +1 -1
  203. package/dist/fork/server.js +45 -13
  204. package/dist/fork/server.js.map +1 -1
  205. package/dist/fork/storage.d.ts +4 -4
  206. package/dist/fork/storage.d.ts.map +1 -1
  207. package/dist/fork/storage.js +7 -9
  208. package/dist/fork/storage.js.map +1 -1
  209. package/dist/fork/test.d.ts +13 -4
  210. package/dist/fork/test.d.ts.map +1 -1
  211. package/dist/fork/test.js +36 -27
  212. package/dist/fork/test.js.map +1 -1
  213. package/dist/harness/Harness.d.ts +124 -0
  214. package/dist/harness/Harness.d.ts.map +1 -0
  215. package/dist/harness/Harness.js +193 -0
  216. package/dist/harness/Harness.js.map +1 -0
  217. package/dist/harness/codeObject.d.ts +31 -0
  218. package/dist/harness/codeObject.d.ts.map +1 -0
  219. package/dist/harness/codeObject.js +271 -0
  220. package/dist/harness/codeObject.js.map +1 -0
  221. package/dist/harness/errors.d.ts +14 -0
  222. package/dist/harness/errors.d.ts.map +1 -0
  223. package/dist/harness/errors.js +22 -0
  224. package/dist/harness/errors.js.map +1 -0
  225. package/dist/harness/index.d.ts +4 -0
  226. package/dist/harness/index.d.ts.map +1 -0
  227. package/dist/harness/index.js +3 -0
  228. package/dist/harness/index.js.map +1 -0
  229. package/dist/harness/proxy.d.ts +7 -0
  230. package/dist/harness/proxy.d.ts.map +1 -0
  231. package/dist/harness/proxy.js +36 -0
  232. package/dist/harness/proxy.js.map +1 -0
  233. package/dist/harness/script.d.ts +21 -0
  234. package/dist/harness/script.d.ts.map +1 -0
  235. package/dist/harness/script.js +155 -0
  236. package/dist/harness/script.js.map +1 -0
  237. package/dist/harness/view.d.ts +22 -0
  238. package/dist/harness/view.d.ts.map +1 -0
  239. package/dist/harness/view.js +28 -0
  240. package/dist/harness/view.js.map +1 -0
  241. package/dist/helpers/__tests__/semver-utils.test.d.ts +2 -0
  242. package/dist/helpers/__tests__/semver-utils.test.d.ts.map +1 -0
  243. package/dist/helpers/__tests__/semver-utils.test.js +103 -0
  244. package/dist/helpers/__tests__/semver-utils.test.js.map +1 -0
  245. package/dist/helpers/index.d.ts +3 -2
  246. package/dist/helpers/index.d.ts.map +1 -1
  247. package/dist/helpers/index.js +2 -2
  248. package/dist/helpers/index.js.map +1 -1
  249. package/dist/helpers/move-tests.d.ts +3 -3
  250. package/dist/helpers/move-tests.d.ts.map +1 -1
  251. package/dist/helpers/move-tests.js +21 -20
  252. package/dist/helpers/move-tests.js.map +1 -1
  253. package/dist/helpers/npm-registry.d.ts.map +1 -1
  254. package/dist/helpers/npm-registry.js +1 -3
  255. package/dist/helpers/npm-registry.js.map +1 -1
  256. package/dist/helpers/semver-utils.d.ts.map +1 -1
  257. package/dist/helpers/semver-utils.js +4 -3
  258. package/dist/helpers/semver-utils.js.map +1 -1
  259. package/dist/helpers/setup.d.ts.map +1 -1
  260. package/dist/helpers/setup.js +10 -6
  261. package/dist/helpers/setup.js.map +1 -1
  262. package/dist/helpers/setupLocalTesting.d.ts +32 -27
  263. package/dist/helpers/setupLocalTesting.d.ts.map +1 -1
  264. package/dist/helpers/setupLocalTesting.js +179 -180
  265. package/dist/helpers/setupLocalTesting.js.map +1 -1
  266. package/dist/helpers/testFixtures.d.ts +19 -53
  267. package/dist/helpers/testFixtures.d.ts.map +1 -1
  268. package/dist/helpers/testFixtures.js +89 -107
  269. package/dist/helpers/testFixtures.js.map +1 -1
  270. package/dist/index.d.ts +4 -2
  271. package/dist/index.d.ts.map +1 -1
  272. package/dist/index.js +7 -3
  273. package/dist/index.js.map +1 -1
  274. package/dist/node/LocalNodeManager.d.ts +9 -1
  275. package/dist/node/LocalNodeManager.d.ts.map +1 -1
  276. package/dist/node/LocalNodeManager.js +75 -58
  277. package/dist/node/LocalNodeManager.js.map +1 -1
  278. package/dist/node/__tests__/LocalNodeManager.test.d.ts +2 -0
  279. package/dist/node/__tests__/LocalNodeManager.test.d.ts.map +1 -0
  280. package/dist/node/__tests__/LocalNodeManager.test.js +349 -0
  281. package/dist/node/__tests__/LocalNodeManager.test.js.map +1 -0
  282. package/dist/runtime.d.ts +12 -15
  283. package/dist/runtime.d.ts.map +1 -1
  284. package/dist/runtime.js +32 -241
  285. package/dist/runtime.js.map +1 -1
  286. package/dist/templates/README.md +1 -1
  287. package/dist/templates/movehat.config.ts +10 -0
  288. package/dist/templates/package.json +2 -1
  289. package/dist/templates/scripts/deploy-counter.ts +46 -38
  290. package/dist/templates/tests/Counter.test.ts +51 -51
  291. package/dist/templates/types/movehat.d.ts +6 -9
  292. package/dist/types/config.d.ts +8 -0
  293. package/dist/types/config.d.ts.map +1 -1
  294. package/dist/types/fork.d.ts +7 -1
  295. package/dist/types/fork.d.ts.map +1 -1
  296. package/dist/types/harness.d.ts +166 -0
  297. package/dist/types/harness.d.ts.map +1 -0
  298. package/dist/types/harness.js +2 -0
  299. package/dist/types/harness.js.map +1 -0
  300. package/dist/types/runtime.d.ts +7 -1
  301. package/dist/types/runtime.d.ts.map +1 -1
  302. package/dist/ui/__tests__/colors.test.d.ts +2 -0
  303. package/dist/ui/__tests__/colors.test.d.ts.map +1 -0
  304. package/dist/ui/__tests__/colors.test.js +127 -0
  305. package/dist/ui/__tests__/colors.test.js.map +1 -0
  306. package/dist/ui/colors.d.ts.map +1 -1
  307. package/dist/ui/colors.js +6 -2
  308. package/dist/ui/colors.js.map +1 -1
  309. package/dist/ui/logger.d.ts +17 -0
  310. package/dist/ui/logger.d.ts.map +1 -1
  311. package/dist/ui/logger.js +22 -0
  312. package/dist/ui/logger.js.map +1 -1
  313. package/dist/ui/symbols.d.ts +1 -0
  314. package/dist/ui/symbols.d.ts.map +1 -1
  315. package/dist/ui/symbols.js +7 -1
  316. package/dist/ui/symbols.js.map +1 -1
  317. package/dist/utils/__tests__/address.test.d.ts +2 -0
  318. package/dist/utils/__tests__/address.test.d.ts.map +1 -0
  319. package/dist/utils/__tests__/address.test.js +70 -0
  320. package/dist/utils/__tests__/address.test.js.map +1 -0
  321. package/dist/utils/__tests__/childProcessAdapter.test.d.ts +2 -0
  322. package/dist/utils/__tests__/childProcessAdapter.test.d.ts.map +1 -0
  323. package/dist/utils/__tests__/childProcessAdapter.test.js +217 -0
  324. package/dist/utils/__tests__/childProcessAdapter.test.js.map +1 -0
  325. package/dist/utils/__tests__/runCli.test.d.ts +2 -0
  326. package/dist/utils/__tests__/runCli.test.d.ts.map +1 -0
  327. package/dist/utils/__tests__/runCli.test.js +187 -0
  328. package/dist/utils/__tests__/runCli.test.js.map +1 -0
  329. package/dist/utils/address.d.ts +33 -0
  330. package/dist/utils/address.d.ts.map +1 -0
  331. package/dist/utils/address.js +52 -0
  332. package/dist/utils/address.js.map +1 -0
  333. package/dist/utils/childProcessAdapter.d.ts +93 -0
  334. package/dist/utils/childProcessAdapter.d.ts.map +1 -0
  335. package/dist/utils/childProcessAdapter.js +109 -0
  336. package/dist/utils/childProcessAdapter.js.map +1 -0
  337. package/dist/utils/parseCliOutput.d.ts +20 -0
  338. package/dist/utils/parseCliOutput.d.ts.map +1 -0
  339. package/dist/utils/parseCliOutput.js +26 -0
  340. package/dist/utils/parseCliOutput.js.map +1 -0
  341. package/dist/utils/redact.d.ts +15 -0
  342. package/dist/utils/redact.d.ts.map +1 -0
  343. package/dist/utils/redact.js +24 -0
  344. package/dist/utils/redact.js.map +1 -0
  345. package/dist/utils/runCli.d.ts +24 -0
  346. package/dist/utils/runCli.d.ts.map +1 -0
  347. package/dist/utils/runCli.js +37 -0
  348. package/dist/utils/runCli.js.map +1 -0
  349. package/package.json +14 -4
  350. package/src/__tests__/deployContract.test.ts +429 -0
  351. package/src/__tests__/errors.test.ts +84 -0
  352. package/src/__tests__/fixtures/sigint-deploy-harness.ts +95 -0
  353. package/src/__tests__/fork/api.test.ts +143 -0
  354. package/src/__tests__/harness/Harness.createLive.test.ts +57 -0
  355. package/src/__tests__/harness/Harness.proxy.test.ts +115 -0
  356. package/src/__tests__/harness/_fixture.ts +131 -0
  357. package/src/__tests__/harness/codeObject.deploy.test.ts +319 -0
  358. package/src/__tests__/harness/codeObject.upgrade.test.ts +156 -0
  359. package/src/__tests__/harness/script.test.ts +245 -0
  360. package/src/__tests__/harness/view.test.ts +104 -0
  361. package/src/__tests__/runtime.test.ts +182 -0
  362. package/src/cli.ts +2 -1
  363. package/src/commands/__tests__/compile.test.ts +407 -0
  364. package/src/commands/__tests__/init.test.ts +125 -0
  365. package/src/commands/__tests__/run.test.ts +192 -0
  366. package/src/commands/__tests__/test-move.test.ts +81 -0
  367. package/src/commands/__tests__/test.test.ts +204 -0
  368. package/src/commands/__tests__/update.test.ts +223 -0
  369. package/src/commands/compile.ts +168 -32
  370. package/src/commands/fork/__tests__/create.test.ts +132 -0
  371. package/src/commands/fork/__tests__/fund.test.ts +104 -0
  372. package/src/commands/fork/__tests__/list.test.ts +139 -0
  373. package/src/commands/fork/__tests__/serve.test.ts +121 -0
  374. package/src/commands/fork/__tests__/view-resource.test.ts +101 -0
  375. package/src/commands/fork/create.ts +4 -3
  376. package/src/commands/fork/fund.ts +16 -9
  377. package/src/commands/fork/list.ts +3 -2
  378. package/src/commands/fork/serve.ts +6 -3
  379. package/src/commands/fork/view-resource.ts +11 -6
  380. package/src/commands/run.ts +54 -28
  381. package/src/commands/test-move.ts +4 -3
  382. package/src/commands/test.ts +56 -44
  383. package/src/commands/update.ts +19 -16
  384. package/src/core/AccountManager.ts +23 -10
  385. package/src/core/Publisher.ts +322 -0
  386. package/src/core/__tests__/AccountManager.test.ts +290 -0
  387. package/src/core/__tests__/config.test.ts +377 -0
  388. package/src/core/__tests__/deployments.test.ts +247 -0
  389. package/src/core/__tests__/shell.test.ts +138 -0
  390. package/src/core/config.ts +96 -12
  391. package/src/core/contract.ts +13 -4
  392. package/src/core/deployments.ts +13 -11
  393. package/src/core/movementProfile.ts +179 -0
  394. package/src/core/shell.ts +34 -14
  395. package/src/errors.ts +60 -0
  396. package/src/fork/__tests__/manager.test.ts +385 -0
  397. package/src/fork/__tests__/server.test.ts +65 -0
  398. package/src/fork/__tests__/storage.test.ts +281 -0
  399. package/src/fork/__tests__/test.test.ts +97 -0
  400. package/src/fork/api.ts +28 -14
  401. package/src/fork/manager.ts +88 -43
  402. package/src/fork/server.ts +53 -19
  403. package/src/fork/storage.ts +12 -15
  404. package/src/fork/test.ts +58 -32
  405. package/src/harness/Harness.ts +228 -0
  406. package/src/harness/codeObject.ts +388 -0
  407. package/src/harness/errors.ts +22 -0
  408. package/src/harness/index.ts +3 -0
  409. package/src/harness/proxy.ts +40 -0
  410. package/src/harness/script.ts +196 -0
  411. package/src/harness/view.ts +34 -0
  412. package/src/helpers/__tests__/semver-utils.test.ts +121 -0
  413. package/src/helpers/index.ts +2 -8
  414. package/src/helpers/move-tests.ts +27 -23
  415. package/src/helpers/npm-registry.ts +4 -3
  416. package/src/helpers/semver-utils.ts +4 -3
  417. package/src/helpers/setup.ts +9 -5
  418. package/src/helpers/setupLocalTesting.ts +219 -200
  419. package/src/helpers/testFixtures.ts +106 -118
  420. package/src/index.ts +9 -3
  421. package/src/node/LocalNodeManager.ts +87 -62
  422. package/src/node/__tests__/LocalNodeManager.test.ts +452 -0
  423. package/src/runtime.ts +33 -289
  424. package/src/templates/README.md +1 -1
  425. package/src/templates/movehat.config.ts +10 -0
  426. package/src/templates/package.json +2 -1
  427. package/src/templates/scripts/deploy-counter.ts +46 -38
  428. package/src/templates/tests/Counter.test.ts +51 -51
  429. package/src/templates/types/movehat.d.ts +6 -9
  430. package/src/types/config.ts +8 -0
  431. package/src/types/fork.ts +7 -1
  432. package/src/types/harness.ts +182 -0
  433. package/src/types/runtime.ts +11 -3
  434. package/src/ui/__tests__/colors.test.ts +156 -0
  435. package/src/ui/colors.ts +5 -2
  436. package/src/ui/logger.ts +22 -0
  437. package/src/ui/symbols.ts +7 -1
  438. package/src/utils/__tests__/address.test.ts +93 -0
  439. package/src/utils/__tests__/childProcessAdapter.test.ts +266 -0
  440. package/src/utils/__tests__/runCli.test.ts +240 -0
  441. package/src/utils/address.ts +56 -0
  442. package/src/utils/childProcessAdapter.ts +215 -0
  443. package/src/utils/parseCliOutput.ts +27 -0
  444. package/src/utils/redact.ts +24 -0
  445. package/src/utils/runCli.ts +64 -0
@@ -0,0 +1,247 @@
1
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
+ import { vol, fs as memfsFs } from 'memfs';
3
+
4
+ // Mock fs module
5
+ vi.mock('fs', () => ({
6
+ default: memfsFs,
7
+ ...memfsFs,
8
+ }));
9
+
10
+ // Import after mock
11
+ const {
12
+ validateSafeName,
13
+ saveDeployment,
14
+ loadDeployment,
15
+ getAllDeployments,
16
+ getDeployedAddress,
17
+ } = await import('../deployments.js');
18
+
19
+ describe('validateSafeName', () => {
20
+ it('should accept valid names', () => {
21
+ expect(() => validateSafeName('testnet', 'network')).not.toThrow();
22
+ expect(() => validateSafeName('counter', 'module')).not.toThrow();
23
+ expect(() => validateSafeName('my-module', 'module')).not.toThrow();
24
+ expect(() => validateSafeName('module_v2', 'module')).not.toThrow();
25
+ expect(() => validateSafeName('Module123', 'module')).not.toThrow();
26
+ });
27
+
28
+ it('should reject path traversal attempts', () => {
29
+ expect(() => validateSafeName('../etc/passwd', 'network')).toThrow('Path traversal');
30
+ expect(() => validateSafeName('..\\windows', 'network')).toThrow('Path traversal');
31
+ expect(() => validateSafeName('foo/../bar', 'module')).toThrow('Path traversal');
32
+ });
33
+
34
+ it('should reject slashes', () => {
35
+ expect(() => validateSafeName('path/to/file', 'network')).toThrow('Path traversal');
36
+ expect(() => validateSafeName('path\\to\\file', 'network')).toThrow('Path traversal');
37
+ });
38
+
39
+ it('should reject special characters', () => {
40
+ expect(() => validateSafeName('test;rm', 'module')).toThrow('Only alphanumeric');
41
+ expect(() => validateSafeName('test$var', 'module')).toThrow('Only alphanumeric');
42
+ expect(() => validateSafeName('test space', 'module')).toThrow('Only alphanumeric');
43
+ expect(() => validateSafeName('test.module', 'module')).toThrow('Only alphanumeric');
44
+ });
45
+
46
+ it('should reject hidden files (starting with dot)', () => {
47
+ expect(() => validateSafeName('.hidden', 'network')).toThrow('cannot start with a dot');
48
+ expect(() => validateSafeName('.gitignore', 'module')).toThrow('cannot start with a dot');
49
+ });
50
+
51
+ it('should reject empty strings', () => {
52
+ expect(() => validateSafeName('', 'network')).toThrow('must be a non-empty string');
53
+ });
54
+
55
+ it('should reject non-string input', () => {
56
+ expect(() => validateSafeName(null as any, 'network')).toThrow('must be a non-empty string');
57
+ expect(() => validateSafeName(undefined as any, 'module')).toThrow('must be a non-empty string');
58
+ });
59
+
60
+ it('should use correct type in error messages', () => {
61
+ expect(() => validateSafeName('bad name', 'network')).toThrow('Invalid network name');
62
+ expect(() => validateSafeName('bad name', 'module')).toThrow('Invalid module name');
63
+ });
64
+ });
65
+
66
+ describe('saveDeployment and loadDeployment', () => {
67
+ beforeEach(() => {
68
+ vol.reset();
69
+ // Create initial directory structure
70
+ vol.fromJSON({
71
+ '/project/.gitkeep': '',
72
+ });
73
+ // Mock process.cwd
74
+ vi.spyOn(process, 'cwd').mockReturnValue('/project');
75
+ });
76
+
77
+ afterEach(() => {
78
+ vol.reset();
79
+ vi.restoreAllMocks();
80
+ });
81
+
82
+ it('should save and load deployment', () => {
83
+ const deployment = {
84
+ address: '0x1234',
85
+ moduleName: 'counter',
86
+ network: 'testnet',
87
+ deployer: '0xabcd',
88
+ timestamp: 1704985623564,
89
+ txHash: '0x5678',
90
+ };
91
+
92
+ // Mock console.log to suppress output
93
+ vi.spyOn(console, 'log').mockImplementation(() => {});
94
+
95
+ saveDeployment(deployment);
96
+
97
+ const loaded = loadDeployment('testnet', 'counter');
98
+ expect(loaded).toEqual(deployment);
99
+ });
100
+
101
+ it('should return null for non-existent deployment', () => {
102
+ const loaded = loadDeployment('testnet', 'nonexistent');
103
+ expect(loaded).toBeNull();
104
+ });
105
+
106
+ it('should create directories if they do not exist', () => {
107
+ const deployment = {
108
+ address: '0x1234',
109
+ moduleName: 'token',
110
+ network: 'mainnet',
111
+ deployer: '0xabcd',
112
+ timestamp: Date.now(),
113
+ };
114
+
115
+ vi.spyOn(console, 'log').mockImplementation(() => {});
116
+
117
+ saveDeployment(deployment);
118
+
119
+ expect(vol.existsSync('/project/deployments')).toBe(true);
120
+ expect(vol.existsSync('/project/deployments/mainnet')).toBe(true);
121
+ });
122
+
123
+ it('should reject invalid network names when saving', () => {
124
+ const deployment = {
125
+ address: '0x1234',
126
+ moduleName: 'counter',
127
+ network: '../etc',
128
+ deployer: '0xabcd',
129
+ timestamp: Date.now(),
130
+ };
131
+
132
+ expect(() => saveDeployment(deployment)).toThrow('Path traversal');
133
+ });
134
+
135
+ it('should reject invalid module names when saving', () => {
136
+ const deployment = {
137
+ address: '0x1234',
138
+ moduleName: 'counter;rm -rf',
139
+ network: 'testnet',
140
+ deployer: '0xabcd',
141
+ timestamp: Date.now(),
142
+ };
143
+
144
+ expect(() => saveDeployment(deployment)).toThrow('Only alphanumeric');
145
+ });
146
+ });
147
+
148
+ describe('getAllDeployments', () => {
149
+ beforeEach(() => {
150
+ vol.reset();
151
+ vi.spyOn(process, 'cwd').mockReturnValue('/project');
152
+ });
153
+
154
+ afterEach(() => {
155
+ vol.reset();
156
+ vi.restoreAllMocks();
157
+ });
158
+
159
+ it('should return empty object for non-existent network', () => {
160
+ vol.fromJSON({
161
+ '/project/.gitkeep': '',
162
+ });
163
+
164
+ const deployments = getAllDeployments('nonexistent');
165
+ expect(deployments).toEqual({});
166
+ });
167
+
168
+ it('should return all deployments for a network', () => {
169
+ vol.fromJSON({
170
+ '/project/deployments/testnet/counter.json': JSON.stringify({
171
+ address: '0x1',
172
+ moduleName: 'counter',
173
+ network: 'testnet',
174
+ deployer: '0xd1',
175
+ timestamp: 1000,
176
+ }),
177
+ '/project/deployments/testnet/token.json': JSON.stringify({
178
+ address: '0x2',
179
+ moduleName: 'token',
180
+ network: 'testnet',
181
+ deployer: '0xd2',
182
+ timestamp: 2000,
183
+ }),
184
+ });
185
+
186
+ const deployments = getAllDeployments('testnet');
187
+
188
+ expect(Object.keys(deployments)).toHaveLength(2);
189
+ expect(deployments['counter']?.address).toBe('0x1');
190
+ expect(deployments['token']?.address).toBe('0x2');
191
+ });
192
+
193
+ it('should ignore non-JSON files', () => {
194
+ vol.fromJSON({
195
+ '/project/deployments/testnet/counter.json': JSON.stringify({
196
+ address: '0x1',
197
+ moduleName: 'counter',
198
+ network: 'testnet',
199
+ deployer: '0xd1',
200
+ timestamp: 1000,
201
+ }),
202
+ '/project/deployments/testnet/README.md': '# Readme',
203
+ '/project/deployments/testnet/.gitkeep': '',
204
+ });
205
+
206
+ const deployments = getAllDeployments('testnet');
207
+
208
+ expect(Object.keys(deployments)).toHaveLength(1);
209
+ expect(deployments['counter']).toBeDefined();
210
+ });
211
+ });
212
+
213
+ describe('getDeployedAddress', () => {
214
+ beforeEach(() => {
215
+ vol.reset();
216
+ vi.spyOn(process, 'cwd').mockReturnValue('/project');
217
+ });
218
+
219
+ afterEach(() => {
220
+ vol.reset();
221
+ vi.restoreAllMocks();
222
+ });
223
+
224
+ it('should return address for existing deployment', () => {
225
+ vol.fromJSON({
226
+ '/project/deployments/testnet/counter.json': JSON.stringify({
227
+ address: '0x1234abcd',
228
+ moduleName: 'counter',
229
+ network: 'testnet',
230
+ deployer: '0xd1',
231
+ timestamp: 1000,
232
+ }),
233
+ });
234
+
235
+ const address = getDeployedAddress('testnet', 'counter');
236
+ expect(address).toBe('0x1234abcd');
237
+ });
238
+
239
+ it('should return null for non-existent deployment', () => {
240
+ vol.fromJSON({
241
+ '/project/.gitkeep': '',
242
+ });
243
+
244
+ const address = getDeployedAddress('testnet', 'nonexistent');
245
+ expect(address).toBeNull();
246
+ });
247
+ });
@@ -0,0 +1,138 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import {
3
+ escapeShellArg,
4
+ validateAndEscapePath,
5
+ validateAndEscapeProfile,
6
+ } from '../shell.js';
7
+
8
+ describe('escapeShellArg', () => {
9
+ it('should wrap simple strings in single quotes', () => {
10
+ expect(escapeShellArg('hello')).toBe("'hello'");
11
+ });
12
+
13
+ it('should escape single quotes within strings', () => {
14
+ expect(escapeShellArg("it's")).toBe("'it'\\''s'");
15
+ });
16
+
17
+ it('should handle multiple single quotes', () => {
18
+ expect(escapeShellArg("it's a 'test'")).toBe("'it'\\''s a '\\''test'\\'''");
19
+ });
20
+
21
+ it('should handle empty strings', () => {
22
+ expect(escapeShellArg('')).toBe("''");
23
+ });
24
+
25
+ it('should handle strings with spaces', () => {
26
+ expect(escapeShellArg('hello world')).toBe("'hello world'");
27
+ });
28
+
29
+ it('should handle paths with spaces', () => {
30
+ expect(escapeShellArg('/path/to/my project')).toBe("'/path/to/my project'");
31
+ });
32
+
33
+ it('should throw for non-string input', () => {
34
+ expect(() => escapeShellArg(123 as any)).toThrow('Shell argument must be a string');
35
+ expect(() => escapeShellArg(null as any)).toThrow('Shell argument must be a string');
36
+ expect(() => escapeShellArg(undefined as any)).toThrow('Shell argument must be a string');
37
+ });
38
+
39
+ it('should handle special characters safely', () => {
40
+ // These should be safely wrapped, not executed
41
+ expect(escapeShellArg('$(whoami)')).toBe("'$(whoami)'");
42
+ expect(escapeShellArg('`ls`')).toBe("'`ls`'");
43
+ });
44
+ });
45
+
46
+ describe('validateAndEscapePath', () => {
47
+ it('should accept valid paths', () => {
48
+ expect(validateAndEscapePath('/home/user/project')).toBe("'/home/user/project'");
49
+ expect(validateAndEscapePath('./my-project')).toBe("'./my-project'");
50
+ expect(validateAndEscapePath('C:\\Users\\project')).toBe("'C:\\Users\\project'");
51
+ });
52
+
53
+ it('should accept paths with spaces', () => {
54
+ expect(validateAndEscapePath('/home/user/my project')).toBe("'/home/user/my project'");
55
+ });
56
+
57
+ it('should accept paths with dots and underscores', () => {
58
+ expect(validateAndEscapePath('./my_project.test')).toBe("'./my_project.test'");
59
+ });
60
+
61
+ it('should reject paths with semicolons (command chaining)', () => {
62
+ expect(() => validateAndEscapePath('/path; rm -rf /')).toThrow('potentially dangerous characters');
63
+ });
64
+
65
+ it('should reject paths with pipes', () => {
66
+ expect(() => validateAndEscapePath('/path | cat /etc/passwd')).toThrow('potentially dangerous characters');
67
+ });
68
+
69
+ it('should reject paths with backticks (command substitution)', () => {
70
+ expect(() => validateAndEscapePath('/path/`whoami`')).toThrow('potentially dangerous characters');
71
+ });
72
+
73
+ it('should reject paths with $() (command substitution)', () => {
74
+ expect(() => validateAndEscapePath('/path/$(whoami)')).toThrow('potentially dangerous characters');
75
+ });
76
+
77
+ it('should reject paths with ampersand', () => {
78
+ expect(() => validateAndEscapePath('/path & echo hacked')).toThrow('potentially dangerous characters');
79
+ });
80
+
81
+ it('should reject paths with curly braces', () => {
82
+ expect(() => validateAndEscapePath('/path/{a,b}')).toThrow('potentially dangerous characters');
83
+ });
84
+
85
+ it('should reject paths with redirects', () => {
86
+ expect(() => validateAndEscapePath('/path > /etc/passwd')).toThrow('potentially dangerous characters');
87
+ expect(() => validateAndEscapePath('/path < /etc/passwd')).toThrow('potentially dangerous characters');
88
+ });
89
+
90
+ it('should throw for empty paths', () => {
91
+ expect(() => validateAndEscapePath('')).toThrow('must be a non-empty string');
92
+ });
93
+
94
+ it('should throw for non-string input', () => {
95
+ expect(() => validateAndEscapePath(null as any)).toThrow('must be a non-empty string');
96
+ expect(() => validateAndEscapePath(undefined as any)).toThrow('must be a non-empty string');
97
+ });
98
+
99
+ it('should use custom name in error messages', () => {
100
+ expect(() => validateAndEscapePath('', 'Move directory')).toThrow('Invalid Move directory');
101
+ });
102
+ });
103
+
104
+ describe('validateAndEscapeProfile', () => {
105
+ it('should accept valid profile names', () => {
106
+ expect(validateAndEscapeProfile('default')).toBe("'default'");
107
+ expect(validateAndEscapeProfile('my-profile')).toBe("'my-profile'");
108
+ expect(validateAndEscapeProfile('profile_123')).toBe("'profile_123'");
109
+ });
110
+
111
+ it('should accept alphanumeric names', () => {
112
+ expect(validateAndEscapeProfile('Profile1')).toBe("'Profile1'");
113
+ expect(validateAndEscapeProfile('test123')).toBe("'test123'");
114
+ });
115
+
116
+ it('should reject profiles with spaces', () => {
117
+ expect(() => validateAndEscapeProfile('my profile')).toThrow('Only alphanumeric');
118
+ });
119
+
120
+ it('should reject profiles with special characters', () => {
121
+ expect(() => validateAndEscapeProfile('profile;rm')).toThrow('Only alphanumeric');
122
+ expect(() => validateAndEscapeProfile('profile$test')).toThrow('Only alphanumeric');
123
+ expect(() => validateAndEscapeProfile('profile/test')).toThrow('Only alphanumeric');
124
+ });
125
+
126
+ it('should reject profiles with dots', () => {
127
+ expect(() => validateAndEscapeProfile('profile.test')).toThrow('Only alphanumeric');
128
+ });
129
+
130
+ it('should throw for empty profiles', () => {
131
+ expect(() => validateAndEscapeProfile('')).toThrow('must be a non-empty string');
132
+ });
133
+
134
+ it('should throw for non-string input', () => {
135
+ expect(() => validateAndEscapeProfile(null as any)).toThrow('must be a non-empty string');
136
+ expect(() => validateAndEscapeProfile(undefined as any)).toThrow('must be a non-empty string');
137
+ });
138
+ });
@@ -1,11 +1,33 @@
1
1
  import { pathToFileURL } from "url";
2
2
  import { join } from "path";
3
- import { existsSync } from "fs";
3
+ import { existsSync, statSync } from "fs";
4
+ import { Account, Ed25519PrivateKey } from "@aptos-labs/ts-sdk";
4
5
  import { MovehatConfig, MovehatUserConfig } from "../types/config.js";
5
6
 
7
+ interface ConfigCacheEntry {
8
+ mtimeMs: number;
9
+ config: MovehatUserConfig;
10
+ }
11
+
12
+ // Keyed by resolved absolute path. One entry per config file the process
13
+ // has loaded. Closes #62 — the previous `?t=Date.now()` cache-bust
14
+ // created a fresh Node loader module per call.
15
+ //
16
+ // Note on concurrency: two `loadUserConfig()` calls racing on a cold
17
+ // cache may both invoke `import()`. Node's loader cache deduplicates by
18
+ // URL so both resolve to the same module, and both writers store the
19
+ // same value here. No corruption, no in-flight-promise memoization
20
+ // needed.
21
+ const configCache = new Map<string, ConfigCacheEntry>();
22
+
6
23
  /**
7
- * Loads the user's movehat.config.js from the current working directory.
8
- *
24
+ * Loads the user's movehat.config.{ts,js} from the current working directory.
25
+ *
26
+ * Cached by `{ absPath, mtimeMs }`: a second call with no edit returns
27
+ * the parsed object directly and skips both the tsx loader register
28
+ * dance and the dynamic `import()`. Edits invalidate via the file's
29
+ * mtime.
30
+ *
9
31
  * @throws {Error} If the configuration file is not found or fails to load
10
32
  * @security This function loads and executes code from the current working directory.
11
33
  * It should only be called from trusted project directories.
@@ -13,7 +35,6 @@ import { MovehatConfig, MovehatUserConfig } from "../types/config.js";
13
35
  export async function loadUserConfig(): Promise<MovehatUserConfig> {
14
36
  const cwd = process.cwd();
15
37
 
16
- // Try to find config file (.ts first, then .js)
17
38
  const possiblePaths = [
18
39
  join(cwd, "movehat.config.ts"),
19
40
  join(cwd, "movehat.config.js"),
@@ -34,41 +55,56 @@ export async function loadUserConfig(): Promise<MovehatUserConfig> {
34
55
  }
35
56
 
36
57
  try {
58
+ const { mtimeMs } = statSync(configPath);
59
+
60
+ const cached = configCache.get(configPath);
61
+ if (cached && cached.mtimeMs === mtimeMs) {
62
+ return cached.config;
63
+ }
64
+
37
65
  let configModule;
38
66
 
39
67
  if (configPath.endsWith('.ts')) {
40
- // For TypeScript files, we need to use tsx's import system
41
- // Register tsx loader for .ts files
42
68
  const { register } = await import('tsx/esm/api');
43
69
  const unregister = register();
44
70
 
45
71
  try {
46
72
  const configUrl = pathToFileURL(configPath).href;
47
- configModule = await import(configUrl + '?t=' + Date.now());
73
+ configModule = await import(configUrl + '?mtime=' + mtimeMs);
48
74
  } finally {
49
75
  unregister();
50
76
  }
51
77
  } else {
52
- // For .js files, use standard import
53
78
  const configUrl = pathToFileURL(configPath).href;
54
- configModule = await import(configUrl + '?t=' + Date.now());
79
+ configModule = await import(configUrl + '?mtime=' + mtimeMs);
55
80
  }
56
81
 
57
82
  const userConfig = configModule.default as MovehatUserConfig;
58
83
 
59
- // Validate that networks are defined
60
84
  if (!userConfig.networks || Object.keys(userConfig.networks).length === 0) {
61
85
  throw new Error(
62
86
  "No networks defined in configuration. Add at least one network in the 'networks' field."
63
87
  );
64
88
  }
65
89
 
90
+ configCache.set(configPath, { mtimeMs, config: userConfig });
91
+
66
92
  return userConfig;
67
93
  } catch (error) {
68
94
  throw new Error(`Failed to load configuration file '${configPath}': ${error}`);
69
95
  }
70
96
  }
71
97
 
98
+ /**
99
+ * Clear the in-memory config cache. Test-only escape hatch.
100
+ *
101
+ * @internal Not part of the public API surface. Imported via relative
102
+ * path from `core/__tests__/config.test.ts` only.
103
+ */
104
+ export function _resetConfigCache(): void {
105
+ configCache.clear();
106
+ }
107
+
72
108
  /**
73
109
  * Resolve configuration for a specific network
74
110
  * Merges global settings with network-specific settings
@@ -178,18 +214,66 @@ export async function resolveNetworkConfig(
178
214
  ...(networkConfig.namedAddresses || {}),
179
215
  };
180
216
 
217
+ // Capture the primary key after the L178 guard guaranteed it exists
218
+ // (either present from the start, or auto-assigned by the testnet/local
219
+ // branch; the else-branch throws). Pulling into a local lets TS see
220
+ // the non-undefined narrowing.
221
+ const primaryKey = accounts[0];
222
+ if (!primaryKey) {
223
+ throw new Error("invariant: accounts[0] must exist after the L178 guard");
224
+ }
225
+
226
+ // Derive the deployer account address from the resolved private key.
227
+ // Without this, consumers reading `config.account` got an empty string
228
+ // (the previous "Will be derived from privateKey in runtime" TODO was
229
+ // never wired). Falls back to "" on malformed keys so we don't break
230
+ // existing callers that don't need the field.
231
+ const accountAddress = deriveAccountAddress(primaryKey);
232
+
181
233
  // Build resolved config
182
234
  const resolvedConfig: MovehatConfig = {
183
235
  network: selectedNetwork,
184
236
  rpc: networkConfig.url,
185
- privateKey: accounts[0],
237
+ privateKey: primaryKey,
186
238
  allAccounts: accounts,
187
239
  profile: networkConfig.profile || "default",
188
240
  moveDir: userConfig.moveDir || "./move",
189
- account: "", // Will be derived from privateKey in runtime
241
+ account: accountAddress,
190
242
  namedAddresses: mergedNamedAddresses,
191
243
  networkConfig: networkConfig,
192
244
  };
193
245
 
194
246
  return resolvedConfig;
195
247
  }
248
+
249
+ /**
250
+ * Derive the on-chain account address from a private key. Strips the
251
+ * `ed25519-priv-` prefix that Movement CLI sometimes emits; returns ""
252
+ * on any parse failure so existing callers that don't consume the field
253
+ * keep working unchanged. Emits a console.warn on failure so a
254
+ * misconfigured `PRIVATE_KEY` surfaces here (loud, at config-resolution
255
+ * time) instead of as a cryptic "Hex string is too short" SDK error
256
+ * later in the call chain.
257
+ */
258
+ function deriveAccountAddress(privateKeyHex: string | undefined): string {
259
+ if (!privateKeyHex) return "";
260
+ try {
261
+ const stripped = privateKeyHex.startsWith("ed25519-priv-")
262
+ ? privateKeyHex.slice("ed25519-priv-".length)
263
+ : privateKeyHex;
264
+ const account = Account.fromPrivateKey({
265
+ privateKey: new Ed25519PrivateKey(stripped),
266
+ });
267
+ return account.accountAddress.toString();
268
+ } catch (err) {
269
+ // The private key may have come from several sources (network.accounts,
270
+ // global accounts, PRIVATE_KEY env, auto-generated testnet key). Keep
271
+ // the hint generic so it never points at the wrong source.
272
+ console.warn(
273
+ `[movehat] Could not derive account address from the resolved private key: ${
274
+ (err as Error).message
275
+ }. Verify the key configured for this network is a valid Ed25519 private key (with or without the "ed25519-priv-" prefix).`
276
+ );
277
+ return "";
278
+ }
279
+ }
@@ -4,6 +4,7 @@ import {
4
4
  type InputViewFunctionData,
5
5
  type MoveFunctionId,
6
6
  } from "@aptos-labs/ts-sdk";
7
+ import { logger } from "../ui/index.js";
7
8
 
8
9
  export interface TransactionResult {
9
10
  hash: string;
@@ -21,12 +22,17 @@ export class MoveContract {
21
22
  async call(
22
23
  signer: Account,
23
24
  functionName: string,
25
+ // any[]: Move entry-function arguments are heterogeneous primitives
26
+ // (u8/u64/string/bool/address/vector) passed through to the Aptos
27
+ // SDK's `functionArguments`, which validates at submit time. A
28
+ // narrower union here would force casts at every call site for
29
+ // little safety gain.
24
30
  args: any[] = [],
25
31
  typeArgs: string[] = []
26
32
  ): Promise<TransactionResult> {
27
33
  const functionFullName = `${this.moduleAddress}::${this.moduleName}::${functionName}`;
28
34
 
29
- console.log(`📝 Calling ${functionFullName}...`);
35
+ logger.step(`Calling ${functionFullName}...`);
30
36
 
31
37
  const transaction = await this.aptos.transaction.build.simple({
32
38
  sender: signer.accountAddress,
@@ -51,9 +57,10 @@ export class MoveContract {
51
57
  transactionHash: committedTxn.hash,
52
58
  });
53
59
 
54
- console.log(
55
- `✅ Transaction ${committedTxn.hash} committed with status: ${response.vm_status}\n`
60
+ logger.success(
61
+ `Transaction ${committedTxn.hash} committed with status: ${response.vm_status}`
56
62
  );
63
+ logger.newline();
57
64
 
58
65
  return {
59
66
  hash: committedTxn.hash,
@@ -62,8 +69,10 @@ export class MoveContract {
62
69
  };
63
70
  }
64
71
 
65
- async view<T = any>(
72
+ async view<T = unknown>(
66
73
  functionName: string,
74
+ // any[]: see `call()` above — Move view-function arguments share
75
+ // the same SDK-validated boundary semantics.
67
76
  args: any[] = [],
68
77
  typeArgs: string[] = []
69
78
  ): Promise<T> {
@@ -1,5 +1,6 @@
1
1
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
2
2
  import { join } from "path";
3
+ import { logger } from "../ui/index.js";
3
4
 
4
5
  export interface DeploymentInfo {
5
6
  address: string;
@@ -7,8 +8,8 @@ export interface DeploymentInfo {
7
8
  network: string;
8
9
  deployer: string;
9
10
  timestamp: number;
10
- txHash?: string;
11
- blockNumber?: string;
11
+ txHash?: string | undefined;
12
+ blockNumber?: string | undefined;
12
13
  }
13
14
 
14
15
  /**
@@ -30,20 +31,21 @@ export function validateSafeName(name: string, type: "network" | "module"): void
30
31
  );
31
32
  }
32
33
 
33
- // Only allow alphanumeric, hyphens, underscores
34
- const safePattern = /^[a-zA-Z0-9_-]+$/;
35
- if (!safePattern.test(name)) {
34
+ // Reject hidden-file names first so the error message is specific
35
+ // (otherwise the alphanumeric check below would fire generically).
36
+ if (name.startsWith(".")) {
36
37
  throw new Error(
37
38
  `Invalid ${type} name: "${name}"\n` +
38
- `Only alphanumeric characters, hyphens (-), and underscores (_) are allowed.`
39
+ `Names cannot start with a dot (.) to prevent hidden file creation.`
39
40
  );
40
41
  }
41
42
 
42
- // Additional check: prevent starting with dot (hidden files)
43
- if (name.startsWith(".")) {
43
+ // Only allow alphanumeric, hyphens, underscores
44
+ const safePattern = /^[a-zA-Z0-9_-]+$/;
45
+ if (!safePattern.test(name)) {
44
46
  throw new Error(
45
47
  `Invalid ${type} name: "${name}"\n` +
46
- `Names cannot start with a dot (.) to prevent hidden file creation.`
48
+ `Only alphanumeric characters, hyphens (-), and underscores (_) are allowed.`
47
49
  );
48
50
  }
49
51
  }
@@ -89,8 +91,8 @@ export function saveDeployment(deployment: DeploymentInfo): void {
89
91
 
90
92
  try {
91
93
  writeFileSync(filePath, JSON.stringify(deployment, null, 2), "utf-8");
92
- console.log(
93
- `💾 Deployment saved: deployments/${deployment.network}/${deployment.moduleName}.json`
94
+ logger.success(
95
+ `Deployment saved: deployments/${deployment.network}/${deployment.moduleName}.json`
94
96
  );
95
97
  } catch (error) {
96
98
  console.error(