movehat 0.2.0 → 0.2.1

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 (81) hide show
  1. package/README.md +132 -279
  2. package/dist/__tests__/fork/api.test.js +2 -2
  3. package/dist/__tests__/harness/Harness.proxy.test.js +7 -11
  4. package/dist/__tests__/harness/Harness.proxy.test.js.map +1 -1
  5. package/dist/__tests__/harness/codeObject.deploy.test.js +1 -1
  6. package/dist/__tests__/harness/codeObject.deploy.test.js.map +1 -1
  7. package/dist/__tests__/harness/view.test.js +3 -3
  8. package/dist/commands/__tests__/run.test.js +3 -3
  9. package/dist/commands/__tests__/run.test.js.map +1 -1
  10. package/dist/core/AccountManager.d.ts +0 -3
  11. package/dist/core/AccountManager.d.ts.map +1 -1
  12. package/dist/core/AccountManager.js +0 -5
  13. package/dist/core/AccountManager.js.map +1 -1
  14. package/dist/core/Publisher.d.ts +0 -5
  15. package/dist/core/Publisher.d.ts.map +1 -1
  16. package/dist/core/Publisher.js +0 -8
  17. package/dist/core/Publisher.js.map +1 -1
  18. package/dist/core/contract.d.ts +0 -3
  19. package/dist/core/contract.d.ts.map +1 -1
  20. package/dist/core/contract.js +0 -3
  21. package/dist/core/contract.js.map +1 -1
  22. package/dist/core/deployments.d.ts +0 -6
  23. package/dist/core/deployments.d.ts.map +1 -1
  24. package/dist/core/deployments.js +0 -12
  25. package/dist/core/deployments.js.map +1 -1
  26. package/dist/fork/__tests__/manager.test.js +1 -1
  27. package/dist/fork/manager.d.ts +1 -21
  28. package/dist/fork/manager.d.ts.map +1 -1
  29. package/dist/fork/manager.js +1 -41
  30. package/dist/fork/manager.js.map +1 -1
  31. package/dist/fork/test.d.ts +0 -1
  32. package/dist/fork/test.d.ts.map +1 -1
  33. package/dist/fork/test.js.map +1 -1
  34. package/dist/harness/Harness.d.ts +5 -11
  35. package/dist/harness/Harness.d.ts.map +1 -1
  36. package/dist/harness/Harness.js +5 -11
  37. package/dist/harness/Harness.js.map +1 -1
  38. package/dist/harness/codeObject.js +1 -5
  39. package/dist/harness/codeObject.js.map +1 -1
  40. package/dist/helpers/setupLocalTesting.d.ts +1 -2
  41. package/dist/helpers/setupLocalTesting.d.ts.map +1 -1
  42. package/dist/helpers/setupLocalTesting.js.map +1 -1
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +0 -1
  45. package/dist/index.js.map +1 -1
  46. package/dist/runtime.d.ts.map +1 -1
  47. package/dist/runtime.js +1 -3
  48. package/dist/runtime.js.map +1 -1
  49. package/dist/templates/scripts/deploy-counter.ts +1 -1
  50. package/dist/templates/tests/Counter.test.ts +2 -2
  51. package/dist/utils/address.d.ts +0 -4
  52. package/dist/utils/address.d.ts.map +1 -1
  53. package/dist/utils/address.js +0 -4
  54. package/dist/utils/address.js.map +1 -1
  55. package/dist/utils/childProcessAdapter.d.ts.map +1 -1
  56. package/dist/utils/childProcessAdapter.js +3 -4
  57. package/dist/utils/childProcessAdapter.js.map +1 -1
  58. package/package.json +2 -1
  59. package/src/__tests__/fork/api.test.ts +2 -2
  60. package/src/__tests__/harness/Harness.proxy.test.ts +7 -11
  61. package/src/__tests__/harness/codeObject.deploy.test.ts +1 -1
  62. package/src/__tests__/harness/view.test.ts +3 -3
  63. package/src/commands/__tests__/run.test.ts +3 -3
  64. package/src/core/AccountManager.ts +0 -12
  65. package/src/core/Publisher.ts +0 -8
  66. package/src/core/contract.ts +0 -3
  67. package/src/core/deployments.ts +0 -12
  68. package/src/fork/__tests__/manager.test.ts +1 -1
  69. package/src/fork/manager.ts +1 -41
  70. package/src/fork/test.ts +0 -1
  71. package/src/harness/Harness.ts +5 -11
  72. package/src/harness/codeObject.ts +1 -5
  73. package/src/helpers/setupLocalTesting.ts +1 -2
  74. package/src/index.ts +0 -1
  75. package/src/node/__tests__/LocalNodeManager.test.ts +1 -1
  76. package/src/runtime.ts +1 -3
  77. package/src/templates/scripts/deploy-counter.ts +1 -1
  78. package/src/templates/tests/Counter.test.ts +2 -2
  79. package/src/types/runtime.ts +2 -2
  80. package/src/utils/address.ts +0 -4
  81. package/src/utils/childProcessAdapter.ts +3 -4
@@ -50,16 +50,10 @@ export function validateSafeName(name: string, type: "network" | "module"): void
50
50
  }
51
51
  }
52
52
 
53
- /**
54
- * Get the deployments directory path
55
- */
56
53
  function getDeploymentsDir(): string {
57
54
  return join(process.cwd(), "deployments");
58
55
  }
59
56
 
60
- /**
61
- * Get the network-specific deployments directory
62
- */
63
57
  function getNetworkDeploymentsDir(network: string): string {
64
58
  // Validate network name to prevent path traversal
65
59
  validateSafeName(network, "network");
@@ -78,9 +72,6 @@ function getNetworkDeploymentsDir(network: string): string {
78
72
  return networkDir;
79
73
  }
80
74
 
81
- /**
82
- * Save a deployment
83
- */
84
75
  export function saveDeployment(deployment: DeploymentInfo): void {
85
76
  // Validate both network and module name
86
77
  validateSafeName(deployment.network, "network");
@@ -103,9 +94,6 @@ export function saveDeployment(deployment: DeploymentInfo): void {
103
94
  }
104
95
  }
105
96
 
106
- /**
107
- * Load a deployment
108
- */
109
97
  export function loadDeployment(network: string, moduleName: string): DeploymentInfo | null {
110
98
  // Validate both network and module name
111
99
  validateSafeName(network, "network");
@@ -4,7 +4,7 @@ import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
5
 
6
6
  /**
7
- * Tests for `ForkManager` (M3.3). Strategy:
7
+ * Tests for `ForkManager`. Strategy:
8
8
  * - `vi.mock` the upstream `MovementApiClient` (network layer) so
9
9
  * tests stay offline and deterministic.
10
10
  * - Use a REAL `ForkStorage` against a tmpdir (storage is already
@@ -70,16 +70,12 @@ export class ForkManager {
70
70
  ): Promise<void> {
71
71
  if (apiKey !== undefined) this.apiKey = apiKey;
72
72
 
73
- // Create API client (with optional Authorization header)
74
73
  this.apiClient = new MovementApiClient(nodeUrl, this.apiKey);
75
74
 
76
- // Fetch network info
77
75
  const ledgerInfo = await this.apiClient.getLedgerInfo();
78
76
 
79
- // Create fork structure
80
77
  this.storage.initialize();
81
78
 
82
- // Save metadata
83
79
  this.metadata = {
84
80
  network: networkName,
85
81
  nodeUrl,
@@ -110,9 +106,6 @@ export class ForkManager {
110
106
  this.apiClient = new MovementApiClient(this.metadata.nodeUrl, this.apiKey);
111
107
  }
112
108
 
113
- /**
114
- * Get fork metadata
115
- */
116
109
  getMetadata(): ForkMetadata {
117
110
  if (!this.metadata) {
118
111
  this.metadata = this.storage.loadMetadata();
@@ -120,18 +113,12 @@ export class ForkManager {
120
113
  return this.metadata;
121
114
  }
122
115
 
123
- /**
124
- * Get account state (with lazy loading)
125
- */
126
116
  async getAccount(address: string): Promise<AccountState> {
127
- // Normalize address
128
117
  const normalizedAddress = normalizeAddress(address);
129
118
 
130
- // Check cache first
131
119
  let accountState = this.storage.getAccount(normalizedAddress);
132
120
 
133
121
  if (!accountState) {
134
- // Fetch from network
135
122
  if (!this.apiClient) {
136
123
  throw new Error('Fork not initialized. Call initialize() or load() first.');
137
124
  }
@@ -144,7 +131,6 @@ export class ForkManager {
144
131
  authenticationKey: accountData.authentication_key,
145
132
  };
146
133
 
147
- // Cache it
148
134
  this.storage.saveAccount(normalizedAddress, accountState);
149
135
  console.log(` ✓ Cached account ${normalizedAddress}`);
150
136
  }
@@ -152,17 +138,12 @@ export class ForkManager {
152
138
  return accountState;
153
139
  }
154
140
 
155
- /**
156
- * Get a specific resource (with lazy loading)
157
- */
158
141
  async getResource(address: string, resourceType: string): Promise<any> {
159
142
  const normalizedAddress = normalizeAddress(address);
160
143
 
161
- // Check cache first
162
144
  let resource = this.storage.getResource(normalizedAddress, resourceType);
163
145
 
164
146
  if (!resource) {
165
- // Fetch from network
166
147
  if (!this.apiClient) {
167
148
  throw new Error('Fork not initialized. Call initialize() or load() first.');
168
149
  }
@@ -173,7 +154,6 @@ export class ForkManager {
173
154
  const resourceData = await this.apiClient.getAccountResource(normalizedAddress, resourceType);
174
155
  resource = resourceData.data;
175
156
 
176
- // Cache it
177
157
  this.storage.saveResource(normalizedAddress, resourceType, resource);
178
158
  console.log(` ✓ Cached resource ${resourceType}`);
179
159
  } catch (error) {
@@ -188,16 +168,11 @@ export class ForkManager {
188
168
  return resource;
189
169
  }
190
170
 
191
- /**
192
- * Get all resources for an account (with lazy loading)
193
- */
194
171
  async getAllResources(address: string): Promise<Record<string, any>> {
195
172
  const normalizedAddress = normalizeAddress(address);
196
173
 
197
- // Check if we have any cached resources
198
174
  let resources = this.storage.getAllResources(normalizedAddress);
199
175
 
200
- // If no cached resources, fetch all from network
201
176
  if (Object.keys(resources).length === 0) {
202
177
  if (!this.apiClient) {
203
178
  throw new Error('Fork not initialized. Call initialize() or load() first.');
@@ -211,7 +186,6 @@ export class ForkManager {
211
186
  resources[resource.type] = resource.data;
212
187
  }
213
188
 
214
- // Cache them
215
189
  this.storage.saveAllResources(normalizedAddress, resources);
216
190
  console.log(` ✓ Cached ${Object.keys(resources).length} resources`);
217
191
  }
@@ -219,18 +193,13 @@ export class ForkManager {
219
193
  return resources;
220
194
  }
221
195
 
222
- /**
223
- * Set a resource value (for testing/mocking)
224
- */
225
196
  async setResource(address: string, resourceType: string, data: unknown): Promise<void> {
226
197
  const normalizedAddress = normalizeAddress(address);
227
198
  this.storage.saveResource(normalizedAddress, resourceType, data);
228
199
  console.log(` ✓ Updated resource ${resourceType} for ${normalizedAddress}`);
229
200
  }
230
201
 
231
- /**
232
- * Fund an account with coins (adds to existing balance)
233
- */
202
+ /** Adds to the existing balance rather than replacing it. */
234
203
  async fundAccount(address: string, amount: number, coinType: string = '0x1::aptos_coin::AptosCoin'): Promise<void> {
235
204
  const normalizedAddress = normalizeAddress(address);
236
205
  const resourceType = `0x1::coin::CoinStore<${coinType}>`;
@@ -250,7 +219,6 @@ export class ForkManager {
250
219
  throw error;
251
220
  }
252
221
 
253
- // If doesn't exist, create new one
254
222
  coinStore = {
255
223
  coin: { value: '0' },
256
224
  deposit_events: {
@@ -275,15 +243,12 @@ export class ForkManager {
275
243
  };
276
244
  }
277
245
 
278
- // Add to existing balance (instead of replacing it)
279
246
  const currentBalance = BigInt(coinStore.coin.value ?? '0');
280
247
  const newBalance = currentBalance + BigInt(amount);
281
248
  coinStore.coin.value = newBalance.toString();
282
249
 
283
- // Save
284
250
  await this.setResource(normalizedAddress, resourceType, coinStore);
285
251
 
286
- // Also ensure account exists
287
252
  let account = this.storage.getAccount(normalizedAddress);
288
253
  if (!account) {
289
254
  account = {
@@ -296,9 +261,6 @@ export class ForkManager {
296
261
  console.log(` ✓ Funded ${normalizedAddress} with ${amount} coins`);
297
262
  }
298
263
 
299
- /**
300
- * List all accounts in the fork
301
- */
302
264
  listAccounts(): string[] {
303
265
  return this.storage.listAccounts();
304
266
  }
@@ -364,11 +326,9 @@ export class ForkManager {
364
326
  async getOrCreateAccount(address: string): Promise<AccountState> {
365
327
  const normalizedAddress = normalizeAddress(address);
366
328
 
367
- // Try to get existing account
368
329
  try {
369
330
  return await this.getAccount(normalizedAddress);
370
331
  } catch (error) {
371
- // If account doesn't exist, create a minimal one
372
332
  const newAccount: AccountState = {
373
333
  sequenceNumber: '0',
374
334
  authenticationKey: forkAuthKeyPlaceholder(normalizedAddress),
package/src/fork/test.ts CHANGED
@@ -9,7 +9,6 @@ export interface SnapshotOptions {
9
9
  /**
10
10
  * Override the child-process adapter. Test-only — production callers
11
11
  * leave this undefined so the default spawn-based adapter is used.
12
- * Mirrors the M1.3c pattern on `runtime.deployContract`.
13
12
  */
14
13
  adapter?: ChildProcessAdapter;
15
14
  }
@@ -36,16 +36,10 @@ interface HarnessInit {
36
36
  * a Proxy that synchronously throws {@link HarnessDisposedError} on any
37
37
  * post-`cleanup()` call to one of the deployment / script / view methods.
38
38
  *
39
- * Methods `deployCodeObject`, `upgradeCodeObject`, `runViewFunction`,
40
- * and `runMoveScript` are stubbed in M2.1 they throw at runtime until
41
- * M2.2/M2.3 lands. The type surface is complete so callers and docs can
42
- * be written against it ahead of time.
43
- *
44
- * AccountManager note: as of M2.1 the underlying account pool is a
45
- * process-wide static (see `core/AccountManager.ts`). Two Harness
46
- * instances in the same process share account labels; this is the same
47
- * constraint that already governs `setupTestFixture`. A per-Harness pool
48
- * is a future change.
39
+ * AccountManager note: the underlying account pool is a process-wide
40
+ * static (see `core/AccountManager.ts`). Two Harness instances in the
41
+ * same process share account labels; this is the same constraint that
42
+ * already governs `setupTestFixture`.
49
43
  */
50
44
  export class Harness {
51
45
  public readonly mode: HarnessMode;
@@ -128,7 +122,7 @@ export class Harness {
128
122
  * spawned; transactions are submitted to the configured RPC.
129
123
  *
130
124
  * @param network - Named network from movehat.config.ts.
131
- * @param _faucetUrl - Reserved for M2.2 (auto-fund on networks with a faucet).
125
+ * @param _faucetUrl - Reserved for future auto-fund support on networks with a faucet.
132
126
  */
133
127
  static async createLive(network: string, _faucetUrl?: string): Promise<Harness> {
134
128
  const runtime = await initRuntime({ network });
@@ -289,8 +289,6 @@ async function executeMovementMoveObject(
289
289
  }
290
290
 
291
291
  // Parse object address (for deploy-object) and txHash (both flows).
292
- // No captured fixture exists at M2.2 commit time; M4 integration
293
- // tests validate against real CLI output.
294
292
  const objectAddress = opts.fixedAddress ?? parseObjectAddress(deployOut);
295
293
  const txHash = parseTxHash(deployOut);
296
294
 
@@ -361,9 +359,7 @@ async function executeMovementMoveObject(
361
359
  /**
362
360
  * Extract a code-object address from `movement move deploy-object` stdout.
363
361
  *
364
- * Movement CLI typically emits the address in one of these shapes (none
365
- * of them captured at M2.2 commit time — patterns are speculative, with
366
- * M4 integration tests as the validation gate):
362
+ * Movement CLI typically emits the address in one of these shapes:
367
363
  *
368
364
  * - Free text: `Code was successfully deployed to object address 0x…`
369
365
  * - Free text: `Object address: 0x…`
@@ -20,8 +20,7 @@ import type { LocalTestOptions } from "../types/config.js";
20
20
  * @public The `runtime` and `teardown` fields are the supported surface.
21
21
  * `localNode`, `forkServer`, and `forkManager` are exposed for
22
22
  * escape hatches (e.g. mid-test `forkManager.resetState()`) but
23
- * their concrete shapes are considered `@internal` until the M5
24
- * TypeDoc pass formalizes the public API.
23
+ * their concrete shapes are `@internal`.
25
24
  */
26
25
  export interface LocalTestingContext {
27
26
  runtime: MovehatRuntime;
package/src/index.ts CHANGED
@@ -18,6 +18,5 @@ export type { ForkMetadata, AccountState, LedgerInfo, AccountData, AccountResour
18
18
  // Export custom errors
19
19
  export { ModuleAlreadyDeployedError, PostPublishError } from "./errors.js";
20
20
 
21
- // Export Harness (Hardhat-style API — primary public surface from M2 onward)
22
21
  export { Harness, HarnessDisposedError } from "./harness/index.js";
23
22
  export type { HarnessMode } from "./harness/index.js";
@@ -13,7 +13,7 @@ import type {
13
13
  } from "../../utils/childProcessAdapter.js";
14
14
 
15
15
  /**
16
- * Tests for `LocalNodeManager` (M3.3).
16
+ * Tests for `LocalNodeManager`.
17
17
  *
18
18
  * Strategy:
19
19
  * - Inject a fake `ChildProcessAdapter` so we control the spawn
package/src/runtime.ts CHANGED
@@ -93,9 +93,7 @@ export async function initRuntime(
93
93
  adapter?: ChildProcessAdapter;
94
94
  }
95
95
  ): Promise<DeploymentInfo> => {
96
- // Thin orchestrator over Publisher (M1.4 / #79). The 250-line closure
97
- // body lives in core/Publisher.ts and carries the bug fixes for
98
- // #36 / #37 / #38.
96
+ // Thin orchestrator; the actual logic lives in core/Publisher.ts.
99
97
  return new Publisher({ adapter: options?.adapter }).deploy({
100
98
  moduleName,
101
99
  config,
@@ -3,7 +3,7 @@ import { Harness } from "movehat";
3
3
  async function main() {
4
4
  console.log("🚀 Deploying Counter contract...\n");
5
5
 
6
- // Hardhat-style Harness — primary public API since M2.
6
+ // Hardhat-style Harness — the primary public API.
7
7
  // createLive binds to a real running network (testnet / mainnet / a
8
8
  // custom one defined in movehat.config.ts). No local process spawned.
9
9
  const network = process.env.MOVEHAT_NETWORK ?? "testnet";
@@ -11,7 +11,7 @@ describe("Counter Contract", () => {
11
11
  before(async function () {
12
12
  this.timeout(60000); // Allow time for local node startup + deployment
13
13
 
14
- // Hardhat-style Harness — primary public API since M2.
14
+ // Hardhat-style Harness — the primary public API.
15
15
  // createLocal spins up a Movement local node, funds the labeled
16
16
  // accounts from the local faucet, and (via autoDeploy) builds +
17
17
  // publishes the named modules so they're ready to use.
@@ -43,7 +43,7 @@ describe("Counter Contract", () => {
43
43
  const tx = await counter.call(deployer, "init", []);
44
44
  console.log(` Init transaction: ${tx.hash}`);
45
45
 
46
- // Read counter value via harness.runViewFunction (new in M2)
46
+ // Read counter value via harness.runViewFunction
47
47
  const [value] = await harness.runViewFunction({
48
48
  function: `${counter.moduleAddress}::counter::get`,
49
49
  functionArguments: [deployer.accountAddress.toString()],
@@ -51,7 +51,7 @@ export interface MovehatRuntime {
51
51
  getAccountByIndex: (index: number) => Account;
52
52
 
53
53
  // Network switching — returns a new runtime bound to the requested
54
- // network. As of M1.5 there is no module-cached runtime, so callers
55
- // must capture and use the returned instance.
54
+ // network. There is no module-cached runtime, so callers must capture
55
+ // and use the returned instance.
56
56
  switchNetwork: (networkName: string) => Promise<MovehatRuntime>;
57
57
  }
@@ -1,10 +1,6 @@
1
1
  /**
2
2
  * Address normalization helpers shared across the fork code.
3
3
  *
4
- * Two normalization variants live in production today and are preserved here
5
- * with identical semantics so the in-place migration in M1.2 is behavior-
6
- * preserving:
7
- *
8
4
  * - `normalizeAddress` → lowercase + `0x` + left-pad to 64 hex chars.
9
5
  * Used by `fork/manager.ts` for storage keys.
10
6
  * - `normalizeAddressShort` → lowercase + `0x`, no padding.
@@ -99,10 +99,9 @@ class DefaultChildProcessAdapter implements ChildProcessAdapter {
99
99
  run(input: RunInput): Promise<RunResult> {
100
100
  // Skip the default 5-minute timeout when the caller wires stdio
101
101
  // through to the terminal — interactive sessions (mocha, tsx scripts,
102
- // `movement move test`, `pnpm install`) routinely exceed 5 minutes and
103
- // SIGTERM'ing them silently is a regression vs the direct-spawn code
104
- // these callers used before M1.3a. An explicitly-passed `timeoutMs`
105
- // is always honored, regardless of `inheritStdio`.
102
+ // `movement move test`, `pnpm install`) routinely exceed 5 minutes
103
+ // and SIGTERM'ing them silently would be a regression. An explicit
104
+ // `timeoutMs` is always honored, regardless of `inheritStdio`.
106
105
  const timeoutMs =
107
106
  input.timeoutMs ?? (input.inheritStdio ? undefined : DEFAULT_TIMEOUT_MS);
108
107