movehat 0.2.6 → 0.2.8
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/dist/cli.js +1 -1
- package/dist/commands/fork/fund.js +3 -1
- package/dist/commands/fork/serve.js +10 -5
- package/dist/commands/test-move.js +6 -3
- package/dist/core/AccountManager.d.ts +121 -139
- package/dist/core/AccountManager.js +217 -158
- package/dist/fork/api.d.ts +1 -1
- package/dist/fork/api.js +9 -4
- package/dist/fork/manager.d.ts +2 -2
- package/dist/fork/manager.js +4 -8
- package/dist/fork/storage.js +5 -4
- package/dist/fork/test.d.ts +1 -1
- package/dist/fork/validation.d.ts +9 -0
- package/dist/fork/validation.js +88 -0
- package/dist/harness/Harness.d.ts +35 -6
- package/dist/harness/Harness.js +36 -5
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/helpers/move-tests.js +8 -5
- package/dist/helpers/setup.js +6 -3
- package/dist/helpers/setupLocalTesting.d.ts +2 -2
- package/dist/helpers/setupLocalTesting.js +55 -24
- package/dist/helpers/testFixtures.d.ts +5 -4
- package/dist/helpers/testFixtures.js +4 -5
- package/dist/helpers/version-check.js +4 -2
- package/dist/index.d.ts +3 -1
- package/dist/node/MoveliteManager.d.ts +18 -0
- package/dist/node/MoveliteManager.js +152 -0
- package/dist/node/NodeProvider.d.ts +9 -0
- package/dist/node/NodeProvider.js +1 -0
- package/dist/runtime.d.ts +13 -0
- package/dist/runtime.js +8 -4
- package/dist/templates/.mocharc.json +1 -0
- package/dist/templates/tests/Counter.test.ts +12 -14
- package/dist/templates/tests/setup.ts +34 -0
- package/dist/types/config.d.ts +2 -0
- package/dist/types/fork.d.ts +24 -0
- package/dist/types/runtime.d.ts +2 -0
- package/package.json +4 -1
package/dist/cli.js
CHANGED
|
@@ -66,7 +66,7 @@ program
|
|
|
66
66
|
});
|
|
67
67
|
program
|
|
68
68
|
.command('compile')
|
|
69
|
-
.description('Compile Move smart contracts
|
|
69
|
+
.description('Compile Move smart contracts (auto-detects named addresses and updates Move.toml)')
|
|
70
70
|
.action(compileCommand);
|
|
71
71
|
program
|
|
72
72
|
.command('run <script>')
|
|
@@ -34,9 +34,11 @@ export default async function forkFundCommand(options) {
|
|
|
34
34
|
// Verify
|
|
35
35
|
const resourceType = `0x1::coin::CoinStore<${coinType}>`;
|
|
36
36
|
const coinStore = await forkManager.getResource(options.account, resourceType);
|
|
37
|
+
const { assertCoinStore } = await import('../../fork/validation.js');
|
|
38
|
+
const validated = assertCoinStore(coinStore);
|
|
37
39
|
logger.newline();
|
|
38
40
|
logger.success("Account funded successfully!");
|
|
39
|
-
logger.plain(` New balance: ${
|
|
41
|
+
logger.plain(` New balance: ${validated.coin.value}`);
|
|
40
42
|
logger.newline();
|
|
41
43
|
}
|
|
42
44
|
catch (error) {
|
|
@@ -2,6 +2,7 @@ import { join } from 'path';
|
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { loadUserConfig } from '../../core/config.js';
|
|
4
4
|
import { ForkServer } from '../../fork/server.js';
|
|
5
|
+
import { logger } from '../../ui/index.js';
|
|
5
6
|
/**
|
|
6
7
|
* Fork serve command: Start a local RPC server serving the fork
|
|
7
8
|
*/
|
|
@@ -26,9 +27,11 @@ export default async function forkServeCommand(options) {
|
|
|
26
27
|
}
|
|
27
28
|
// Verify fork exists
|
|
28
29
|
if (!existsSync(join(forkPath, 'metadata.json'))) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
logger.newline();
|
|
31
|
+
logger.error(`Fork not found at ${forkPath}`);
|
|
32
|
+
logger.newline();
|
|
33
|
+
logger.error("Create a fork first with:");
|
|
34
|
+
logger.error(" movehat fork create --network <network> --name <name>");
|
|
32
35
|
process.exit(1);
|
|
33
36
|
}
|
|
34
37
|
// Get port (already validated by Commander's parsePort in cli.ts)
|
|
@@ -38,7 +41,8 @@ export default async function forkServeCommand(options) {
|
|
|
38
41
|
const server = new ForkServer(forkPath, port, host);
|
|
39
42
|
// Handle graceful shutdown (use 'once' to prevent duplicate shutdowns)
|
|
40
43
|
const shutdown = async () => {
|
|
41
|
-
|
|
44
|
+
logger.newline();
|
|
45
|
+
logger.step("Shutting down...");
|
|
42
46
|
await server.stop();
|
|
43
47
|
process.exit(0);
|
|
44
48
|
};
|
|
@@ -59,7 +63,8 @@ export default async function forkServeCommand(options) {
|
|
|
59
63
|
}
|
|
60
64
|
catch (error) {
|
|
61
65
|
const msg = error instanceof Error ? error.message : String(error);
|
|
62
|
-
|
|
66
|
+
logger.newline();
|
|
67
|
+
logger.error(`Error starting fork server: ${msg}`);
|
|
63
68
|
process.exit(1);
|
|
64
69
|
}
|
|
65
70
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { runMoveTests } from "../helpers/move-tests.js";
|
|
2
|
+
import { logger } from "../ui/index.js";
|
|
2
3
|
export default async function testMoveCommand(options = {}) {
|
|
3
4
|
try {
|
|
4
|
-
|
|
5
|
+
logger.step("Running Move unit tests...");
|
|
6
|
+
logger.newline();
|
|
5
7
|
await runMoveTests({
|
|
6
8
|
filter: options.filter,
|
|
7
9
|
ignoreWarnings: options.ignoreWarnings,
|
|
@@ -10,10 +12,11 @@ export default async function testMoveCommand(options = {}) {
|
|
|
10
12
|
process.exit(0);
|
|
11
13
|
}
|
|
12
14
|
catch (err) {
|
|
13
|
-
|
|
15
|
+
logger.newline();
|
|
16
|
+
logger.error("Move tests failed");
|
|
14
17
|
const msg = err instanceof Error ? err.message : String(err);
|
|
15
18
|
if (msg) {
|
|
16
|
-
|
|
19
|
+
logger.error(` ${msg}`);
|
|
17
20
|
}
|
|
18
21
|
process.exit(1);
|
|
19
22
|
}
|
|
@@ -14,183 +14,165 @@ export interface SaveAccountPoolOptions {
|
|
|
14
14
|
*/
|
|
15
15
|
includeImported?: boolean | undefined;
|
|
16
16
|
}
|
|
17
|
+
export interface AccountManagerOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Filesystem location where `saveAccountPool` writes `test-pool.json`
|
|
20
|
+
* and `loadAccountPool` reads from. When omitted, the path is computed
|
|
21
|
+
* LAZILY on each call from `join(process.cwd(), ".movehat", "accounts")`
|
|
22
|
+
* — so `process.chdir()` between construction and pool I/O is respected.
|
|
23
|
+
*
|
|
24
|
+
* Pass an explicit value when per-instance isolation matters (parallel
|
|
25
|
+
* test files, harness pools that must not collide with another suite's).
|
|
26
|
+
*
|
|
27
|
+
* The process-wide static facade exposed on the `AccountManager` class
|
|
28
|
+
* itself uses a separate singleton whose `poolPath` is EAGERLY captured
|
|
29
|
+
* at module-import time. That preserves the legacy F8(b) behavior for
|
|
30
|
+
* any code still on the static API during the 0.2.7 deprecation window;
|
|
31
|
+
* the static facade is removed in 0.3.0.
|
|
32
|
+
*/
|
|
33
|
+
poolPath?: string | undefined;
|
|
34
|
+
}
|
|
17
35
|
/**
|
|
18
36
|
* Centralized Account Manager for movehat
|
|
19
37
|
*
|
|
20
38
|
* Manages all account creation, loading, and lifecycle operations.
|
|
21
|
-
* Provides a pool of reusable test accounts with labels for better test
|
|
39
|
+
* Provides a pool of reusable test accounts with labels for better test
|
|
40
|
+
* readability.
|
|
41
|
+
*
|
|
42
|
+
* Two API surfaces are exposed:
|
|
43
|
+
*
|
|
44
|
+
* **Instance API (recommended; M9.1+)** — `new AccountManager(options?)`
|
|
45
|
+
* gives a fully isolated pool. Two instances in the same process have
|
|
46
|
+
* independent labelMaps, private-key maps, and account pools. Each
|
|
47
|
+
* `Harness` constructed in 0.3.0+ will own one of these; user code
|
|
48
|
+
* accesses labeled accounts via `harness.accounts.<label>` (Harness
|
|
49
|
+
* snapshots them at construction time).
|
|
50
|
+
*
|
|
51
|
+
* **Static facade (deprecated; will be removed in 0.3.0)** — every
|
|
52
|
+
* former static method (`AccountManager.createAccount(...)`, etc.) still
|
|
53
|
+
* works and forwards to a single process-wide singleton. This preserves
|
|
54
|
+
* the existing label-sharing behavior across calls during the
|
|
55
|
+
* deprecation window. Migration target is the instance API; see M9 meta
|
|
56
|
+
* (#270) and migration guide at `/docs/upgrading/0.3.0` (published in
|
|
57
|
+
* M9.4).
|
|
22
58
|
*/
|
|
23
59
|
export declare class AccountManager {
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
private
|
|
28
|
-
private
|
|
29
|
-
private
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
60
|
+
private readonly pool;
|
|
61
|
+
private readonly privateKeys;
|
|
62
|
+
private readonly labelMap;
|
|
63
|
+
private readonly generatedAccountAddresses;
|
|
64
|
+
private poolLoaded;
|
|
65
|
+
private readonly poolPathOverride;
|
|
66
|
+
constructor(options?: AccountManagerOptions);
|
|
67
|
+
/**
|
|
68
|
+
* Resolved pool directory. When the caller supplied an explicit
|
|
69
|
+
* `poolPath` to the constructor, that value is returned verbatim.
|
|
70
|
+
* Otherwise the path is computed LAZILY from the current
|
|
71
|
+
* `process.cwd()` on each access — so `process.chdir()` performed
|
|
72
|
+
* between construction and pool I/O takes effect, unlike the legacy
|
|
73
|
+
* static-only API which captured cwd at module import time
|
|
74
|
+
* (audit finding F8(b)).
|
|
75
|
+
*/
|
|
76
|
+
private get poolPath();
|
|
77
|
+
/**
|
|
78
|
+
* Get a test account from the pool. If label is provided and exists,
|
|
79
|
+
* returns that account. Otherwise creates a new account with the
|
|
80
|
+
* optional label.
|
|
81
|
+
*
|
|
82
|
+
* @param label Optional label for the account (e.g., "alice", "bob")
|
|
35
83
|
* @returns An Account instance
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* const alice = AccountManager.getTestAccount("alice");
|
|
39
|
-
* const randomAccount = AccountManager.getTestAccount();
|
|
40
84
|
*/
|
|
41
|
-
|
|
85
|
+
getTestAccount(label?: string): Account;
|
|
42
86
|
/**
|
|
43
|
-
* Create a new account and optionally add it to the pool with a
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* @param fund Whether to fund the account (handled externally)
|
|
47
|
-
* @returns A new Account instance
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* const deployer = AccountManager.createAccount("deployer");
|
|
51
|
-
* const bob = AccountManager.createAccount("bob", true);
|
|
87
|
+
* Create a new account and optionally add it to the pool with a
|
|
88
|
+
* label. The `fund` parameter is accepted for API symmetry; actual
|
|
89
|
+
* funding is the caller's responsibility.
|
|
52
90
|
*/
|
|
53
|
-
|
|
91
|
+
createAccount(label?: string, _fund?: boolean): Account;
|
|
54
92
|
/**
|
|
55
|
-
* Get an account by its label
|
|
56
|
-
*
|
|
57
|
-
* @param label The label to look up
|
|
58
|
-
* @returns The Account if found, undefined otherwise
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* const alice = AccountManager.getAccountByLabel("alice");
|
|
62
|
-
* if (alice) {
|
|
63
|
-
* console.log(`Alice's address: ${alice.accountAddress.toString()}`);
|
|
64
|
-
* }
|
|
93
|
+
* Get an account by its label, or undefined if not present.
|
|
65
94
|
*/
|
|
66
|
-
|
|
95
|
+
getAccountByLabel(label: string): Account | undefined;
|
|
67
96
|
/**
|
|
68
|
-
* Load account from environment variable
|
|
69
|
-
*
|
|
70
|
-
* @param envVar The environment variable name (defaults to "PRIVATE_KEY")
|
|
71
|
-
* @returns Account instance
|
|
72
|
-
* @throws Error if environment variable is not set
|
|
97
|
+
* Load account from environment variable.
|
|
73
98
|
*
|
|
74
|
-
* @
|
|
75
|
-
* const account = AccountManager.loadAccountFromEnv("MH_PRIVATE_KEY");
|
|
99
|
+
* @throws Error if the environment variable is not set
|
|
76
100
|
*/
|
|
77
|
-
|
|
101
|
+
loadAccountFromEnv(envVar?: string): Account;
|
|
78
102
|
/**
|
|
79
|
-
* Load account from a private key hex string
|
|
80
|
-
*
|
|
81
|
-
* @param privateKeyHex The private key as a hex string (with or without 0x prefix)
|
|
82
|
-
* @returns Account instance
|
|
83
|
-
*
|
|
84
|
-
* @example
|
|
85
|
-
* const account = AccountManager.loadAccountFromPrivateKey("0xabc123...");
|
|
103
|
+
* Load account from a private key hex string (with or without 0x prefix).
|
|
86
104
|
*/
|
|
87
|
-
|
|
105
|
+
loadAccountFromPrivateKey(privateKeyHex: string): Account;
|
|
88
106
|
/**
|
|
89
|
-
* Load all accounts from movehat config
|
|
90
|
-
*
|
|
91
|
-
* @param config The resolved MovehatConfig
|
|
92
|
-
* @returns Array of Account instances
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* const config = await resolveNetworkConfig(userConfig);
|
|
96
|
-
* const accounts = AccountManager.loadAccountsFromConfig(config);
|
|
107
|
+
* Load all accounts from movehat config.
|
|
97
108
|
*/
|
|
98
|
-
|
|
109
|
+
loadAccountsFromConfig(config: MovehatConfig): Account[];
|
|
99
110
|
/**
|
|
100
|
-
* Get all labeled accounts in the pool
|
|
101
|
-
*
|
|
102
|
-
* @returns Record of label to Account mappings
|
|
103
|
-
*
|
|
104
|
-
* @example
|
|
105
|
-
* const labeled = AccountManager.getLabeledAccounts();
|
|
106
|
-
* console.log(`Deployer: ${labeled.deployer?.accountAddress.toString()}`);
|
|
111
|
+
* Get all labeled accounts in the pool.
|
|
107
112
|
*/
|
|
108
|
-
|
|
113
|
+
getLabeledAccounts(): Record<string, Account>;
|
|
109
114
|
/**
|
|
110
|
-
* Save the current account pool to disk for persistence
|
|
111
|
-
*
|
|
112
|
-
* @param poolPath Optional custom path (defaults to .movehat/accounts)
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* AccountManager.saveAccountPool();
|
|
115
|
+
* Save the current account pool to disk for persistence.
|
|
116
116
|
*/
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
saveAccountPool(): void;
|
|
118
|
+
saveAccountPool(poolPath: string): void;
|
|
119
|
+
saveAccountPool(options: SaveAccountPoolOptions): void;
|
|
120
|
+
saveAccountPool(poolPath: string, options: SaveAccountPoolOptions): void;
|
|
121
121
|
/**
|
|
122
|
-
* Load account pool from disk
|
|
123
|
-
*
|
|
124
|
-
* @param poolPath Optional custom path (defaults to .movehat/accounts)
|
|
125
|
-
* @returns true if pool was loaded, false if file doesn't exist
|
|
126
|
-
*
|
|
127
|
-
* @example
|
|
128
|
-
* if (AccountManager.loadAccountPool()) {
|
|
129
|
-
* console.log("Pool loaded successfully");
|
|
130
|
-
* }
|
|
122
|
+
* Load account pool from disk. Returns true if a pool file was found
|
|
123
|
+
* and parsed, false if the file does not exist or parsing failed.
|
|
131
124
|
*/
|
|
132
|
-
|
|
125
|
+
loadAccountPool(poolPath?: string): boolean;
|
|
133
126
|
/**
|
|
134
|
-
* Clear the entire account pool
|
|
135
|
-
* Useful for test isolation
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* after(() => {
|
|
139
|
-
* AccountManager.clearPool();
|
|
140
|
-
* });
|
|
127
|
+
* Clear the entire account pool. Useful for test isolation.
|
|
141
128
|
*/
|
|
142
|
-
|
|
129
|
+
clearPool(): void;
|
|
143
130
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* @returns Number of accounts in the pool
|
|
131
|
+
* Number of accounts in the pool.
|
|
147
132
|
*/
|
|
148
|
-
|
|
133
|
+
getPoolSize(): number;
|
|
149
134
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* @returns Array of all Account instances
|
|
135
|
+
* All accounts in the pool.
|
|
153
136
|
*/
|
|
154
|
-
|
|
137
|
+
getAllAccounts(): Account[];
|
|
155
138
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* @param label The label to check
|
|
159
|
-
* @returns true if label exists, false otherwise
|
|
139
|
+
* Whether a label is currently bound to an account in this pool.
|
|
160
140
|
*/
|
|
161
|
-
|
|
141
|
+
hasLabel(label: string): boolean;
|
|
162
142
|
/**
|
|
163
|
-
* Get or create an account with a specific label
|
|
164
|
-
* If the label exists, returns the existing account
|
|
165
|
-
* Otherwise creates a new account with that label
|
|
166
|
-
*
|
|
167
|
-
* @param label The label for the account
|
|
168
|
-
* @returns Account instance
|
|
169
|
-
*
|
|
170
|
-
* @example
|
|
171
|
-
* const alice = AccountManager.getOrCreateLabeled("alice");
|
|
172
|
-
* const aliceAgain = AccountManager.getOrCreateLabeled("alice"); // Same account
|
|
143
|
+
* Get or create an account with a specific label.
|
|
173
144
|
*/
|
|
174
|
-
|
|
145
|
+
getOrCreateLabeled(label: string): Account;
|
|
175
146
|
/**
|
|
176
|
-
* Batch create multiple labeled accounts
|
|
177
|
-
*
|
|
178
|
-
* @param labels Array of labels to create
|
|
179
|
-
* @returns Record of label to Account mappings
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* const accounts = AccountManager.createBatch(["alice", "bob", "charlie"]);
|
|
183
|
-
* console.log(accounts.alice.accountAddress.toString());
|
|
147
|
+
* Batch create multiple labeled accounts.
|
|
184
148
|
*/
|
|
185
|
-
|
|
149
|
+
createBatch(labels: readonly string[]): Record<string, Account>;
|
|
186
150
|
/**
|
|
187
|
-
* Export account private keys for backup/sharing
|
|
188
|
-
* WARNING: Only use this for test accounts, never production keys
|
|
189
|
-
*
|
|
190
|
-
* @param labels Optional array of labels to export (exports all if not provided)
|
|
191
|
-
* @returns Record of label/address to private key hex string
|
|
151
|
+
* Export account private keys for backup/sharing.
|
|
152
|
+
* WARNING: Only use this for test accounts, never production keys.
|
|
192
153
|
*/
|
|
154
|
+
exportPrivateKeys(labels?: string[]): Record<string, string>;
|
|
155
|
+
private accountFromPrivateKey;
|
|
156
|
+
private trackAccount;
|
|
157
|
+
static getTestAccount(label?: string): Account;
|
|
158
|
+
static createAccount(label?: string, fund?: boolean): Account;
|
|
159
|
+
static getAccountByLabel(label: string): Account | undefined;
|
|
160
|
+
static loadAccountFromEnv(envVar?: string): Account;
|
|
161
|
+
static loadAccountFromPrivateKey(privateKeyHex: string): Account;
|
|
162
|
+
static loadAccountsFromConfig(config: MovehatConfig): Account[];
|
|
163
|
+
static getLabeledAccounts(): Record<string, Account>;
|
|
164
|
+
static saveAccountPool(): void;
|
|
165
|
+
static saveAccountPool(poolPath: string): void;
|
|
166
|
+
static saveAccountPool(options: SaveAccountPoolOptions): void;
|
|
167
|
+
static saveAccountPool(poolPath: string, options: SaveAccountPoolOptions): void;
|
|
168
|
+
static loadAccountPool(poolPath?: string): boolean;
|
|
169
|
+
static clearPool(): void;
|
|
170
|
+
static getPoolSize(): number;
|
|
171
|
+
static getAllAccounts(): Account[];
|
|
172
|
+
static hasLabel(label: string): boolean;
|
|
173
|
+
static getOrCreateLabeled(label: string): Account;
|
|
174
|
+
static createBatch(labels: readonly string[]): Record<string, Account>;
|
|
193
175
|
static exportPrivateKeys(labels?: string[]): Record<string, string>;
|
|
194
|
-
private static accountFromPrivateKey;
|
|
195
|
-
private static trackAccount;
|
|
196
176
|
}
|
|
177
|
+
/** @internal — test-only. Resets the once-per-method dedup Set. */
|
|
178
|
+
export declare function _resetDeprecationWarnings(): void;
|