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
@@ -0,0 +1,37 @@
1
+ import { CliExecutionError } from '../errors.js';
2
+ import { defaultChildProcessAdapter, } from './childProcessAdapter.js';
3
+ import { redactSecrets } from './redact.js';
4
+ export { redactSecrets } from './redact.js';
5
+ const STDOUT_PREVIEW_CHARS = 2000;
6
+ /**
7
+ * Spawns a CLI command through the injectable adapter, redacts well-known
8
+ * secret shapes from stdout and stderr before returning, and throws
9
+ * `CliExecutionError` (with already-redacted payloads) on non-zero exits.
10
+ *
11
+ * Callers that need to inspect raw output should set `throwOnNonZeroExit:false`
12
+ * and consume the returned `RunResult` directly — fields are still redacted.
13
+ *
14
+ * Pass `input.inheritStdio: true` for interactive commands (mocha, tsx,
15
+ * package managers) where the user expects to see live output. Under that
16
+ * flag, `stdout` and `stderr` in the returned `RunResult` are empty strings
17
+ * (and so is `stdoutPreview` on any `CliExecutionError`), since the child
18
+ * writes directly to the terminal rather than to a captured buffer.
19
+ */
20
+ export async function runCli(input, options = {}) {
21
+ const adapter = options.adapter ?? defaultChildProcessAdapter;
22
+ const throwOnNonZeroExit = options.throwOnNonZeroExit ?? true;
23
+ const raw = await adapter.run(input);
24
+ const result = {
25
+ exitCode: raw.exitCode,
26
+ stdout: redactSecrets(raw.stdout),
27
+ stderr: redactSecrets(raw.stderr),
28
+ };
29
+ if (raw.signal) {
30
+ result.signal = raw.signal;
31
+ }
32
+ if (result.exitCode !== 0 && throwOnNonZeroExit) {
33
+ throw new CliExecutionError(`Command failed with exit code ${result.exitCode}: ${input.command}`, input.command, input.args, result.exitCode, result.stderr, result.stdout.slice(0, STDOUT_PREVIEW_CHARS));
34
+ }
35
+ return result;
36
+ }
37
+ //# sourceMappingURL=runCli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runCli.js","sourceRoot":"","sources":["../../src/utils/runCli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EACL,0BAA0B,GAI3B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,oBAAoB,GAAG,IAAI,CAAC;AASlC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,KAAe,EACf,UAAyB,EAAE;IAE3B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,0BAA0B,CAAC;IAC9D,MAAM,kBAAkB,GAAG,OAAO,CAAC,kBAAkB,IAAI,IAAI,CAAC;IAE9D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,MAAM,GAAc;QACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC;QACjC,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC;KAClC,CAAC;IACF,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,IAAI,kBAAkB,EAAE,CAAC;QAChD,MAAM,IAAI,iBAAiB,CACzB,iCAAiC,MAAM,CAAC,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE,EACpE,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,IAAI,EACV,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAC7C,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "movehat",
3
- "version": "0.1.9",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
- "description": "Hardhat-like development framework for Movement L1 and Aptos Move smart contracts",
5
+ "description": "Hardhat-like development framework for Movement L1 smart contracts",
6
6
  "bin": {
7
7
  "movehat": "./bin/movehat.js"
8
8
  },
@@ -21,6 +21,12 @@
21
21
  "copy-templates": "cp -r src/templates dist/",
22
22
  "dev": "tsc --watch",
23
23
  "clean": "rm -rf dist",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "test:coverage": "vitest run --coverage",
27
+ "test:integration": "vitest run --config vitest.integration.config.ts",
28
+ "docs:api": "typedoc && node scripts/postprocess-typedoc.mjs",
29
+ "bench": "cd ../../examples/counter-example && tsx ../../packages/movehat/bench/fork.bench.ts",
24
30
  "prepublishOnly": "npm run build"
25
31
  },
26
32
  "files": [
@@ -38,7 +44,6 @@
38
44
  },
39
45
  "keywords": [
40
46
  "move",
41
- "aptos",
42
47
  "movement",
43
48
  "blockchain",
44
49
  "smart-contracts",
@@ -68,6 +73,11 @@
68
73
  "@types/js-yaml": "^4.0.9",
69
74
  "@types/node": "^24.10.1",
70
75
  "@types/prompts": "^2.4.9",
71
- "typescript": "^5.9.3"
76
+ "@vitest/coverage-v8": "^4.0.16",
77
+ "memfs": "^4.51.1",
78
+ "typedoc": "^0.28.19",
79
+ "typedoc-plugin-markdown": "^4.11.0",
80
+ "typescript": "^5.9.3",
81
+ "vitest": "^4.0.16"
72
82
  }
73
83
  }
@@ -0,0 +1,429 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import {
3
+ existsSync,
4
+ mkdirSync,
5
+ mkdtempSync,
6
+ readFileSync,
7
+ rmSync,
8
+ writeFileSync,
9
+ } from "node:fs";
10
+ import { tmpdir } from "node:os";
11
+ import { dirname, join } from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+ import { createRequire } from "node:module";
14
+ import { spawn } from "node:child_process";
15
+ import * as yaml from "js-yaml";
16
+ import { CliExecutionError } from "../errors.js";
17
+ import { initRuntime } from "../runtime.js";
18
+ import { Publisher } from "../core/Publisher.js";
19
+ import type { ChildProcessAdapter, RunInput, RunResult } from "../utils/childProcessAdapter.js";
20
+
21
+ const __dirname = dirname(fileURLToPath(import.meta.url));
22
+ const require = createRequire(import.meta.url);
23
+
24
+ /**
25
+ * Guards against the bug-#43 leak path: when `movement move publish`
26
+ * echoes `ed25519-priv-…` material in stdout/stderr, neither the
27
+ * thrown error nor anything reaching `console.error` may carry the
28
+ * raw key. The redaction is structurally guaranteed by runCli today
29
+ * — these tests make the guarantee *directly* asserted so a future
30
+ * PR adding a non-runCli code path can't silently re-leak.
31
+ */
32
+ describe("runtime.deployContract — secret redaction", () => {
33
+ let tmpHome: string;
34
+ let tmpCwd: string;
35
+ let origHome: string | undefined;
36
+ let origCwd: string;
37
+
38
+ beforeEach(() => {
39
+ tmpHome = mkdtempSync(join(tmpdir(), "movehat-test-home-"));
40
+ tmpCwd = mkdtempSync(join(tmpdir(), "movehat-test-cwd-"));
41
+
42
+ // Minimal movehat.config.js — testnet with no `accounts` means the
43
+ // auto-generated deterministic test key is used (config.ts:147-155).
44
+ writeFileSync(
45
+ join(tmpCwd, "movehat.config.js"),
46
+ `export default {
47
+ defaultNetwork: "testnet",
48
+ networks: {
49
+ testnet: {
50
+ url: "https://testnet.movementnetwork.xyz/v1",
51
+ chainId: "testnet"
52
+ }
53
+ }
54
+ };
55
+ `
56
+ );
57
+
58
+ // Minimal Move package layout. `extractNamedAddresses` reads
59
+ // <moveDir>/sources/*.move; the empty file produces an empty Set.
60
+ const moveDir = join(tmpCwd, "move");
61
+ mkdirSync(join(moveDir, "sources"), { recursive: true });
62
+ writeFileSync(
63
+ join(moveDir, "Move.toml"),
64
+ `[package]
65
+ name = "dummy"
66
+ version = "0.0.1"
67
+
68
+ [addresses]
69
+ `
70
+ );
71
+ writeFileSync(join(moveDir, "sources", "dummy.move"), "// intentionally empty\n");
72
+
73
+ origHome = process.env.HOME;
74
+ process.env.HOME = tmpHome;
75
+ origCwd = process.cwd();
76
+ process.chdir(tmpCwd);
77
+ });
78
+
79
+ afterEach(() => {
80
+ try {
81
+ process.chdir(origCwd);
82
+ } finally {
83
+ if (origHome === undefined) delete process.env.HOME;
84
+ else process.env.HOME = origHome;
85
+ if (existsSync(tmpHome)) rmSync(tmpHome, { recursive: true, force: true });
86
+ if (existsSync(tmpCwd)) rmSync(tmpCwd, { recursive: true, force: true });
87
+ }
88
+ });
89
+
90
+ function makeAdapter(steps: { build: RunResult; publish: RunResult }): {
91
+ adapter: ChildProcessAdapter;
92
+ calls: RunInput[];
93
+ } {
94
+ const calls: RunInput[] = [];
95
+ const adapter: ChildProcessAdapter = {
96
+ async run(input) {
97
+ calls.push(input);
98
+ // The args layout is `["move", "build" | "publish", ...rest]`.
99
+ if (input.args[1] === "build") return steps.build;
100
+ if (input.args[1] === "publish") return steps.publish;
101
+ throw new Error(`unexpected movement subcommand: ${input.args[1]}`);
102
+ },
103
+ spawn() {
104
+ throw new Error("spawn not used in deployContract tests");
105
+ },
106
+ };
107
+ return { adapter, calls };
108
+ }
109
+
110
+ it("leak path #2 — rethrown error has redacted stderr (no raw ed25519-priv-)", async () => {
111
+ const rawKey = "ed25519-priv-0x" + "a".repeat(64);
112
+ const { adapter, calls } = makeAdapter({
113
+ build: { exitCode: 0, stdout: "build ok", stderr: "" },
114
+ publish: { exitCode: 1, stdout: "", stderr: `Movement publish failed: ${rawKey}` },
115
+ });
116
+
117
+ const runtime = await initRuntime();
118
+
119
+ let captured: unknown;
120
+ try {
121
+ await runtime.deployContract("mymodule", { adapter });
122
+ } catch (err) {
123
+ captured = err;
124
+ }
125
+
126
+ expect(captured).toBeInstanceOf(CliExecutionError);
127
+ const err = captured as CliExecutionError;
128
+ expect(err.stderr).toContain("***REDACTED***");
129
+ expect(err.stderr).not.toContain("ed25519-priv-");
130
+ expect(err.stderr).not.toContain(rawKey);
131
+
132
+ // Pin the call shape: build then publish, args reach the adapter un-quoted.
133
+ // A previous regression (shell-escape mismatch fixed in 511fd95) survived
134
+ // unit tests because no assertion checked what landed in `args`.
135
+ expect(calls).toHaveLength(2);
136
+ const [build, publish] = calls;
137
+ if (!build || !publish) throw new Error("expected 2 captured calls");
138
+ expect(build.command).toBe("movement");
139
+ expect(build.args.slice(0, 2)).toEqual(["move", "build"]);
140
+ expect(publish.args.slice(0, 2)).toEqual(["move", "publish"]);
141
+ for (const arg of [...build.args, ...publish.args]) {
142
+ expect(arg.startsWith("'")).toBe(false);
143
+ expect(arg.endsWith("'")).toBe(false);
144
+ }
145
+
146
+ // Bonus: deployContract's finally block must have restored / removed the
147
+ // movement config file. If a future refactor breaks the finally, this
148
+ // assertion fires before any real damage.
149
+ expect(existsSync(join(tmpHome, ".aptos", "config.yaml"))).toBe(false);
150
+ });
151
+
152
+ it("two concurrent deploys do not corrupt ~/.aptos/config.yaml (#37)", async () => {
153
+ // Pre-fix #37: both deploys overwrote ~/.aptos/config.yaml with the
154
+ // SAME profile name ("default" by default), then both restored
155
+ // independently. The second deploy's restore would overwrite the
156
+ // first's profile mid-publish → potential cross-contamination of
157
+ // private keys / accounts. Post-fix: each deploy uses a unique
158
+ // movehat-deploy-<uuid> profile name and only deletes its own key
159
+ // on cleanup. The user's other profiles never get touched.
160
+ //
161
+ // The mutex is what makes this safe — without it, the
162
+ // read-modify-write cycles would race and silently drop a profile.
163
+
164
+ // Seed the yaml with an unrelated user profile that MUST survive.
165
+ const aptosDir = join(tmpHome, ".aptos");
166
+ mkdirSync(aptosDir, { recursive: true });
167
+ const preExisting = {
168
+ profiles: {
169
+ user_main: {
170
+ private_key: "0x" + "1".repeat(64),
171
+ public_key: "0x" + "2".repeat(64),
172
+ account: "0x" + "3".repeat(64),
173
+ rest_url: "https://example.invalid/v1",
174
+ },
175
+ },
176
+ };
177
+ const configPath = join(aptosDir, "config.yaml");
178
+ writeFileSync(configPath, yaml.dump(preExisting), { mode: 0o600 });
179
+
180
+ // Set up two Publisher instances with fake adapters that record their
181
+ // own --profile argument and inject a small delay on publish so the
182
+ // critical sections overlap.
183
+ function makeDelayedAdapter(label: string): {
184
+ adapter: ChildProcessAdapter;
185
+ captured: { publishCall?: RunInput };
186
+ } {
187
+ const captured: { publishCall?: RunInput } = {};
188
+ const adapter: ChildProcessAdapter = {
189
+ async run(input) {
190
+ if (input.args[1] === "build") {
191
+ return { exitCode: 0, stdout: `built ${label}`, stderr: "" };
192
+ }
193
+ if (input.args[1] === "publish") {
194
+ captured.publishCall = input;
195
+ // Hold the lock-protected critical section open long enough
196
+ // for the other deploy's addProfile to compete.
197
+ await new Promise((r) => setTimeout(r, 30));
198
+ return {
199
+ exitCode: 0,
200
+ stdout: `Transaction hash: 0x${"d".repeat(64)}`,
201
+ stderr: "",
202
+ };
203
+ }
204
+ throw new Error(`unexpected: ${input.args[1]}`);
205
+ },
206
+ spawn() {
207
+ throw new Error("spawn not used");
208
+ },
209
+ };
210
+ return { adapter, captured };
211
+ }
212
+
213
+ const a = makeDelayedAdapter("A");
214
+ const b = makeDelayedAdapter("B");
215
+
216
+ // Build a minimal config + account once via initRuntime, then call
217
+ // Publisher directly (bypasses the loadDeployment cache that would
218
+ // throw on the second deploy if both used moduleName "test").
219
+ const runtime = await initRuntime();
220
+ const { config, account } = runtime;
221
+
222
+ await Promise.all([
223
+ new Publisher({ adapter: a.adapter }).deploy({
224
+ moduleName: "concurrent_a",
225
+ config,
226
+ account,
227
+ packageDir: join(tmpCwd, "move"),
228
+ }),
229
+ new Publisher({ adapter: b.adapter }).deploy({
230
+ moduleName: "concurrent_b",
231
+ config,
232
+ account,
233
+ packageDir: join(tmpCwd, "move"),
234
+ }),
235
+ ]);
236
+
237
+ // Both publish calls captured distinct --profile args.
238
+ const argsA = a.captured.publishCall!.args;
239
+ const argsB = b.captured.publishCall!.args;
240
+ const profileArgA = argsA[argsA.indexOf("--profile") + 1];
241
+ const profileArgB = argsB[argsB.indexOf("--profile") + 1];
242
+ expect(profileArgA).toMatch(/^movehat-deploy-/);
243
+ expect(profileArgB).toMatch(/^movehat-deploy-/);
244
+ expect(profileArgA).not.toBe(profileArgB);
245
+
246
+ // After both deploys finish, ~/.aptos/config.yaml contains the
247
+ // user's original profile and zero movehat-deploy-* profiles.
248
+ const finalYaml: any = yaml.load(readFileSync(configPath, "utf8"));
249
+ expect(finalYaml.profiles).toBeDefined();
250
+ expect(Object.keys(finalYaml.profiles)).toEqual(["user_main"]);
251
+ expect(finalYaml.profiles.user_main.private_key).toBe(
252
+ preExisting.profiles.user_main.private_key
253
+ );
254
+ });
255
+
256
+ it("SIGINT mid-deploy cleans the profile from ~/.aptos/config.yaml (#36)", async () => {
257
+ // Pre-fix #36: between the yaml write (private key persisted) and the
258
+ // finally block, a SIGINT would skip cleanup and leave the user's
259
+ // private key sitting in ~/.aptos/config.yaml at mode 0o600.
260
+ // Post-fix: a sync signal handler runs synchronously before exit,
261
+ // removing the deploy's unique profile from the yaml.
262
+ //
263
+ // This test spawns a child process running a harness that drives
264
+ // Publisher.deploy() with a 3-second-delayed publish, then sends
265
+ // SIGINT mid-flight. Vitest's own process is unaffected because
266
+ // the SIGINT goes to the child.
267
+
268
+ // Seed an unrelated user profile that MUST survive.
269
+ const aptosDir = join(tmpHome, ".aptos");
270
+ mkdirSync(aptosDir, { recursive: true });
271
+ const configPath = join(aptosDir, "config.yaml");
272
+ writeFileSync(
273
+ configPath,
274
+ yaml.dump({
275
+ profiles: {
276
+ user_main: {
277
+ private_key: "0x" + "a".repeat(64),
278
+ public_key: "0x" + "b".repeat(64),
279
+ account: "0x" + "c".repeat(64),
280
+ rest_url: "https://example.invalid/v1",
281
+ },
282
+ },
283
+ }),
284
+ { mode: 0o600 }
285
+ );
286
+
287
+ const harnessPath = join(__dirname, "fixtures", "sigint-deploy-harness.ts");
288
+ // Resolve tsx's CLI binary by absolute path — the test's tmp cwd has
289
+ // no node_modules, so a bare `tsx` import would fail to resolve.
290
+ // `require.resolve("tsx")` returns the package's main (dist/loader.mjs);
291
+ // the binary is two levels up from there, in `<root>/dist/cli.mjs`
292
+ // (same trick `commands/run.ts:49-53` uses).
293
+ const tsxMain = require.resolve("tsx");
294
+ const tsxCliPath = join(dirname(dirname(tsxMain)), "dist", "cli.mjs");
295
+ const child = spawn(
296
+ process.execPath,
297
+ [tsxCliPath, harnessPath],
298
+ {
299
+ env: { ...process.env, HOME: tmpHome },
300
+ cwd: tmpCwd,
301
+ stdio: ["ignore", "pipe", "pipe"],
302
+ }
303
+ );
304
+
305
+ // Wait for the harness to announce its unique profile name via stdout
306
+ // (it writes a JSON line `{"profile":"movehat-deploy-XXXX"}` just
307
+ // before entering the slow publish step).
308
+ let announced: string | undefined;
309
+ let stdoutBuf = "";
310
+ let stderrBuf = "";
311
+ child.stdout?.on("data", (chunk: Buffer) => {
312
+ stdoutBuf += chunk.toString();
313
+ for (const line of stdoutBuf.split("\n")) {
314
+ const trimmed = line.trim();
315
+ if (!trimmed.startsWith("{")) continue;
316
+ try {
317
+ const parsed = JSON.parse(trimmed);
318
+ if (typeof parsed.profile === "string") announced = parsed.profile;
319
+ } catch {
320
+ /* not a JSON line we care about */
321
+ }
322
+ }
323
+ });
324
+ child.stderr?.on("data", (c: Buffer) => (stderrBuf += c.toString()));
325
+
326
+ // Poll until the harness has announced OR 8s timeout (the import +
327
+ // SDK initialization can take a few seconds in CI/cold-start).
328
+ const start = Date.now();
329
+ while (!announced && Date.now() - start < 8000) {
330
+ await new Promise((r) => setTimeout(r, 100));
331
+ }
332
+
333
+ if (!announced) {
334
+ child.kill("SIGKILL");
335
+ throw new Error(
336
+ `harness never announced profile in 8s.\n` +
337
+ `stdout so far:\n${stdoutBuf}\n---\nstderr so far:\n${stderrBuf}`
338
+ );
339
+ }
340
+
341
+ expect(announced).toMatch(/^movehat-deploy-/);
342
+
343
+ // Deliver SIGINT mid-publish and wait for the harness to exit.
344
+ child.kill("SIGINT");
345
+ const exitCode = await new Promise<number | null>((resolve) => {
346
+ child.on("exit", (code) => resolve(code));
347
+ });
348
+ expect(exitCode).toBe(130);
349
+
350
+ // The yaml on disk contains the user's original profile and NO
351
+ // movehat-deploy-* leftovers.
352
+ expect(existsSync(configPath)).toBe(true);
353
+ const finalYaml: any = yaml.load(readFileSync(configPath, "utf8"));
354
+ expect(finalYaml.profiles).toBeDefined();
355
+ expect(Object.keys(finalYaml.profiles).sort()).toEqual(["user_main"]);
356
+ expect(finalYaml.profiles.user_main.private_key).toBe("0x" + "a".repeat(64));
357
+ }, 15000);
358
+
359
+ it("does not mutate Move.toml during deploy (#38)", async () => {
360
+ // Pre-fix #38: deployContract overwrote every entry under [addresses]
361
+ // with the deployer address, then relied on `finally` to restore.
362
+ // Post-fix: Move.toml is never touched — `--named-addresses` carries
363
+ // the overrides on the CLI line for both build and publish.
364
+ const moveTomlPath = join(tmpCwd, "move", "Move.toml");
365
+ const moveTomlContent = `[package]
366
+ name = "dummy"
367
+ version = "0.0.1"
368
+
369
+ [addresses]
370
+ counter = "0x42"
371
+ greeting = "0xcafe"
372
+ `;
373
+ writeFileSync(moveTomlPath, moveTomlContent);
374
+
375
+ // Move source that references "counter" so extractNamedAddresses picks
376
+ // it up — otherwise the --named-addresses arg is empty and the test
377
+ // is uninteresting.
378
+ writeFileSync(
379
+ join(tmpCwd, "move", "sources", "dummy.move"),
380
+ "module counter::dummy { }\n"
381
+ );
382
+
383
+ const { adapter } = makeAdapter({
384
+ build: { exitCode: 0, stdout: "build ok", stderr: "" },
385
+ publish: {
386
+ exitCode: 0,
387
+ stdout: "Transaction hash: 0x" + "c".repeat(64),
388
+ stderr: "",
389
+ },
390
+ });
391
+
392
+ const runtime = await initRuntime();
393
+ await runtime.deployContract("counter", { adapter });
394
+
395
+ const after = readFileSync(moveTomlPath, "utf8");
396
+ expect(after).toBe(moveTomlContent);
397
+ });
398
+
399
+ it("leak path #1 — console.error on a noisy-but-successful publish never sees raw key", async () => {
400
+ const rawKey = "ed25519-priv-0x" + "a".repeat(64);
401
+ const { adapter } = makeAdapter({
402
+ build: { exitCode: 0, stdout: "build ok", stderr: "" },
403
+ // Publish succeeds (exitCode 0) but emits a stderr line containing the key.
404
+ publish: {
405
+ exitCode: 0,
406
+ stdout: "Transaction hash: 0x" + "b".repeat(64),
407
+ stderr: `warning: ${rawKey}`,
408
+ },
409
+ });
410
+
411
+ const errSpy = vi.spyOn(console, "error").mockImplementation(() => {});
412
+ const logSpy = vi.spyOn(console, "log").mockImplementation(() => {});
413
+
414
+ try {
415
+ const runtime = await initRuntime();
416
+ await runtime.deployContract("mymodule", { adapter });
417
+
418
+ const allErr = errSpy.mock.calls.flat().join("\n");
419
+ const allLog = logSpy.mock.calls.flat().join("\n");
420
+ expect(allErr).not.toContain("ed25519-priv-");
421
+ expect(allErr).not.toContain(rawKey);
422
+ expect(allLog).not.toContain("ed25519-priv-");
423
+ expect(allLog).not.toContain(rawKey);
424
+ } finally {
425
+ errSpy.mockRestore();
426
+ logSpy.mockRestore();
427
+ }
428
+ });
429
+ });
@@ -0,0 +1,84 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { ModuleAlreadyDeployedError } from '../errors.js';
3
+
4
+ describe('ModuleAlreadyDeployedError', () => {
5
+ it('should create error with all properties', () => {
6
+ const error = new ModuleAlreadyDeployedError(
7
+ 'Module "counter" is already deployed',
8
+ 'counter',
9
+ 'testnet',
10
+ '0x1234',
11
+ 1704985623564,
12
+ '0xabcd'
13
+ );
14
+
15
+ expect(error).toBeInstanceOf(Error);
16
+ expect(error).toBeInstanceOf(ModuleAlreadyDeployedError);
17
+ expect(error.name).toBe('ModuleAlreadyDeployedError');
18
+ expect(error.message).toBe('Module "counter" is already deployed');
19
+ expect(error.moduleName).toBe('counter');
20
+ expect(error.network).toBe('testnet');
21
+ expect(error.address).toBe('0x1234');
22
+ expect(error.timestamp).toBe(1704985623564);
23
+ expect(error.txHash).toBe('0xabcd');
24
+ });
25
+
26
+ it('should work without optional txHash', () => {
27
+ const error = new ModuleAlreadyDeployedError(
28
+ 'Module already deployed',
29
+ 'token',
30
+ 'mainnet',
31
+ '0x5678',
32
+ 1704985623564
33
+ );
34
+
35
+ expect(error.moduleName).toBe('token');
36
+ expect(error.network).toBe('mainnet');
37
+ expect(error.txHash).toBeUndefined();
38
+ });
39
+
40
+ it('should have proper stack trace', () => {
41
+ const error = new ModuleAlreadyDeployedError(
42
+ 'Test error',
43
+ 'test',
44
+ 'local',
45
+ '0x0',
46
+ Date.now()
47
+ );
48
+
49
+ expect(error.stack).toBeDefined();
50
+ expect(error.stack).toContain('ModuleAlreadyDeployedError');
51
+ });
52
+
53
+ it('should be catchable as Error', () => {
54
+ const throwError = () => {
55
+ throw new ModuleAlreadyDeployedError(
56
+ 'Test',
57
+ 'module',
58
+ 'testnet',
59
+ '0x1',
60
+ Date.now()
61
+ );
62
+ };
63
+
64
+ expect(throwError).toThrow(Error);
65
+ expect(throwError).toThrow(ModuleAlreadyDeployedError);
66
+ });
67
+
68
+ it('should allow instanceof checks', () => {
69
+ try {
70
+ throw new ModuleAlreadyDeployedError(
71
+ 'Test',
72
+ 'module',
73
+ 'testnet',
74
+ '0x1',
75
+ Date.now()
76
+ );
77
+ } catch (e) {
78
+ expect(e instanceof ModuleAlreadyDeployedError).toBe(true);
79
+ if (e instanceof ModuleAlreadyDeployedError) {
80
+ expect(e.moduleName).toBe('module');
81
+ }
82
+ }
83
+ });
84
+ });