movehat 0.1.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/__tests__/deployContract.test.d.ts +2 -0
- package/dist/__tests__/deployContract.test.d.ts.map +1 -0
- package/dist/__tests__/deployContract.test.js +368 -0
- package/dist/__tests__/deployContract.test.js.map +1 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +46 -0
- package/dist/__tests__/errors.test.js.map +1 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts +24 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.d.ts.map +1 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.js +82 -0
- package/dist/__tests__/fixtures/sigint-deploy-harness.js.map +1 -0
- package/dist/__tests__/fork/api.test.d.ts +2 -0
- package/dist/__tests__/fork/api.test.d.ts.map +1 -0
- package/dist/__tests__/fork/api.test.js +110 -0
- package/dist/__tests__/fork/api.test.js.map +1 -0
- package/dist/__tests__/harness/Harness.createLive.test.d.ts +2 -0
- package/dist/__tests__/harness/Harness.createLive.test.d.ts.map +1 -0
- package/dist/__tests__/harness/Harness.createLive.test.js +53 -0
- package/dist/__tests__/harness/Harness.createLive.test.js.map +1 -0
- package/dist/__tests__/harness/Harness.proxy.test.d.ts +2 -0
- package/dist/__tests__/harness/Harness.proxy.test.d.ts.map +1 -0
- package/dist/__tests__/harness/Harness.proxy.test.js +93 -0
- package/dist/__tests__/harness/Harness.proxy.test.js.map +1 -0
- package/dist/__tests__/harness/_fixture.d.ts +54 -0
- package/dist/__tests__/harness/_fixture.d.ts.map +1 -0
- package/dist/__tests__/harness/_fixture.js +69 -0
- package/dist/__tests__/harness/_fixture.js.map +1 -0
- package/dist/__tests__/harness/codeObject.deploy.test.d.ts +2 -0
- package/dist/__tests__/harness/codeObject.deploy.test.d.ts.map +1 -0
- package/dist/__tests__/harness/codeObject.deploy.test.js +288 -0
- package/dist/__tests__/harness/codeObject.deploy.test.js.map +1 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.d.ts +2 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.d.ts.map +1 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.js +138 -0
- package/dist/__tests__/harness/codeObject.upgrade.test.js.map +1 -0
- package/dist/__tests__/harness/script.test.d.ts +2 -0
- package/dist/__tests__/harness/script.test.d.ts.map +1 -0
- package/dist/__tests__/harness/script.test.js +219 -0
- package/dist/__tests__/harness/script.test.js.map +1 -0
- package/dist/__tests__/harness/view.test.d.ts +2 -0
- package/dist/__tests__/harness/view.test.d.ts.map +1 -0
- package/dist/__tests__/harness/view.test.js +92 -0
- package/dist/__tests__/harness/view.test.js.map +1 -0
- package/dist/__tests__/runtime.test.d.ts +2 -0
- package/dist/__tests__/runtime.test.d.ts.map +1 -0
- package/dist/__tests__/runtime.test.js +141 -0
- package/dist/__tests__/runtime.test.js.map +1 -0
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/__tests__/compile.test.d.ts +2 -0
- package/dist/commands/__tests__/compile.test.d.ts.map +1 -0
- package/dist/commands/__tests__/compile.test.js +351 -0
- package/dist/commands/__tests__/compile.test.js.map +1 -0
- package/dist/commands/__tests__/init.test.d.ts +2 -0
- package/dist/commands/__tests__/init.test.d.ts.map +1 -0
- package/dist/commands/__tests__/init.test.js +101 -0
- package/dist/commands/__tests__/init.test.js.map +1 -0
- package/dist/commands/__tests__/run.test.d.ts +2 -0
- package/dist/commands/__tests__/run.test.d.ts.map +1 -0
- package/dist/commands/__tests__/run.test.js +166 -0
- package/dist/commands/__tests__/run.test.js.map +1 -0
- package/dist/commands/__tests__/test-move.test.d.ts +2 -0
- package/dist/commands/__tests__/test-move.test.d.ts.map +1 -0
- package/dist/commands/__tests__/test-move.test.js +59 -0
- package/dist/commands/__tests__/test-move.test.js.map +1 -0
- package/dist/commands/__tests__/test.test.d.ts +2 -0
- package/dist/commands/__tests__/test.test.d.ts.map +1 -0
- package/dist/commands/__tests__/test.test.js +168 -0
- package/dist/commands/__tests__/test.test.js.map +1 -0
- package/dist/commands/__tests__/update.test.d.ts +2 -0
- package/dist/commands/__tests__/update.test.d.ts.map +1 -0
- package/dist/commands/__tests__/update.test.js +176 -0
- package/dist/commands/__tests__/update.test.js.map +1 -0
- package/dist/commands/compile.d.ts +7 -1
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +150 -33
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/fork/__tests__/create.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/create.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/create.test.js +108 -0
- package/dist/commands/fork/__tests__/create.test.js.map +1 -0
- package/dist/commands/fork/__tests__/fund.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/fund.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/fund.test.js +72 -0
- package/dist/commands/fork/__tests__/fund.test.js.map +1 -0
- package/dist/commands/fork/__tests__/list.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/list.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/list.test.js +119 -0
- package/dist/commands/fork/__tests__/list.test.js.map +1 -0
- package/dist/commands/fork/__tests__/serve.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/serve.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/serve.test.js +97 -0
- package/dist/commands/fork/__tests__/serve.test.js.map +1 -0
- package/dist/commands/fork/__tests__/view-resource.test.d.ts +2 -0
- package/dist/commands/fork/__tests__/view-resource.test.d.ts.map +1 -0
- package/dist/commands/fork/__tests__/view-resource.test.js +77 -0
- package/dist/commands/fork/__tests__/view-resource.test.js.map +1 -0
- package/dist/commands/fork/create.d.ts +1 -1
- package/dist/commands/fork/create.d.ts.map +1 -1
- package/dist/commands/fork/create.js +3 -2
- package/dist/commands/fork/create.js.map +1 -1
- package/dist/commands/fork/fund.d.ts.map +1 -1
- package/dist/commands/fork/fund.js +15 -8
- package/dist/commands/fork/fund.js.map +1 -1
- package/dist/commands/fork/list.d.ts.map +1 -1
- package/dist/commands/fork/list.js +2 -1
- package/dist/commands/fork/list.js.map +1 -1
- package/dist/commands/fork/serve.d.ts +1 -0
- package/dist/commands/fork/serve.d.ts.map +1 -1
- package/dist/commands/fork/serve.js +4 -2
- package/dist/commands/fork/serve.js.map +1 -1
- package/dist/commands/fork/view-resource.d.ts.map +1 -1
- package/dist/commands/fork/view-resource.js +10 -5
- package/dist/commands/fork/view-resource.js.map +1 -1
- package/dist/commands/run.d.ts +15 -0
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +50 -27
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/test-move.d.ts.map +1 -1
- package/dist/commands/test-move.js +3 -2
- package/dist/commands/test-move.js.map +1 -1
- package/dist/commands/test.js +52 -46
- package/dist/commands/test.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +15 -13
- package/dist/commands/update.js.map +1 -1
- package/dist/core/AccountManager.d.ts +1 -1
- package/dist/core/AccountManager.d.ts.map +1 -1
- package/dist/core/AccountManager.js +20 -7
- package/dist/core/AccountManager.js.map +1 -1
- package/dist/core/Publisher.d.ts +31 -0
- package/dist/core/Publisher.d.ts.map +1 -0
- package/dist/core/Publisher.js +248 -0
- package/dist/core/Publisher.js.map +1 -0
- package/dist/core/__tests__/AccountManager.test.d.ts +2 -0
- package/dist/core/__tests__/AccountManager.test.d.ts.map +1 -0
- package/dist/core/__tests__/AccountManager.test.js +239 -0
- package/dist/core/__tests__/AccountManager.test.js.map +1 -0
- package/dist/core/__tests__/config.test.d.ts +2 -0
- package/dist/core/__tests__/config.test.d.ts.map +1 -0
- package/dist/core/__tests__/config.test.js +311 -0
- package/dist/core/__tests__/config.test.js.map +1 -0
- package/dist/core/__tests__/deployments.test.d.ts +2 -0
- package/dist/core/__tests__/deployments.test.d.ts.map +1 -0
- package/dist/core/__tests__/deployments.test.js +201 -0
- package/dist/core/__tests__/deployments.test.js.map +1 -0
- package/dist/core/__tests__/shell.test.d.ts +2 -0
- package/dist/core/__tests__/shell.test.d.ts.map +1 -0
- package/dist/core/__tests__/shell.test.js +107 -0
- package/dist/core/__tests__/shell.test.js.map +1 -0
- package/dist/core/config.d.ts +13 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +80 -11
- package/dist/core/config.js.map +1 -1
- package/dist/core/contract.d.ts +1 -1
- package/dist/core/contract.d.ts.map +1 -1
- package/dist/core/contract.js +15 -4
- package/dist/core/contract.js.map +1 -1
- package/dist/core/deployments.d.ts +2 -2
- package/dist/core/deployments.d.ts.map +1 -1
- package/dist/core/deployments.js +8 -6
- package/dist/core/deployments.js.map +1 -1
- package/dist/core/movementProfile.d.ts +34 -0
- package/dist/core/movementProfile.d.ts.map +1 -0
- package/dist/core/movementProfile.js +150 -0
- package/dist/core/movementProfile.js.map +1 -0
- package/dist/core/shell.d.ts +23 -7
- package/dist/core/shell.d.ts.map +1 -1
- package/dist/core/shell.js +32 -14
- package/dist/core/shell.js.map +1 -1
- package/dist/errors.d.ts +35 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +54 -0
- package/dist/errors.js.map +1 -1
- package/dist/fork/__tests__/manager.test.d.ts +2 -0
- package/dist/fork/__tests__/manager.test.d.ts.map +1 -0
- package/dist/fork/__tests__/manager.test.js +309 -0
- package/dist/fork/__tests__/manager.test.js.map +1 -0
- package/dist/fork/__tests__/server.test.d.ts +2 -0
- package/dist/fork/__tests__/server.test.d.ts.map +1 -0
- package/dist/fork/__tests__/server.test.js +54 -0
- package/dist/fork/__tests__/server.test.js.map +1 -0
- package/dist/fork/__tests__/storage.test.d.ts +2 -0
- package/dist/fork/__tests__/storage.test.d.ts.map +1 -0
- package/dist/fork/__tests__/storage.test.js +222 -0
- package/dist/fork/__tests__/storage.test.js.map +1 -0
- package/dist/fork/__tests__/test.test.d.ts +2 -0
- package/dist/fork/__tests__/test.test.d.ts.map +1 -0
- package/dist/fork/__tests__/test.test.js +81 -0
- package/dist/fork/__tests__/test.test.js.map +1 -0
- package/dist/fork/api.d.ts +14 -3
- package/dist/fork/api.d.ts.map +1 -1
- package/dist/fork/api.js +25 -14
- package/dist/fork/api.js.map +1 -1
- package/dist/fork/manager.d.ts +23 -9
- package/dist/fork/manager.d.ts.map +1 -1
- package/dist/fork/manager.js +79 -36
- package/dist/fork/manager.js.map +1 -1
- package/dist/fork/server.d.ts +11 -3
- package/dist/fork/server.d.ts.map +1 -1
- package/dist/fork/server.js +45 -13
- package/dist/fork/server.js.map +1 -1
- package/dist/fork/storage.d.ts +4 -4
- package/dist/fork/storage.d.ts.map +1 -1
- package/dist/fork/storage.js +7 -9
- package/dist/fork/storage.js.map +1 -1
- package/dist/fork/test.d.ts +13 -4
- package/dist/fork/test.d.ts.map +1 -1
- package/dist/fork/test.js +36 -27
- package/dist/fork/test.js.map +1 -1
- package/dist/harness/Harness.d.ts +124 -0
- package/dist/harness/Harness.d.ts.map +1 -0
- package/dist/harness/Harness.js +193 -0
- package/dist/harness/Harness.js.map +1 -0
- package/dist/harness/codeObject.d.ts +31 -0
- package/dist/harness/codeObject.d.ts.map +1 -0
- package/dist/harness/codeObject.js +271 -0
- package/dist/harness/codeObject.js.map +1 -0
- package/dist/harness/errors.d.ts +14 -0
- package/dist/harness/errors.d.ts.map +1 -0
- package/dist/harness/errors.js +22 -0
- package/dist/harness/errors.js.map +1 -0
- package/dist/harness/index.d.ts +4 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +3 -0
- package/dist/harness/index.js.map +1 -0
- package/dist/harness/proxy.d.ts +7 -0
- package/dist/harness/proxy.d.ts.map +1 -0
- package/dist/harness/proxy.js +36 -0
- package/dist/harness/proxy.js.map +1 -0
- package/dist/harness/script.d.ts +21 -0
- package/dist/harness/script.d.ts.map +1 -0
- package/dist/harness/script.js +155 -0
- package/dist/harness/script.js.map +1 -0
- package/dist/harness/view.d.ts +22 -0
- package/dist/harness/view.d.ts.map +1 -0
- package/dist/harness/view.js +28 -0
- package/dist/harness/view.js.map +1 -0
- package/dist/helpers/__tests__/semver-utils.test.d.ts +2 -0
- package/dist/helpers/__tests__/semver-utils.test.d.ts.map +1 -0
- package/dist/helpers/__tests__/semver-utils.test.js +103 -0
- package/dist/helpers/__tests__/semver-utils.test.js.map +1 -0
- package/dist/helpers/index.d.ts +3 -2
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +2 -2
- package/dist/helpers/index.js.map +1 -1
- package/dist/helpers/move-tests.d.ts +3 -3
- package/dist/helpers/move-tests.d.ts.map +1 -1
- package/dist/helpers/move-tests.js +21 -20
- package/dist/helpers/move-tests.js.map +1 -1
- package/dist/helpers/npm-registry.d.ts.map +1 -1
- package/dist/helpers/npm-registry.js +1 -3
- package/dist/helpers/npm-registry.js.map +1 -1
- package/dist/helpers/semver-utils.d.ts.map +1 -1
- package/dist/helpers/semver-utils.js +4 -3
- package/dist/helpers/semver-utils.js.map +1 -1
- package/dist/helpers/setup.d.ts.map +1 -1
- package/dist/helpers/setup.js +10 -6
- package/dist/helpers/setup.js.map +1 -1
- package/dist/helpers/setupLocalTesting.d.ts +32 -27
- package/dist/helpers/setupLocalTesting.d.ts.map +1 -1
- package/dist/helpers/setupLocalTesting.js +179 -180
- package/dist/helpers/setupLocalTesting.js.map +1 -1
- package/dist/helpers/testFixtures.d.ts +19 -53
- package/dist/helpers/testFixtures.d.ts.map +1 -1
- package/dist/helpers/testFixtures.js +89 -107
- package/dist/helpers/testFixtures.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/node/LocalNodeManager.d.ts +9 -1
- package/dist/node/LocalNodeManager.d.ts.map +1 -1
- package/dist/node/LocalNodeManager.js +75 -58
- package/dist/node/LocalNodeManager.js.map +1 -1
- package/dist/node/__tests__/LocalNodeManager.test.d.ts +2 -0
- package/dist/node/__tests__/LocalNodeManager.test.d.ts.map +1 -0
- package/dist/node/__tests__/LocalNodeManager.test.js +349 -0
- package/dist/node/__tests__/LocalNodeManager.test.js.map +1 -0
- package/dist/runtime.d.ts +12 -15
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +32 -241
- package/dist/runtime.js.map +1 -1
- package/dist/templates/README.md +1 -1
- package/dist/templates/movehat.config.ts +10 -0
- package/dist/templates/package.json +2 -1
- package/dist/templates/scripts/deploy-counter.ts +46 -38
- package/dist/templates/tests/Counter.test.ts +51 -51
- package/dist/templates/types/movehat.d.ts +6 -9
- package/dist/types/config.d.ts +8 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/fork.d.ts +7 -1
- package/dist/types/fork.d.ts.map +1 -1
- package/dist/types/harness.d.ts +166 -0
- package/dist/types/harness.d.ts.map +1 -0
- package/dist/types/harness.js +2 -0
- package/dist/types/harness.js.map +1 -0
- package/dist/types/runtime.d.ts +7 -1
- package/dist/types/runtime.d.ts.map +1 -1
- package/dist/ui/__tests__/colors.test.d.ts +2 -0
- package/dist/ui/__tests__/colors.test.d.ts.map +1 -0
- package/dist/ui/__tests__/colors.test.js +127 -0
- package/dist/ui/__tests__/colors.test.js.map +1 -0
- package/dist/ui/colors.d.ts.map +1 -1
- package/dist/ui/colors.js +6 -2
- package/dist/ui/colors.js.map +1 -1
- package/dist/ui/logger.d.ts +17 -0
- package/dist/ui/logger.d.ts.map +1 -1
- package/dist/ui/logger.js +22 -0
- package/dist/ui/logger.js.map +1 -1
- package/dist/ui/symbols.d.ts +1 -0
- package/dist/ui/symbols.d.ts.map +1 -1
- package/dist/ui/symbols.js +7 -1
- package/dist/ui/symbols.js.map +1 -1
- package/dist/utils/__tests__/address.test.d.ts +2 -0
- package/dist/utils/__tests__/address.test.d.ts.map +1 -0
- package/dist/utils/__tests__/address.test.js +70 -0
- package/dist/utils/__tests__/address.test.js.map +1 -0
- package/dist/utils/__tests__/childProcessAdapter.test.d.ts +2 -0
- package/dist/utils/__tests__/childProcessAdapter.test.d.ts.map +1 -0
- package/dist/utils/__tests__/childProcessAdapter.test.js +217 -0
- package/dist/utils/__tests__/childProcessAdapter.test.js.map +1 -0
- package/dist/utils/__tests__/runCli.test.d.ts +2 -0
- package/dist/utils/__tests__/runCli.test.d.ts.map +1 -0
- package/dist/utils/__tests__/runCli.test.js +187 -0
- package/dist/utils/__tests__/runCli.test.js.map +1 -0
- package/dist/utils/address.d.ts +33 -0
- package/dist/utils/address.d.ts.map +1 -0
- package/dist/utils/address.js +52 -0
- package/dist/utils/address.js.map +1 -0
- package/dist/utils/childProcessAdapter.d.ts +93 -0
- package/dist/utils/childProcessAdapter.d.ts.map +1 -0
- package/dist/utils/childProcessAdapter.js +109 -0
- package/dist/utils/childProcessAdapter.js.map +1 -0
- package/dist/utils/parseCliOutput.d.ts +20 -0
- package/dist/utils/parseCliOutput.d.ts.map +1 -0
- package/dist/utils/parseCliOutput.js +26 -0
- package/dist/utils/parseCliOutput.js.map +1 -0
- package/dist/utils/redact.d.ts +15 -0
- package/dist/utils/redact.d.ts.map +1 -0
- package/dist/utils/redact.js +24 -0
- package/dist/utils/redact.js.map +1 -0
- package/dist/utils/runCli.d.ts +24 -0
- package/dist/utils/runCli.d.ts.map +1 -0
- package/dist/utils/runCli.js +37 -0
- package/dist/utils/runCli.js.map +1 -0
- package/package.json +14 -4
- package/src/__tests__/deployContract.test.ts +429 -0
- package/src/__tests__/errors.test.ts +84 -0
- package/src/__tests__/fixtures/sigint-deploy-harness.ts +95 -0
- package/src/__tests__/fork/api.test.ts +143 -0
- package/src/__tests__/harness/Harness.createLive.test.ts +57 -0
- package/src/__tests__/harness/Harness.proxy.test.ts +115 -0
- package/src/__tests__/harness/_fixture.ts +131 -0
- package/src/__tests__/harness/codeObject.deploy.test.ts +319 -0
- package/src/__tests__/harness/codeObject.upgrade.test.ts +156 -0
- package/src/__tests__/harness/script.test.ts +245 -0
- package/src/__tests__/harness/view.test.ts +104 -0
- package/src/__tests__/runtime.test.ts +182 -0
- package/src/cli.ts +2 -1
- package/src/commands/__tests__/compile.test.ts +407 -0
- package/src/commands/__tests__/init.test.ts +125 -0
- package/src/commands/__tests__/run.test.ts +192 -0
- package/src/commands/__tests__/test-move.test.ts +81 -0
- package/src/commands/__tests__/test.test.ts +204 -0
- package/src/commands/__tests__/update.test.ts +223 -0
- package/src/commands/compile.ts +168 -32
- package/src/commands/fork/__tests__/create.test.ts +132 -0
- package/src/commands/fork/__tests__/fund.test.ts +104 -0
- package/src/commands/fork/__tests__/list.test.ts +139 -0
- package/src/commands/fork/__tests__/serve.test.ts +121 -0
- package/src/commands/fork/__tests__/view-resource.test.ts +101 -0
- package/src/commands/fork/create.ts +4 -3
- package/src/commands/fork/fund.ts +16 -9
- package/src/commands/fork/list.ts +3 -2
- package/src/commands/fork/serve.ts +6 -3
- package/src/commands/fork/view-resource.ts +11 -6
- package/src/commands/run.ts +54 -28
- package/src/commands/test-move.ts +4 -3
- package/src/commands/test.ts +56 -44
- package/src/commands/update.ts +19 -16
- package/src/core/AccountManager.ts +23 -10
- package/src/core/Publisher.ts +322 -0
- package/src/core/__tests__/AccountManager.test.ts +290 -0
- package/src/core/__tests__/config.test.ts +377 -0
- package/src/core/__tests__/deployments.test.ts +247 -0
- package/src/core/__tests__/shell.test.ts +138 -0
- package/src/core/config.ts +96 -12
- package/src/core/contract.ts +13 -4
- package/src/core/deployments.ts +13 -11
- package/src/core/movementProfile.ts +179 -0
- package/src/core/shell.ts +34 -14
- package/src/errors.ts +60 -0
- package/src/fork/__tests__/manager.test.ts +385 -0
- package/src/fork/__tests__/server.test.ts +65 -0
- package/src/fork/__tests__/storage.test.ts +281 -0
- package/src/fork/__tests__/test.test.ts +97 -0
- package/src/fork/api.ts +28 -14
- package/src/fork/manager.ts +88 -43
- package/src/fork/server.ts +53 -19
- package/src/fork/storage.ts +12 -15
- package/src/fork/test.ts +58 -32
- package/src/harness/Harness.ts +228 -0
- package/src/harness/codeObject.ts +388 -0
- package/src/harness/errors.ts +22 -0
- package/src/harness/index.ts +3 -0
- package/src/harness/proxy.ts +40 -0
- package/src/harness/script.ts +196 -0
- package/src/harness/view.ts +34 -0
- package/src/helpers/__tests__/semver-utils.test.ts +121 -0
- package/src/helpers/index.ts +2 -8
- package/src/helpers/move-tests.ts +27 -23
- package/src/helpers/npm-registry.ts +4 -3
- package/src/helpers/semver-utils.ts +4 -3
- package/src/helpers/setup.ts +9 -5
- package/src/helpers/setupLocalTesting.ts +219 -200
- package/src/helpers/testFixtures.ts +106 -118
- package/src/index.ts +9 -3
- package/src/node/LocalNodeManager.ts +87 -62
- package/src/node/__tests__/LocalNodeManager.test.ts +452 -0
- package/src/runtime.ts +33 -289
- package/src/templates/README.md +1 -1
- package/src/templates/movehat.config.ts +10 -0
- package/src/templates/package.json +2 -1
- package/src/templates/scripts/deploy-counter.ts +46 -38
- package/src/templates/tests/Counter.test.ts +51 -51
- package/src/templates/types/movehat.d.ts +6 -9
- package/src/types/config.ts +8 -0
- package/src/types/fork.ts +7 -1
- package/src/types/harness.ts +182 -0
- package/src/types/runtime.ts +11 -3
- package/src/ui/__tests__/colors.test.ts +156 -0
- package/src/ui/colors.ts +5 -2
- package/src/ui/logger.ts +22 -0
- package/src/ui/symbols.ts +7 -1
- package/src/utils/__tests__/address.test.ts +93 -0
- package/src/utils/__tests__/childProcessAdapter.test.ts +266 -0
- package/src/utils/__tests__/runCli.test.ts +240 -0
- package/src/utils/address.ts +56 -0
- package/src/utils/childProcessAdapter.ts +215 -0
- package/src/utils/parseCliOutput.ts +27 -0
- package/src/utils/redact.ts +24 -0
- package/src/utils/runCli.ts +64 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, statSync, existsSync, writeFileSync } from "fs";
|
|
3
|
+
import { tmpdir, platform } from "os";
|
|
4
|
+
import { join } from "path";
|
|
5
|
+
import { AccountManager } from "../AccountManager.js";
|
|
6
|
+
import type { MovehatConfig } from "../../types/config.js";
|
|
7
|
+
|
|
8
|
+
describe("AccountManager.saveAccountPool", () => {
|
|
9
|
+
let tmpDir: string;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
tmpDir = mkdtempSync(join(tmpdir(), "movehat-acc-pool-"));
|
|
13
|
+
AccountManager.clearPool();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
AccountManager.clearPool();
|
|
18
|
+
if (existsSync(tmpDir)) {
|
|
19
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("writes test-pool.json with 0o600 permissions", () => {
|
|
24
|
+
AccountManager.createAccount("alice");
|
|
25
|
+
AccountManager.createAccount("bob");
|
|
26
|
+
|
|
27
|
+
const poolDir = join(tmpDir, "accounts");
|
|
28
|
+
AccountManager.saveAccountPool(poolDir);
|
|
29
|
+
|
|
30
|
+
const poolFile = join(poolDir, "test-pool.json");
|
|
31
|
+
expect(existsSync(poolFile)).toBe(true);
|
|
32
|
+
|
|
33
|
+
// Mode check is POSIX-only; skip on Windows where mode bits don't apply.
|
|
34
|
+
if (platform() !== "win32") {
|
|
35
|
+
const stat = statSync(poolFile);
|
|
36
|
+
const mode = stat.mode & 0o777;
|
|
37
|
+
expect(mode).toBe(0o600);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("creates the pool directory with 0o700 permissions when missing", () => {
|
|
42
|
+
AccountManager.createAccount("alice");
|
|
43
|
+
|
|
44
|
+
const poolDir = join(tmpDir, "fresh-accounts");
|
|
45
|
+
AccountManager.saveAccountPool(poolDir);
|
|
46
|
+
|
|
47
|
+
expect(existsSync(poolDir)).toBe(true);
|
|
48
|
+
|
|
49
|
+
if (platform() !== "win32") {
|
|
50
|
+
const stat = statSync(poolDir);
|
|
51
|
+
const mode = stat.mode & 0o777;
|
|
52
|
+
expect(mode).toBe(0o700);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const TEST_KEY_A =
|
|
58
|
+
"0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
59
|
+
const TEST_KEY_B =
|
|
60
|
+
"0x0000000000000000000000000000000000000000000000000000000000000002";
|
|
61
|
+
|
|
62
|
+
describe("AccountManager — create / lookup / label", () => {
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
AccountManager.clearPool();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
afterEach(() => {
|
|
68
|
+
AccountManager.clearPool();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("getTestAccount(label) creates on first call, returns the same on second", () => {
|
|
72
|
+
const first = AccountManager.getTestAccount("alice");
|
|
73
|
+
const second = AccountManager.getTestAccount("alice");
|
|
74
|
+
expect(second.accountAddress.toString()).toBe(first.accountAddress.toString());
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("getTestAccount() with no label creates a fresh unlabeled account", () => {
|
|
78
|
+
const a = AccountManager.getTestAccount();
|
|
79
|
+
const b = AccountManager.getTestAccount();
|
|
80
|
+
expect(a.accountAddress.toString()).not.toBe(b.accountAddress.toString());
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("createAccount tracks the new account in the pool", () => {
|
|
84
|
+
expect(AccountManager.getPoolSize()).toBe(0);
|
|
85
|
+
AccountManager.createAccount("alice");
|
|
86
|
+
AccountManager.createAccount("bob");
|
|
87
|
+
expect(AccountManager.getPoolSize()).toBe(2);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("getAccountByLabel returns undefined for an unknown label", () => {
|
|
91
|
+
expect(AccountManager.getAccountByLabel("missing")).toBeUndefined();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("getLabeledAccounts returns a map of every labeled account", () => {
|
|
95
|
+
AccountManager.createAccount("alice");
|
|
96
|
+
AccountManager.createAccount("bob");
|
|
97
|
+
AccountManager.createAccount(); // unlabeled — should NOT appear
|
|
98
|
+
const labeled = AccountManager.getLabeledAccounts();
|
|
99
|
+
expect(Object.keys(labeled).sort()).toEqual(["alice", "bob"]);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("hasLabel reflects the label map state", () => {
|
|
103
|
+
expect(AccountManager.hasLabel("alice")).toBe(false);
|
|
104
|
+
AccountManager.createAccount("alice");
|
|
105
|
+
expect(AccountManager.hasLabel("alice")).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("getOrCreateLabeled returns the existing labeled account on second call", () => {
|
|
109
|
+
const first = AccountManager.getOrCreateLabeled("alice");
|
|
110
|
+
const second = AccountManager.getOrCreateLabeled("alice");
|
|
111
|
+
expect(second.accountAddress.toString()).toBe(first.accountAddress.toString());
|
|
112
|
+
expect(AccountManager.getPoolSize()).toBe(1);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("createBatch creates one account per label and returns the map", () => {
|
|
116
|
+
const accounts = AccountManager.createBatch(["alice", "bob", "charlie"]);
|
|
117
|
+
expect(Object.keys(accounts).sort()).toEqual(["alice", "bob", "charlie"]);
|
|
118
|
+
expect(AccountManager.getPoolSize()).toBe(3);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("getAllAccounts returns every account in insertion order", () => {
|
|
122
|
+
const a = AccountManager.createAccount("alice");
|
|
123
|
+
const b = AccountManager.createAccount("bob");
|
|
124
|
+
const addrs = AccountManager.getAllAccounts().map((acc) =>
|
|
125
|
+
acc.accountAddress.toString()
|
|
126
|
+
);
|
|
127
|
+
// Insertion order is preserved by the underlying Map iteration.
|
|
128
|
+
expect(addrs).toEqual([
|
|
129
|
+
a.accountAddress.toString(),
|
|
130
|
+
b.accountAddress.toString(),
|
|
131
|
+
]);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("clearPool resets pool, label map, and poolLoaded flag", () => {
|
|
135
|
+
AccountManager.createAccount("alice");
|
|
136
|
+
expect(AccountManager.getPoolSize()).toBe(1);
|
|
137
|
+
AccountManager.clearPool();
|
|
138
|
+
expect(AccountManager.getPoolSize()).toBe(0);
|
|
139
|
+
expect(AccountManager.hasLabel("alice")).toBe(false);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
describe("AccountManager — load from env / key / config", () => {
|
|
144
|
+
let origEnv: string | undefined;
|
|
145
|
+
|
|
146
|
+
beforeEach(() => {
|
|
147
|
+
AccountManager.clearPool();
|
|
148
|
+
origEnv = process.env.PRIVATE_KEY;
|
|
149
|
+
delete process.env.PRIVATE_KEY;
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
afterEach(() => {
|
|
153
|
+
AccountManager.clearPool();
|
|
154
|
+
if (origEnv === undefined) delete process.env.PRIVATE_KEY;
|
|
155
|
+
else process.env.PRIVATE_KEY = origEnv;
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("loadAccountFromEnv reads from PRIVATE_KEY by default", () => {
|
|
159
|
+
process.env.PRIVATE_KEY = TEST_KEY_A;
|
|
160
|
+
const acc = AccountManager.loadAccountFromEnv();
|
|
161
|
+
expect(acc.accountAddress.toString()).toMatch(/^0x[a-f0-9]+$/i);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("loadAccountFromEnv reads from a custom env var name", () => {
|
|
165
|
+
process.env.MY_CUSTOM_KEY = TEST_KEY_A;
|
|
166
|
+
try {
|
|
167
|
+
const acc = AccountManager.loadAccountFromEnv("MY_CUSTOM_KEY");
|
|
168
|
+
expect(acc.accountAddress.toString()).toMatch(/^0x[a-f0-9]+$/i);
|
|
169
|
+
} finally {
|
|
170
|
+
delete process.env.MY_CUSTOM_KEY;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("loadAccountFromEnv throws when the env var is unset", () => {
|
|
175
|
+
expect(() => AccountManager.loadAccountFromEnv("DEFINITELY_NOT_SET")).toThrow(
|
|
176
|
+
/not found/
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it("loadAccountFromPrivateKey adds the account to the pool", () => {
|
|
181
|
+
expect(AccountManager.getPoolSize()).toBe(0);
|
|
182
|
+
AccountManager.loadAccountFromPrivateKey(TEST_KEY_A);
|
|
183
|
+
expect(AccountManager.getPoolSize()).toBe(1);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("loadAccountsFromConfig loads every valid key", () => {
|
|
187
|
+
const config = {
|
|
188
|
+
allAccounts: [TEST_KEY_A, TEST_KEY_B],
|
|
189
|
+
} as unknown as MovehatConfig;
|
|
190
|
+
const accounts = AccountManager.loadAccountsFromConfig(config);
|
|
191
|
+
expect(accounts).toHaveLength(2);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it("loadAccountsFromConfig warns on a malformed key and skips it", () => {
|
|
195
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => undefined);
|
|
196
|
+
const config = {
|
|
197
|
+
allAccounts: [TEST_KEY_A, "not-a-real-key"],
|
|
198
|
+
} as unknown as MovehatConfig;
|
|
199
|
+
const accounts = AccountManager.loadAccountsFromConfig(config);
|
|
200
|
+
expect(accounts).toHaveLength(1);
|
|
201
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
202
|
+
expect.stringMatching(/Failed to load account from config/)
|
|
203
|
+
);
|
|
204
|
+
warnSpy.mockRestore();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe("AccountManager.loadAccountPool / exportPrivateKeys", () => {
|
|
209
|
+
let tmpDir: string;
|
|
210
|
+
|
|
211
|
+
beforeEach(() => {
|
|
212
|
+
tmpDir = mkdtempSync(join(tmpdir(), "movehat-acc-load-"));
|
|
213
|
+
AccountManager.clearPool();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
afterEach(() => {
|
|
217
|
+
AccountManager.clearPool();
|
|
218
|
+
if (existsSync(tmpDir)) {
|
|
219
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("loadAccountPool returns false when the file does not exist", () => {
|
|
224
|
+
expect(AccountManager.loadAccountPool(tmpDir)).toBe(false);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("loadAccountPool restores accounts and labels from disk", () => {
|
|
228
|
+
// Plant a pool via save → clear → load round-trip.
|
|
229
|
+
AccountManager.createAccount("alice");
|
|
230
|
+
AccountManager.createAccount("bob");
|
|
231
|
+
const poolDir = join(tmpDir, "accounts");
|
|
232
|
+
AccountManager.saveAccountPool(poolDir);
|
|
233
|
+
AccountManager.clearPool();
|
|
234
|
+
expect(AccountManager.getPoolSize()).toBe(0);
|
|
235
|
+
|
|
236
|
+
const ok = AccountManager.loadAccountPool(poolDir);
|
|
237
|
+
expect(ok).toBe(true);
|
|
238
|
+
expect(AccountManager.getPoolSize()).toBe(2);
|
|
239
|
+
expect(AccountManager.hasLabel("alice")).toBe(true);
|
|
240
|
+
expect(AccountManager.hasLabel("bob")).toBe(true);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("loadAccountPool is a no-op when poolLoaded is already true", () => {
|
|
244
|
+
AccountManager.createAccount("alice");
|
|
245
|
+
const poolDir = join(tmpDir, "accounts");
|
|
246
|
+
AccountManager.saveAccountPool(poolDir);
|
|
247
|
+
expect(AccountManager.loadAccountPool(poolDir)).toBe(true);
|
|
248
|
+
// Second call short-circuits via the poolLoaded flag.
|
|
249
|
+
expect(AccountManager.loadAccountPool(poolDir)).toBe(true);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("loadAccountPool returns false and warns on corrupt JSON", () => {
|
|
253
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => undefined);
|
|
254
|
+
const poolDir = join(tmpDir, "accounts");
|
|
255
|
+
// mkdir then write a deliberately malformed test-pool.json.
|
|
256
|
+
AccountManager.createAccount("alice");
|
|
257
|
+
AccountManager.saveAccountPool(poolDir);
|
|
258
|
+
writeFileSync(join(poolDir, "test-pool.json"), "{ not valid json");
|
|
259
|
+
AccountManager.clearPool();
|
|
260
|
+
expect(AccountManager.loadAccountPool(poolDir)).toBe(false);
|
|
261
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
262
|
+
expect.stringMatching(/Failed to load account pool/)
|
|
263
|
+
);
|
|
264
|
+
warnSpy.mockRestore();
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("exportPrivateKeys returns every labeled account's key when called with no args", () => {
|
|
268
|
+
AccountManager.createAccount("alice");
|
|
269
|
+
AccountManager.createAccount("bob");
|
|
270
|
+
const exported = AccountManager.exportPrivateKeys();
|
|
271
|
+
expect(Object.keys(exported).sort()).toEqual(["alice", "bob"]);
|
|
272
|
+
for (const key of Object.values(exported)) {
|
|
273
|
+
expect(typeof key).toBe("string");
|
|
274
|
+
expect(key.length).toBeGreaterThan(0);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it("exportPrivateKeys filters by labels when an array is passed", () => {
|
|
279
|
+
AccountManager.createAccount("alice");
|
|
280
|
+
AccountManager.createAccount("bob");
|
|
281
|
+
AccountManager.createAccount("charlie");
|
|
282
|
+
const exported = AccountManager.exportPrivateKeys(["alice", "charlie"]);
|
|
283
|
+
expect(Object.keys(exported).sort()).toEqual(["alice", "charlie"]);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it("exportPrivateKeys with an unknown label returns an empty map", () => {
|
|
287
|
+
const exported = AccountManager.exportPrivateKeys(["missing"]);
|
|
288
|
+
expect(exported).toEqual({});
|
|
289
|
+
});
|
|
290
|
+
});
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
mkdtempSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
rmSync,
|
|
6
|
+
utimesSync,
|
|
7
|
+
writeFileSync,
|
|
8
|
+
} from "node:fs";
|
|
9
|
+
import { tmpdir } from "node:os";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { loadUserConfig, resolveNetworkConfig, _resetConfigCache } from "../config.js";
|
|
13
|
+
import type { MovehatUserConfig } from "../../types/config.js";
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
|
|
17
|
+
const CONFIG_A = `export default {
|
|
18
|
+
defaultNetwork: "testnet",
|
|
19
|
+
networks: {
|
|
20
|
+
testnet: { url: "https://testnet.movementnetwork.xyz/v1", chainId: "testnet" }
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
const CONFIG_B = `export default {
|
|
26
|
+
defaultNetwork: "mainnet",
|
|
27
|
+
networks: {
|
|
28
|
+
mainnet: { url: "https://mainnet.movementnetwork.xyz/v1", chainId: "mainnet" }
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
describe("loadUserConfig — mtime cache (#81, #62)", () => {
|
|
34
|
+
let tmpCwd: string;
|
|
35
|
+
let origCwd: string;
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
_resetConfigCache();
|
|
39
|
+
origCwd = process.cwd();
|
|
40
|
+
tmpCwd = mkdtempSync(join(tmpdir(), "movehat-config-test-"));
|
|
41
|
+
process.chdir(tmpCwd);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
process.chdir(origCwd);
|
|
46
|
+
rmSync(tmpCwd, { recursive: true, force: true });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("first call reads from disk", async () => {
|
|
50
|
+
writeFileSync(join(tmpCwd, "movehat.config.js"), CONFIG_A);
|
|
51
|
+
|
|
52
|
+
const config = await loadUserConfig();
|
|
53
|
+
|
|
54
|
+
expect(config.defaultNetwork).toBe("testnet");
|
|
55
|
+
expect(config.networks).toHaveProperty("testnet");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("second call returns the same parsed object (cache hit)", async () => {
|
|
59
|
+
writeFileSync(join(tmpCwd, "movehat.config.js"), CONFIG_A);
|
|
60
|
+
|
|
61
|
+
const first = await loadUserConfig();
|
|
62
|
+
const second = await loadUserConfig();
|
|
63
|
+
|
|
64
|
+
// Reference equality proves we returned the cached object rather
|
|
65
|
+
// than re-importing and getting a structurally-equal copy.
|
|
66
|
+
expect(second).toBe(first);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("mtime change invalidates the cache", async () => {
|
|
70
|
+
const path = join(tmpCwd, "movehat.config.js");
|
|
71
|
+
writeFileSync(path, CONFIG_A);
|
|
72
|
+
|
|
73
|
+
const first = await loadUserConfig();
|
|
74
|
+
expect(first.defaultNetwork).toBe("testnet");
|
|
75
|
+
|
|
76
|
+
// Rewrite + force an mtime far in the future so we don't depend on
|
|
77
|
+
// filesystem mtime resolution.
|
|
78
|
+
writeFileSync(path, CONFIG_B);
|
|
79
|
+
const future = new Date(Date.now() + 60_000);
|
|
80
|
+
utimesSync(path, future, future);
|
|
81
|
+
|
|
82
|
+
const second = await loadUserConfig();
|
|
83
|
+
|
|
84
|
+
expect(second).not.toBe(first);
|
|
85
|
+
expect(second.defaultNetwork).toBe("mainnet");
|
|
86
|
+
expect(second.networks).toHaveProperty("mainnet");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("different cwds keep separate cache entries", async () => {
|
|
90
|
+
writeFileSync(join(tmpCwd, "movehat.config.js"), CONFIG_A);
|
|
91
|
+
const fromA = await loadUserConfig();
|
|
92
|
+
expect(fromA.defaultNetwork).toBe("testnet");
|
|
93
|
+
|
|
94
|
+
const tmpCwdB = mkdtempSync(join(tmpdir(), "movehat-config-test-b-"));
|
|
95
|
+
try {
|
|
96
|
+
process.chdir(tmpCwdB);
|
|
97
|
+
writeFileSync(join(tmpCwdB, "movehat.config.js"), CONFIG_B);
|
|
98
|
+
const fromB = await loadUserConfig();
|
|
99
|
+
expect(fromB.defaultNetwork).toBe("mainnet");
|
|
100
|
+
|
|
101
|
+
// Switching back to A returns A's cached entry, not B's — proves
|
|
102
|
+
// the cache is keyed by absolute path, not by something process-
|
|
103
|
+
// scoped like "the last value loaded".
|
|
104
|
+
process.chdir(tmpCwd);
|
|
105
|
+
const fromAagain = await loadUserConfig();
|
|
106
|
+
expect(fromAagain).toBe(fromA);
|
|
107
|
+
expect(fromAagain.defaultNetwork).toBe("testnet");
|
|
108
|
+
} finally {
|
|
109
|
+
process.chdir(tmpCwd);
|
|
110
|
+
rmSync(tmpCwdB, { recursive: true, force: true });
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("source file no longer contains the `?t=` cache-bust (#62 regression guard)", () => {
|
|
115
|
+
const configSrc = readFileSync(join(__dirname, "..", "config.ts"), "utf-8");
|
|
116
|
+
|
|
117
|
+
expect(configSrc).not.toMatch(/\?t=['"]\s*\+\s*Date\.now/);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Note: there's no direct behavioral test for `_resetConfigCache()`.
|
|
121
|
+
// The function is exercised in `beforeEach` above — if it didn't
|
|
122
|
+
// actually clear the in-memory map, tests 3 and 4 would leak state
|
|
123
|
+
// between each other and start failing. Its "test" is therefore the
|
|
124
|
+
// rest of this suite continuing to pass.
|
|
125
|
+
|
|
126
|
+
it("throws when no movehat.config.{ts,js} is present", async () => {
|
|
127
|
+
// tmpCwd is empty (no config written) — should reject with the
|
|
128
|
+
// 'Configuration file not found' message.
|
|
129
|
+
await expect(loadUserConfig()).rejects.toThrow(/Configuration file not found/);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("rejects a config with empty `networks`", async () => {
|
|
133
|
+
writeFileSync(
|
|
134
|
+
join(tmpCwd, "movehat.config.js"),
|
|
135
|
+
`export default { networks: {} };
|
|
136
|
+
`
|
|
137
|
+
);
|
|
138
|
+
await expect(loadUserConfig()).rejects.toThrow(/No networks defined/);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
const TEST_KEY =
|
|
143
|
+
"0x0000000000000000000000000000000000000000000000000000000000000001";
|
|
144
|
+
|
|
145
|
+
const baseUserConfig = (networks: MovehatUserConfig["networks"]): MovehatUserConfig => ({
|
|
146
|
+
networks,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
describe("resolveNetworkConfig", () => {
|
|
150
|
+
const envSnapshot: Record<string, string | undefined> = {};
|
|
151
|
+
|
|
152
|
+
beforeEach(() => {
|
|
153
|
+
envSnapshot.PRIVATE_KEY = process.env.PRIVATE_KEY;
|
|
154
|
+
envSnapshot.MH_CLI_NETWORK = process.env.MH_CLI_NETWORK;
|
|
155
|
+
envSnapshot.MH_DEFAULT_NETWORK = process.env.MH_DEFAULT_NETWORK;
|
|
156
|
+
delete process.env.PRIVATE_KEY;
|
|
157
|
+
delete process.env.MH_CLI_NETWORK;
|
|
158
|
+
delete process.env.MH_DEFAULT_NETWORK;
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
afterEach(() => {
|
|
162
|
+
for (const [key, value] of Object.entries(envSnapshot)) {
|
|
163
|
+
if (value === undefined) {
|
|
164
|
+
delete process.env[key];
|
|
165
|
+
} else {
|
|
166
|
+
process.env[key] = value;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("uses the network passed as the argument over defaultNetwork", async () => {
|
|
172
|
+
const user = baseUserConfig({
|
|
173
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
174
|
+
b: { url: "https://b.example.com/v1", chainId: "b", accounts: [TEST_KEY] },
|
|
175
|
+
});
|
|
176
|
+
user.defaultNetwork = "a";
|
|
177
|
+
const resolved = await resolveNetworkConfig(user, "b");
|
|
178
|
+
expect(resolved.network).toBe("b");
|
|
179
|
+
expect(resolved.rpc).toBe("https://b.example.com/v1");
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("MH_CLI_NETWORK env var overrides defaultNetwork when no arg is passed", async () => {
|
|
183
|
+
process.env.MH_CLI_NETWORK = "b";
|
|
184
|
+
const user = baseUserConfig({
|
|
185
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
186
|
+
b: { url: "https://b.example.com/v1", chainId: "b", accounts: [TEST_KEY] },
|
|
187
|
+
});
|
|
188
|
+
user.defaultNetwork = "a";
|
|
189
|
+
const resolved = await resolveNetworkConfig(user);
|
|
190
|
+
expect(resolved.network).toBe("b");
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("MH_DEFAULT_NETWORK env var is the next-lower priority after MH_CLI_NETWORK", async () => {
|
|
194
|
+
process.env.MH_DEFAULT_NETWORK = "b";
|
|
195
|
+
const user = baseUserConfig({
|
|
196
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
197
|
+
b: { url: "https://b.example.com/v1", chainId: "b", accounts: [TEST_KEY] },
|
|
198
|
+
});
|
|
199
|
+
user.defaultNetwork = "a";
|
|
200
|
+
const resolved = await resolveNetworkConfig(user);
|
|
201
|
+
expect(resolved.network).toBe("b");
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("auto-generates a testnet config when 'testnet' is missing from user networks", async () => {
|
|
205
|
+
const logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
206
|
+
const user = baseUserConfig({
|
|
207
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
208
|
+
});
|
|
209
|
+
const resolved = await resolveNetworkConfig(user, "testnet");
|
|
210
|
+
expect(resolved.network).toBe("testnet");
|
|
211
|
+
expect(resolved.rpc).toBe("https://testnet.movementnetwork.xyz/v1");
|
|
212
|
+
logSpy.mockRestore();
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("auto-generates a local config when 'local' is missing from user networks", async () => {
|
|
216
|
+
const logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
217
|
+
const user = baseUserConfig({
|
|
218
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
219
|
+
});
|
|
220
|
+
const resolved = await resolveNetworkConfig(user, "local");
|
|
221
|
+
expect(resolved.network).toBe("local");
|
|
222
|
+
expect(resolved.rpc).toBe("http://localhost:8080/v1");
|
|
223
|
+
logSpy.mockRestore();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it("throws on a completely unknown network with a clear list of available ones", async () => {
|
|
227
|
+
const user = baseUserConfig({
|
|
228
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
229
|
+
});
|
|
230
|
+
await expect(resolveNetworkConfig(user, "nonexistent")).rejects.toThrow(
|
|
231
|
+
/Network 'nonexistent' not found/
|
|
232
|
+
);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
it("falls back to PRIVATE_KEY env var when no accounts are configured anywhere", async () => {
|
|
236
|
+
process.env.PRIVATE_KEY = TEST_KEY;
|
|
237
|
+
const user = baseUserConfig({
|
|
238
|
+
a: { url: "https://a.example.com/v1", chainId: "a" },
|
|
239
|
+
});
|
|
240
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
241
|
+
expect(resolved.privateKey).toBe(TEST_KEY);
|
|
242
|
+
expect(resolved.allAccounts).toEqual([TEST_KEY]);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("auto-generates a deterministic test key for testnet when no accounts are anywhere", async () => {
|
|
246
|
+
const logSpy = vi.spyOn(console, "log").mockImplementation(() => undefined);
|
|
247
|
+
const user = baseUserConfig({
|
|
248
|
+
testnet: { url: "https://testnet.movementnetwork.xyz/v1", chainId: "testnet" },
|
|
249
|
+
});
|
|
250
|
+
const resolved = await resolveNetworkConfig(user, "testnet");
|
|
251
|
+
// The auto-generated key is the canonical Hardhat-style test key.
|
|
252
|
+
expect(resolved.privateKey).toBe(
|
|
253
|
+
"0x0000000000000000000000000000000000000000000000000000000000000001"
|
|
254
|
+
);
|
|
255
|
+
logSpy.mockRestore();
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it("rejects a non-testnet/local network with no accounts (security gate)", async () => {
|
|
259
|
+
const user = baseUserConfig({
|
|
260
|
+
mainnet: { url: "https://mainnet.movementnetwork.xyz/v1", chainId: "mainnet" },
|
|
261
|
+
});
|
|
262
|
+
await expect(resolveNetworkConfig(user, "mainnet")).rejects.toThrow(
|
|
263
|
+
/requires explicit account configuration/
|
|
264
|
+
);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it("prefers network-specific accounts over global ones", async () => {
|
|
268
|
+
const user: MovehatUserConfig = {
|
|
269
|
+
accounts: ["0xglobal"],
|
|
270
|
+
networks: {
|
|
271
|
+
a: {
|
|
272
|
+
url: "https://a.example.com/v1",
|
|
273
|
+
chainId: "a",
|
|
274
|
+
accounts: [TEST_KEY],
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
279
|
+
expect(resolved.privateKey).toBe(TEST_KEY);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it("falls back to global accounts when network has none", async () => {
|
|
283
|
+
const user: MovehatUserConfig = {
|
|
284
|
+
accounts: [TEST_KEY],
|
|
285
|
+
networks: {
|
|
286
|
+
a: { url: "https://a.example.com/v1", chainId: "a" },
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
290
|
+
expect(resolved.privateKey).toBe(TEST_KEY);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it("merges named addresses, with network-specific overriding global", async () => {
|
|
294
|
+
const user: MovehatUserConfig = {
|
|
295
|
+
namedAddresses: { foo: "0xglobal", shared: "0xglobal" },
|
|
296
|
+
networks: {
|
|
297
|
+
a: {
|
|
298
|
+
url: "https://a.example.com/v1",
|
|
299
|
+
chainId: "a",
|
|
300
|
+
accounts: [TEST_KEY],
|
|
301
|
+
namedAddresses: { bar: "0xnet", shared: "0xnet" },
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
};
|
|
305
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
306
|
+
expect(resolved.namedAddresses).toEqual({
|
|
307
|
+
foo: "0xglobal",
|
|
308
|
+
bar: "0xnet",
|
|
309
|
+
shared: "0xnet",
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
it("derives the on-chain account address from the resolved key", async () => {
|
|
314
|
+
const user = baseUserConfig({
|
|
315
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
316
|
+
});
|
|
317
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
318
|
+
// The canonical Hardhat-style 0x...01 key derives to a well-known address.
|
|
319
|
+
expect(resolved.account).toMatch(/^0x[a-f0-9]+$/i);
|
|
320
|
+
expect(resolved.account.length).toBeGreaterThan(2);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it("returns account='' and warns when the configured key is malformed", async () => {
|
|
324
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => undefined);
|
|
325
|
+
const user = baseUserConfig({
|
|
326
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: ["not-a-real-key"] },
|
|
327
|
+
});
|
|
328
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
329
|
+
expect(resolved.account).toBe("");
|
|
330
|
+
expect(warnSpy).toHaveBeenCalledWith(
|
|
331
|
+
expect.stringMatching(/Could not derive account address/)
|
|
332
|
+
);
|
|
333
|
+
warnSpy.mockRestore();
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
it("strips the 'ed25519-priv-' prefix when deriving the account address", async () => {
|
|
337
|
+
const user = baseUserConfig({
|
|
338
|
+
a: {
|
|
339
|
+
url: "https://a.example.com/v1",
|
|
340
|
+
chainId: "a",
|
|
341
|
+
accounts: [`ed25519-priv-${TEST_KEY}`],
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
345
|
+
// Same key, prefixed and unprefixed, should derive the same address.
|
|
346
|
+
const bareResolved = await resolveNetworkConfig(
|
|
347
|
+
baseUserConfig({
|
|
348
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
349
|
+
}),
|
|
350
|
+
"a"
|
|
351
|
+
);
|
|
352
|
+
expect(resolved.account).toBe(bareResolved.account);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it("uses profile='default' when networkConfig has no profile", async () => {
|
|
356
|
+
const user = baseUserConfig({
|
|
357
|
+
a: { url: "https://a.example.com/v1", chainId: "a", accounts: [TEST_KEY] },
|
|
358
|
+
});
|
|
359
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
360
|
+
expect(resolved.profile).toBe("default");
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
it("respects networkConfig.profile when set", async () => {
|
|
364
|
+
const user: MovehatUserConfig = {
|
|
365
|
+
networks: {
|
|
366
|
+
a: {
|
|
367
|
+
url: "https://a.example.com/v1",
|
|
368
|
+
chainId: "a",
|
|
369
|
+
accounts: [TEST_KEY],
|
|
370
|
+
profile: "custom-profile",
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
const resolved = await resolveNetworkConfig(user, "a");
|
|
375
|
+
expect(resolved.profile).toBe("custom-profile");
|
|
376
|
+
});
|
|
377
|
+
});
|