movehat 0.1.9 → 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 +6 -4
  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 +28 -239
  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 +39 -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 +6 -4
  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 +30 -288
  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 +39 -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
@@ -1,9 +1,9 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
- import { exec } from "child_process";
4
3
  import { loadUserConfig } from "../core/config.js";
5
- import { validateAndEscapePath, escapeShellArg } from "../core/shell.js";
4
+ import { validatePathSafety } from "../core/shell.js";
6
5
  import { logger } from "../ui/index.js";
6
+ import { runCli } from "../utils/runCli.js";
7
7
 
8
8
  /**
9
9
  * Recursively find all .move files in a directory
@@ -61,6 +61,7 @@ export function extractNamedAddresses(moveDir: string): Set<string> {
61
61
 
62
62
  while ((match = moduleRegex.exec(content)) !== null) {
63
63
  const address = match[1];
64
+ if (!address) continue;
64
65
  // Skip standard addresses
65
66
  if (address !== 'std' && address !== 'aptos_framework' && address !== 'aptos_std') {
66
67
  addresses.add(address);
@@ -71,22 +72,148 @@ export function extractNamedAddresses(moveDir: string): Set<string> {
71
72
  return addresses;
72
73
  }
73
74
 
74
- function run(command: string, cwd: string) {
75
- return new Promise<void>((resolve, reject) => {
76
- exec(command, {
75
+ /**
76
+ * List of dev addresses to use for auto-assignment (to avoid conflicts)
77
+ */
78
+ const DEV_ADDRESSES = [
79
+ "0xcafe",
80
+ "0xbeef",
81
+ "0xdead",
82
+ "0xface",
83
+ "0xfeed",
84
+ "0xc0de",
85
+ "0xbabe",
86
+ "0xf00d",
87
+ ];
88
+
89
+ /**
90
+ * Update Move.toml with detected addresses
91
+ * Adds missing addresses to [addresses] and [dev-addresses] sections
92
+ */
93
+ export function updateMoveToml(moveDir: string, detectedAddresses: Set<string>): string[] {
94
+ const moveTomlPath = path.join(moveDir, "Move.toml");
95
+
96
+ if (!fs.existsSync(moveTomlPath)) {
97
+ return [];
98
+ }
99
+
100
+ let content = fs.readFileSync(moveTomlPath, "utf-8");
101
+ const addedAddresses: string[] = [];
102
+
103
+ // Parse existing addresses from [addresses] section
104
+ const existingAddresses = new Set<string>();
105
+ const addressesMatch = content.match(/\[addresses\]([\s\S]*?)(?=\[|$)/);
106
+ if (addressesMatch && addressesMatch[1]) {
107
+ const addressesSection = addressesMatch[1];
108
+ const addrRegex = /^([a-zA-Z_][a-zA-Z0-9_]*)\s*=/gm;
109
+ let match;
110
+ while ((match = addrRegex.exec(addressesSection)) !== null) {
111
+ if (match[1]) existingAddresses.add(match[1]);
112
+ }
113
+ }
114
+
115
+ // Parse existing dev-addresses
116
+ const existingDevAddresses = new Map<string, string>();
117
+ const devAddressesMatch = content.match(/\[dev-addresses\]([\s\S]*?)(?=\[|$)/);
118
+ if (devAddressesMatch && devAddressesMatch[1]) {
119
+ const devSection = devAddressesMatch[1];
120
+ const devRegex = /^([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*"(0x[a-fA-F0-9]+)"/gm;
121
+ let match;
122
+ while ((match = devRegex.exec(devSection)) !== null) {
123
+ const name = match[1];
124
+ const addr = match[2];
125
+ if (name && addr) existingDevAddresses.set(name, addr.toLowerCase());
126
+ }
127
+ }
128
+
129
+ // Get used dev addresses to avoid conflicts
130
+ const usedDevAddresses = new Set(existingDevAddresses.values());
131
+
132
+ // Find addresses that need to be added
133
+ const missingAddresses: string[] = [];
134
+ for (const addr of detectedAddresses) {
135
+ if (!existingAddresses.has(addr)) {
136
+ missingAddresses.push(addr);
137
+ }
138
+ }
139
+
140
+ if (missingAddresses.length === 0) {
141
+ return [];
142
+ }
143
+
144
+ // Assign unique dev addresses to new addresses
145
+ const newDevAddresses: Map<string, string> = new Map();
146
+ let devAddrIndex = 0;
147
+
148
+ for (const addr of missingAddresses) {
149
+ // Find next available dev address
150
+ while (devAddrIndex < DEV_ADDRESSES.length) {
151
+ const candidate = DEV_ADDRESSES[devAddrIndex];
152
+ if (candidate && !usedDevAddresses.has(candidate)) break;
153
+ devAddrIndex++;
154
+ }
155
+
156
+ const devCandidate = DEV_ADDRESSES[devAddrIndex];
157
+ if (devCandidate) {
158
+ newDevAddresses.set(addr, devCandidate);
159
+ usedDevAddresses.add(devCandidate);
160
+ devAddrIndex++;
161
+ } else {
162
+ // Generate a unique address if we run out of predefined ones
163
+ const uniqueAddr = `0x${(0x1000 + devAddrIndex).toString(16)}`;
164
+ newDevAddresses.set(addr, uniqueAddr);
165
+ devAddrIndex++;
166
+ }
167
+ }
168
+
169
+ // Update [addresses] section
170
+ if (addressesMatch && addressesMatch[1] !== undefined) {
171
+ const addressesSection = addressesMatch[1];
172
+ const newLines = missingAddresses.map(addr => `${addr} = "_"`).join("\n");
173
+ const updatedSection = addressesSection.trimEnd() + "\n" + newLines + "\n";
174
+ content = content.replace(addressesMatch[0], `[addresses]${updatedSection}`);
175
+ }
176
+
177
+ // Update [dev-addresses] section
178
+ const updatedDevMatch = content.match(/\[dev-addresses\]([\s\S]*?)(?=\[|$)/);
179
+ if (updatedDevMatch && updatedDevMatch[1] !== undefined) {
180
+ const devSection = updatedDevMatch[1];
181
+ const newDevLines = missingAddresses.map(addr => `${addr} = "${newDevAddresses.get(addr)}"`).join("\n");
182
+ // Remove trailing comments/whitespace before adding new lines
183
+ const cleanedSection = devSection.replace(/\n*$/, "\n");
184
+ const updatedDevSection = cleanedSection + newDevLines + "\n";
185
+ content = content.replace(updatedDevMatch[0], `[dev-addresses]${updatedDevSection}`);
186
+ }
187
+
188
+ // Write updated content
189
+ fs.writeFileSync(moveTomlPath, content);
190
+
191
+ return missingAddresses;
192
+ }
193
+
194
+ async function runMovementBuild(
195
+ args: readonly string[],
196
+ cwd: string
197
+ ): Promise<void> {
198
+ // Use throwOnNonZeroExit:false so we can log stdout/stderr in both
199
+ // success and failure paths, matching the behavior of the previous
200
+ // exec-based helper.
201
+ const result = await runCli(
202
+ {
203
+ command: "movement",
204
+ args,
77
205
  cwd,
78
- timeout: 120000, // 2 minutes for git dependency downloads
79
- maxBuffer: 10 * 1024 * 1024, // 10MB buffer for large outputs
80
- }, (error, stdout, stderr) => {
81
- if (stdout) console.log(stdout.trim());
82
- if (stderr) console.error(stderr.trim());
83
- if (error) {
84
- reject(error);
85
- return;
86
- }
87
- resolve();
88
- });
89
- });
206
+ timeoutMs: 120000, // 2 minutes for git dependency downloads
207
+ },
208
+ { throwOnNonZeroExit: false }
209
+ );
210
+
211
+ if (result.stdout) console.log(result.stdout.trim());
212
+ if (result.stderr) console.error(result.stderr.trim());
213
+
214
+ if (result.exitCode !== 0) {
215
+ throw new Error(`movement move build exited with code ${result.exitCode}`);
216
+ }
90
217
  }
91
218
 
92
219
  /**
@@ -94,8 +221,9 @@ function run(command: string, cwd: string) {
94
221
  *
95
222
  * This command:
96
223
  * - Detects named addresses used in Move modules
224
+ * - Auto-updates Move.toml with missing addresses
97
225
  * - Merges auto-detected addresses with user-configured addresses
98
- * - Auto-assigns development addresses (0xcafe) for missing addresses
226
+ * - Auto-assigns development addresses for missing addresses
99
227
  * - Executes `movement move build` with proper named address mappings
100
228
  *
101
229
  * @example
@@ -118,12 +246,19 @@ export default async function compileCommand() {
118
246
  process.exit(1);
119
247
  }
120
248
 
121
- // Validate and escape to prevent command injection
122
- const safeMoveDir = validateAndEscapePath(moveDir, "Move directory");
249
+ // Validate the move directory before passing it to the child process.
250
+ // No shell escaping needed — runCli uses spawn-with-args, not exec.
251
+ const safeMoveDir = validatePathSafety(moveDir, "Move directory");
123
252
 
124
253
  // Auto-detect named addresses from Move files
125
254
  const detectedAddresses = extractNamedAddresses(moveDir);
126
255
 
256
+ // Auto-update Move.toml with missing addresses
257
+ const addedToToml = updateMoveToml(moveDir, detectedAddresses);
258
+ if (addedToToml.length > 0) {
259
+ logger.success(`Added ${addedToToml.length} address(es) to Move.toml: ${addedToToml.join(", ")}`);
260
+ }
261
+
127
262
  // Merge user-configured addresses with auto-detected ones
128
263
  const namedAddresses = { ...(userConfig.namedAddresses ?? {}) };
129
264
  const autoAssignedAddresses: string[] = [];
@@ -136,11 +271,10 @@ export default async function compileCommand() {
136
271
  }
137
272
  }
138
273
 
139
- let namedAddressesArg = "";
274
+ let namedAddressesValue = "";
140
275
 
141
276
  if (Object.keys(namedAddresses).length > 0) {
142
- // Validate and escape each address name and value
143
- const escapedAddresses = Object.entries(namedAddresses)
277
+ namedAddressesValue = Object.entries(namedAddresses)
144
278
  .map(([k, v]) => {
145
279
  // Validate address name (alphanumeric, underscore only)
146
280
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(k)) {
@@ -158,36 +292,38 @@ export default async function compileCommand() {
158
292
  );
159
293
  }
160
294
 
161
- // No need to escape since we validated the format
162
295
  return `${k}=${v}`;
163
296
  })
164
297
  .join(",");
165
-
166
- namedAddressesArg = `--named-addresses ${escapeShellArg(escapedAddresses)}`;
167
298
  }
168
299
 
169
- const command = `movement move build --package-dir ${safeMoveDir} ${namedAddressesArg}`.trim();
300
+ const args: string[] = ["move", "build", "--package-dir", safeMoveDir];
301
+ if (namedAddressesValue) {
302
+ args.push("--named-addresses", namedAddressesValue);
303
+ }
170
304
 
171
305
  logger.kv('Move directory', moveDir, 2);
172
306
  if (detectedAddresses.size > 0) {
173
307
  logger.kv('Detected addresses', Array.from(detectedAddresses).join(", "), 2);
174
308
  }
175
- if (Object.keys(userConfig.namedAddresses ?? {}).length > 0) {
176
- logger.kv('Configured addresses', Object.keys(userConfig.namedAddresses!).join(", "), 2);
309
+ const namedAddrs = userConfig.namedAddresses ?? {};
310
+ if (Object.keys(namedAddrs).length > 0) {
311
+ logger.kv('Configured addresses', Object.keys(namedAddrs).join(", "), 2);
177
312
  }
178
313
  if (autoAssignedAddresses.length > 0) {
179
314
  logger.kv('Auto-assigned (0xcafe)', autoAssignedAddresses.join(", "), 2);
180
315
  }
181
316
  logger.newline();
182
317
 
183
- await run(command, moveDir);
318
+ await runMovementBuild(args, moveDir);
184
319
 
185
320
  logger.newline();
186
321
  logger.success('Compilation finished successfully');
187
322
  logger.newline();
188
- } catch (err: any) {
323
+ } catch (err) {
189
324
  logger.newline();
190
- logger.error(`Compilation failed: ${err.message ?? err}`);
325
+ const msg = err instanceof Error ? err.message : String(err);
326
+ logger.error(`Compilation failed: ${msg}`);
191
327
  logger.newline();
192
328
  process.exit(1);
193
329
  }
@@ -0,0 +1,132 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { existsSync, mkdtempSync, mkdirSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+
6
+ const promptsMock = vi.fn();
7
+ const forkManagerInitialize = vi.fn();
8
+ const forkManagerGetMetadata = vi.fn();
9
+ const ForkManagerCtor = vi.fn();
10
+ const loadUserConfigMock = vi.fn();
11
+ const resolveNetworkConfigMock = vi.fn();
12
+
13
+ vi.mock("prompts", () => ({ default: promptsMock }));
14
+
15
+ vi.mock("../../../fork/manager.js", () => ({
16
+ ForkManager: class {
17
+ constructor(forkPath: string) {
18
+ ForkManagerCtor(forkPath);
19
+ }
20
+ initialize = forkManagerInitialize;
21
+ getMetadata = forkManagerGetMetadata;
22
+ },
23
+ }));
24
+
25
+ vi.mock("../../../core/config.js", () => ({
26
+ loadUserConfig: loadUserConfigMock,
27
+ resolveNetworkConfig: resolveNetworkConfigMock,
28
+ }));
29
+
30
+ const { default: forkCreateCommand } = await import("../create.js");
31
+
32
+ describe("forkCreateCommand", () => {
33
+ let tmpCwd: string;
34
+ let origCwd: string;
35
+ let exitSpy: ReturnType<typeof vi.spyOn>;
36
+
37
+ beforeEach(() => {
38
+ promptsMock.mockReset();
39
+ forkManagerInitialize.mockReset().mockResolvedValue(undefined);
40
+ forkManagerGetMetadata.mockReset().mockReturnValue({
41
+ network: "testnet",
42
+ nodeUrl: "https://testnet.movementnetwork.xyz/v1",
43
+ chainId: 27,
44
+ ledgerVersion: "100",
45
+ timestamp: "12345",
46
+ epoch: "5",
47
+ blockHeight: "42",
48
+ createdAt: new Date(0).toISOString(),
49
+ });
50
+ ForkManagerCtor.mockReset();
51
+ loadUserConfigMock.mockReset().mockResolvedValue({
52
+ defaultNetwork: "testnet",
53
+ networks: { testnet: { url: "https://testnet.movementnetwork.xyz/v1", chainId: "testnet" } },
54
+ });
55
+ resolveNetworkConfigMock.mockReset().mockResolvedValue({
56
+ network: "testnet",
57
+ rpc: "https://testnet.movementnetwork.xyz/v1",
58
+ privateKey: "0x" + "1".repeat(64),
59
+ allAccounts: [],
60
+ profile: "default",
61
+ moveDir: "./move",
62
+ account: "",
63
+ namedAddresses: {},
64
+ networkConfig: { url: "https://testnet.movementnetwork.xyz/v1", chainId: "testnet" },
65
+ });
66
+
67
+ origCwd = process.cwd();
68
+ tmpCwd = mkdtempSync(join(tmpdir(), "movehat-forkcreate-"));
69
+ process.chdir(tmpCwd);
70
+ exitSpy = vi
71
+ .spyOn(process, "exit")
72
+ .mockImplementation(((code?: number) => {
73
+ throw new Error(`__test_exit_${code ?? 0}__`);
74
+ }) as never);
75
+ vi.spyOn(console, "log").mockImplementation(() => undefined);
76
+ vi.spyOn(console, "error").mockImplementation(() => undefined);
77
+ });
78
+
79
+ afterEach(() => {
80
+ process.chdir(origCwd);
81
+ if (existsSync(tmpCwd)) rmSync(tmpCwd, { recursive: true, force: true });
82
+ vi.restoreAllMocks();
83
+ });
84
+
85
+ it("happy path: initializes a fresh fork at the default path", async () => {
86
+ await forkCreateCommand({ network: "testnet" });
87
+
88
+ expect(forkManagerInitialize).toHaveBeenCalledTimes(1);
89
+ expect(forkManagerInitialize).toHaveBeenCalledWith(
90
+ "https://testnet.movementnetwork.xyz/v1",
91
+ "testnet"
92
+ );
93
+ expect(promptsMock).not.toHaveBeenCalled();
94
+ });
95
+
96
+ it("uses a custom fork name and path when provided", async () => {
97
+ const customPath = join(tmpCwd, "my-custom-fork");
98
+ await forkCreateCommand({ network: "testnet", path: customPath, name: "ignored-when-path-set" });
99
+
100
+ expect(ForkManagerCtor).toHaveBeenCalledWith(customPath);
101
+ });
102
+
103
+ it("prompts for overwrite when the fork directory already exists", async () => {
104
+ const forkPath = join(tmpCwd, ".movehat", "forks", "testnet-fork");
105
+ mkdirSync(forkPath, { recursive: true });
106
+ promptsMock.mockResolvedValueOnce({ overwrite: true });
107
+
108
+ await forkCreateCommand({ network: "testnet" });
109
+
110
+ expect(promptsMock).toHaveBeenCalledTimes(1);
111
+ expect(forkManagerInitialize).toHaveBeenCalledTimes(1);
112
+ });
113
+
114
+ it("aborts gracefully when the user declines the overwrite prompt", async () => {
115
+ const forkPath = join(tmpCwd, ".movehat", "forks", "testnet-fork");
116
+ mkdirSync(forkPath, { recursive: true });
117
+ promptsMock.mockResolvedValueOnce({ overwrite: false });
118
+
119
+ await forkCreateCommand({ network: "testnet" });
120
+
121
+ expect(forkManagerInitialize).not.toHaveBeenCalled();
122
+ expect(exitSpy).not.toHaveBeenCalled();
123
+ });
124
+
125
+ it("exits 1 when the manager's initialize throws", async () => {
126
+ forkManagerInitialize.mockRejectedValueOnce(new Error("upstream is unreachable"));
127
+
128
+ await expect(forkCreateCommand({ network: "testnet" })).rejects.toThrow(
129
+ "__test_exit_1__"
130
+ );
131
+ });
132
+ });
@@ -0,0 +1,104 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+
3
+ const forkManagerLoad = vi.fn();
4
+ const forkManagerFundAccount = vi.fn();
5
+ const forkManagerGetResource = vi.fn();
6
+ const ForkManagerCtor = vi.fn();
7
+
8
+ vi.mock("../../../fork/manager.js", () => ({
9
+ ForkManager: class {
10
+ constructor(forkPath: string) {
11
+ ForkManagerCtor(forkPath);
12
+ }
13
+ load = forkManagerLoad;
14
+ fundAccount = forkManagerFundAccount;
15
+ getResource = forkManagerGetResource;
16
+ },
17
+ }));
18
+
19
+ const { default: forkFundCommand } = await import("../fund.js");
20
+
21
+ describe("forkFundCommand", () => {
22
+ let exitSpy: ReturnType<typeof vi.spyOn>;
23
+
24
+ beforeEach(() => {
25
+ forkManagerLoad.mockReset();
26
+ forkManagerFundAccount.mockReset().mockResolvedValue(undefined);
27
+ forkManagerGetResource.mockReset().mockResolvedValue({
28
+ coin: { value: "1000" },
29
+ });
30
+ ForkManagerCtor.mockReset();
31
+ exitSpy = vi
32
+ .spyOn(process, "exit")
33
+ .mockImplementation(((code?: number) => {
34
+ throw new Error(`__test_exit_${code ?? 0}__`);
35
+ }) as never);
36
+ vi.spyOn(console, "log").mockImplementation(() => undefined);
37
+ vi.spyOn(console, "error").mockImplementation(() => undefined);
38
+ });
39
+
40
+ afterEach(() => {
41
+ vi.restoreAllMocks();
42
+ });
43
+
44
+ it("exits 1 when --account is missing", async () => {
45
+ await expect(
46
+ forkFundCommand({ account: "", amount: "100" } as never)
47
+ ).rejects.toThrow("__test_exit_1__");
48
+ expect(forkManagerFundAccount).not.toHaveBeenCalled();
49
+ });
50
+
51
+ it("exits 1 when --amount is missing", async () => {
52
+ await expect(
53
+ forkFundCommand({ account: "0xabc", amount: "" } as never)
54
+ ).rejects.toThrow("__test_exit_1__");
55
+ expect(forkManagerFundAccount).not.toHaveBeenCalled();
56
+ });
57
+
58
+ it("exits 1 when --amount is not a positive integer", async () => {
59
+ await expect(
60
+ forkFundCommand({ account: "0xabc", amount: "abc" } as never)
61
+ ).rejects.toThrow("__test_exit_1__");
62
+ await expect(
63
+ forkFundCommand({ account: "0xabc", amount: "-5" } as never)
64
+ ).rejects.toThrow("__test_exit_1__");
65
+ });
66
+
67
+ it("happy path: loads fork, funds the account, prints new balance", async () => {
68
+ await forkFundCommand({
69
+ account: "0xabc",
70
+ amount: "1000",
71
+ fork: "/tmp/fork",
72
+ } as never);
73
+
74
+ expect(forkManagerLoad).toHaveBeenCalledTimes(1);
75
+ expect(forkManagerFundAccount).toHaveBeenCalledWith(
76
+ "0xabc",
77
+ 1000,
78
+ "0x1::aptos_coin::AptosCoin"
79
+ );
80
+ expect(forkManagerGetResource).toHaveBeenCalled();
81
+ });
82
+
83
+ it("respects --coinType when provided", async () => {
84
+ await forkFundCommand({
85
+ account: "0xabc",
86
+ amount: "1000",
87
+ coinType: "0x99::custom::Coin",
88
+ } as never);
89
+
90
+ expect(forkManagerFundAccount).toHaveBeenCalledWith(
91
+ "0xabc",
92
+ 1000,
93
+ "0x99::custom::Coin"
94
+ );
95
+ });
96
+
97
+ it("exits 1 when fundAccount throws", async () => {
98
+ forkManagerFundAccount.mockRejectedValueOnce(new Error("fund failed"));
99
+
100
+ await expect(
101
+ forkFundCommand({ account: "0xabc", amount: "1000" } as never)
102
+ ).rejects.toThrow("__test_exit_1__");
103
+ });
104
+ });
@@ -0,0 +1,139 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { existsSync, mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+
6
+ const storageExists = vi.fn();
7
+ const storageLoadMetadata = vi.fn();
8
+ const storageListAccounts = vi.fn();
9
+
10
+ vi.mock("../../../fork/storage.js", () => ({
11
+ ForkStorage: class {
12
+ exists = storageExists;
13
+ loadMetadata = storageLoadMetadata;
14
+ listAccounts = storageListAccounts;
15
+ },
16
+ }));
17
+
18
+ const { default: forkListCommand } = await import("../list.js");
19
+
20
+ describe("forkListCommand", () => {
21
+ let tmpCwd: string;
22
+ let origCwd: string;
23
+ let exitSpy: ReturnType<typeof vi.spyOn>;
24
+ let logSpy: ReturnType<typeof vi.spyOn>;
25
+
26
+ beforeEach(() => {
27
+ storageExists.mockReset();
28
+ storageLoadMetadata.mockReset();
29
+ storageListAccounts.mockReset();
30
+ origCwd = process.cwd();
31
+ tmpCwd = mkdtempSync(join(tmpdir(), "movehat-forklist-"));
32
+ process.chdir(tmpCwd);
33
+ exitSpy = vi
34
+ .spyOn(process, "exit")
35
+ .mockImplementation(((code?: number) => {
36
+ throw new Error(`__test_exit_${code ?? 0}__`);
37
+ }) as never);
38
+ logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
39
+ vi.spyOn(console, "error").mockImplementation(() => undefined);
40
+ });
41
+
42
+ afterEach(() => {
43
+ process.chdir(origCwd);
44
+ if (existsSync(tmpCwd)) rmSync(tmpCwd, { recursive: true, force: true });
45
+ vi.restoreAllMocks();
46
+ });
47
+
48
+ it("prints 'no forks found' when the forks dir doesn't exist", async () => {
49
+ await forkListCommand();
50
+
51
+ const printed = logSpy.mock.calls.flat().join(" ");
52
+ expect(printed).toMatch(/No forks found/i);
53
+ expect(storageExists).not.toHaveBeenCalled();
54
+ });
55
+
56
+ it("prints 'no forks found' when the forks dir is empty", async () => {
57
+ mkdirSync(join(tmpCwd, ".movehat", "forks"), { recursive: true });
58
+ await forkListCommand();
59
+
60
+ const printed = logSpy.mock.calls.flat().join(" ");
61
+ expect(printed).toMatch(/No forks found/i);
62
+ });
63
+
64
+ it("lists a single valid fork in a table", async () => {
65
+ mkdirSync(join(tmpCwd, ".movehat", "forks", "testnet-fork"), { recursive: true });
66
+ storageExists.mockReturnValue(true);
67
+ storageLoadMetadata.mockReturnValue({
68
+ network: "testnet",
69
+ nodeUrl: "https://testnet.movementnetwork.xyz/v1",
70
+ chainId: 27,
71
+ ledgerVersion: "100",
72
+ timestamp: "12345",
73
+ epoch: "5",
74
+ blockHeight: "42",
75
+ createdAt: new Date(1700000000000).toISOString(),
76
+ });
77
+ storageListAccounts.mockReturnValue(["0xabc", "0xdef"]);
78
+
79
+ await forkListCommand();
80
+
81
+ const printed = logSpy.mock.calls.flat().join(" ");
82
+ expect(printed).toMatch(/testnet-fork/);
83
+ expect(printed).toMatch(/testnet/);
84
+ });
85
+
86
+ it("flags forks with invalid/missing metadata gracefully", async () => {
87
+ mkdirSync(join(tmpCwd, ".movehat", "forks", "broken-fork"), { recursive: true });
88
+ storageExists.mockReturnValue(false);
89
+
90
+ await forkListCommand();
91
+
92
+ const printed = logSpy.mock.calls.flat().join(" ");
93
+ expect(printed).toMatch(/broken-fork/);
94
+ expect(printed).toMatch(/invalid/);
95
+ });
96
+
97
+ it("handles metadata-load errors per-fork without aborting the list", async () => {
98
+ mkdirSync(join(tmpCwd, ".movehat", "forks", "fork-a"), { recursive: true });
99
+ mkdirSync(join(tmpCwd, ".movehat", "forks", "fork-b"), { recursive: true });
100
+
101
+ // First fork: exists() throws on metadata load; second: ok.
102
+ let call = 0;
103
+ storageExists.mockImplementation(() => {
104
+ call++;
105
+ if (call === 1) throw new Error("metadata corrupt");
106
+ return true;
107
+ });
108
+ storageLoadMetadata.mockReturnValue({
109
+ network: "testnet",
110
+ nodeUrl: "url",
111
+ chainId: 27,
112
+ ledgerVersion: "100",
113
+ timestamp: "0",
114
+ epoch: "0",
115
+ blockHeight: "0",
116
+ createdAt: new Date(0).toISOString(),
117
+ });
118
+ storageListAccounts.mockReturnValue([]);
119
+
120
+ await forkListCommand();
121
+
122
+ const printed = logSpy.mock.calls.flat().join(" ");
123
+ expect(printed).toMatch(/fork-a/);
124
+ expect(printed).toMatch(/error/);
125
+ expect(printed).toMatch(/fork-b/);
126
+ });
127
+
128
+ it("skips non-directory entries in the forks dir", async () => {
129
+ mkdirSync(join(tmpCwd, ".movehat", "forks"), { recursive: true });
130
+ // Plant a stray file at the forks-dir level.
131
+ writeFileSync(join(tmpCwd, ".movehat", "forks", "not-a-fork.txt"), "x");
132
+
133
+ // No actual fork subdirs — should still hit the "0 forks" branch.
134
+ await forkListCommand();
135
+
136
+ const printed = logSpy.mock.calls.flat().join(" ");
137
+ expect(printed).toMatch(/No forks found/i);
138
+ });
139
+ });