movehat 0.1.2 → 0.1.4
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 +159 -80
- package/bin/movehat.js +10 -0
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +40 -3
- package/dist/commands/run.js.map +1 -1
- package/dist/core/AccountManager.d.ts +186 -0
- package/dist/core/AccountManager.d.ts.map +1 -0
- package/dist/core/AccountManager.js +363 -0
- package/dist/core/AccountManager.js.map +1 -0
- package/dist/fork/manager.d.ts +33 -0
- package/dist/fork/manager.d.ts.map +1 -1
- package/dist/fork/manager.js +61 -0
- package/dist/fork/manager.js.map +1 -1
- package/dist/fork/storage.d.ts +10 -0
- package/dist/fork/storage.d.ts.map +1 -1
- package/dist/fork/storage.js +28 -1
- package/dist/fork/storage.js.map +1 -1
- package/dist/helpers/index.d.ts +8 -1
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +4 -0
- package/dist/helpers/index.js.map +1 -1
- package/dist/helpers/setup.d.ts.map +1 -1
- package/dist/helpers/setup.js +5 -4
- package/dist/helpers/setup.js.map +1 -1
- package/dist/helpers/setupLocalTesting.d.ts +60 -0
- package/dist/helpers/setupLocalTesting.d.ts.map +1 -0
- package/dist/helpers/setupLocalTesting.js +277 -0
- package/dist/helpers/setupLocalTesting.js.map +1 -0
- package/dist/helpers/testFixtures.d.ts +115 -0
- package/dist/helpers/testFixtures.d.ts.map +1 -0
- package/dist/helpers/testFixtures.js +163 -0
- package/dist/helpers/testFixtures.js.map +1 -0
- package/dist/helpers/version-check.d.ts.map +1 -1
- package/dist/helpers/version-check.js +4 -0
- package/dist/helpers/version-check.js.map +1 -1
- package/dist/node/LocalNodeManager.d.ts +68 -0
- package/dist/node/LocalNodeManager.d.ts.map +1 -0
- package/dist/node/LocalNodeManager.js +237 -0
- package/dist/node/LocalNodeManager.js.map +1 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +91 -46
- package/dist/runtime.js.map +1 -1
- package/dist/templates/README.md +17 -4
- package/dist/templates/move/sources/Counter.move +12 -4
- package/dist/templates/tests/Counter.test.ts +98 -57
- package/dist/types/config.d.ts +24 -0
- package/dist/types/config.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/commands/run.ts +43 -3
- package/src/core/AccountManager.ts +439 -0
- package/src/fork/manager.ts +74 -0
- package/src/fork/storage.ts +33 -1
- package/src/helpers/index.ts +18 -1
- package/src/helpers/setup.ts +4 -3
- package/src/helpers/setupLocalTesting.ts +335 -0
- package/src/helpers/testFixtures.ts +222 -0
- package/src/helpers/version-check.ts +5 -0
- package/src/node/LocalNodeManager.ts +297 -0
- package/src/runtime.ts +108 -47
- package/src/templates/README.md +17 -4
- package/src/templates/move/sources/Counter.move +12 -4
- package/src/templates/tests/Counter.test.ts +98 -57
- package/src/types/config.ts +32 -0
package/README.md
CHANGED
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
|
-
- **
|
|
10
|
+
- **Local Node Testing** - Run a real Movement blockchain locally for testing (just like Hardhat!)
|
|
11
|
+
- **Dual Testing Modes** - Choose between `local-node` (full blockchain) or `fork` (read-only snapshot)
|
|
12
|
+
- **Auto-Deploy in Tests** - Contracts deploy automatically when tests run - zero manual setup
|
|
13
|
+
- **setupTestFixture Helper** - High-level API for test setup with type-safe contracts
|
|
14
|
+
- **Auto-detection of Named Addresses** - Automatically detects and configures addresses from Move code
|
|
11
15
|
- **Quick Start** - Scaffold new Move projects in seconds
|
|
12
16
|
- **TypeScript Testing** - Write integration tests with familiar tools (Mocha, Chai)
|
|
13
|
-
- **Built-in Helpers** - Interact with contracts easily
|
|
14
17
|
- **Movement CLI Integration** - Seamless compilation and deployment
|
|
15
|
-
- **Hot Reload** - Test changes instantly with watch mode
|
|
16
18
|
|
|
17
19
|
## Prerequisites
|
|
18
20
|
|
|
@@ -102,140 +104,217 @@ MH_NETWORK=testnet
|
|
|
102
104
|
|
|
103
105
|
## Writing Tests
|
|
104
106
|
|
|
105
|
-
Movehat
|
|
107
|
+
Movehat runs tests on a **real local Movement blockchain** (just like Hardhat!):
|
|
106
108
|
|
|
107
109
|
```typescript
|
|
108
|
-
import { describe, it, before } from "mocha";
|
|
110
|
+
import { describe, it, before, after } from "mocha";
|
|
109
111
|
import { expect } from "chai";
|
|
110
|
-
import {
|
|
112
|
+
import { setupTestFixture, teardownTestFixture, type TestFixture } from "movehat/helpers";
|
|
111
113
|
|
|
112
114
|
describe("Counter Contract", () => {
|
|
113
|
-
let
|
|
114
|
-
let contractAddress: string;
|
|
115
|
+
let fixture: TestFixture<'counter'>;
|
|
115
116
|
|
|
116
117
|
before(async function () {
|
|
117
|
-
this.timeout(
|
|
118
|
+
this.timeout(60000); // Allow time for local node startup + deployment
|
|
119
|
+
|
|
120
|
+
// Setup local testing environment with auto-deployment
|
|
121
|
+
// This will:
|
|
122
|
+
// 1. Start a local Movement blockchain node
|
|
123
|
+
// 2. Generate and fund test accounts from local faucet
|
|
124
|
+
// 3. Auto-deploy the counter module
|
|
125
|
+
// 4. Return everything ready to use
|
|
126
|
+
fixture = await setupTestFixture(['counter'] as const, ['alice', 'bob']);
|
|
127
|
+
|
|
128
|
+
console.log(`\n✅ Testing on local blockchain`);
|
|
129
|
+
console.log(` Deployer: ${fixture.accounts.deployer.accountAddress.toString()}`);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("should initialize with value 0", async () => {
|
|
133
|
+
const counter = fixture.contracts.counter; // Type-safe, no `!` needed
|
|
134
|
+
const deployer = fixture.accounts.deployer;
|
|
135
|
+
|
|
136
|
+
// Read counter value (returns string from view function)
|
|
137
|
+
const value = await counter.view<string>("get", [
|
|
138
|
+
deployer.accountAddress.toString()
|
|
139
|
+
]);
|
|
140
|
+
|
|
141
|
+
expect(parseInt(value)).to.equal(0);
|
|
142
|
+
});
|
|
118
143
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
144
|
+
it("should increment counter", async () => {
|
|
145
|
+
const counter = fixture.contracts.counter;
|
|
146
|
+
const deployer = fixture.accounts.deployer;
|
|
147
|
+
|
|
148
|
+
// Increment the counter (real transaction on local blockchain!)
|
|
149
|
+
const tx = await counter.call(deployer, "increment", []);
|
|
150
|
+
console.log(` Transaction: ${tx.hash}`);
|
|
151
|
+
|
|
152
|
+
// Read new value
|
|
153
|
+
const value = await counter.view<string>("get", [
|
|
154
|
+
deployer.accountAddress.toString()
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
expect(parseInt(value)).to.equal(1);
|
|
123
158
|
});
|
|
124
159
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
// Build transaction
|
|
129
|
-
const transaction = await mh.aptos.transaction.build.simple({
|
|
130
|
-
sender: mh.account.accountAddress,
|
|
131
|
-
data: {
|
|
132
|
-
function: `${contractAddress}::counter::init`,
|
|
133
|
-
functionArguments: []
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// Simulate transaction (no gas cost, instant)
|
|
138
|
-
const [simulation] = await mh.aptos.transaction.simulate.simple({
|
|
139
|
-
signerPublicKey: mh.account.publicKey,
|
|
140
|
-
transaction
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Verify simulation succeeded
|
|
144
|
-
expect(simulation.success).to.be.true;
|
|
145
|
-
console.log(`Gas used: ${simulation.gas_used}`);
|
|
160
|
+
after(async () => {
|
|
161
|
+
// Cleanup: Stop local node and clear account pool
|
|
162
|
+
await teardownTestFixture();
|
|
146
163
|
});
|
|
147
164
|
});
|
|
148
165
|
```
|
|
149
166
|
|
|
150
|
-
**Benefits of
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
-
|
|
155
|
-
-
|
|
167
|
+
**Benefits of Local Node Testing:**
|
|
168
|
+
- Real blockchain with actual state changes
|
|
169
|
+
- Test real transactions (not just simulations)
|
|
170
|
+
- Auto-deploy contracts for each test run
|
|
171
|
+
- Type-safe contract access (no `!` operator needed)
|
|
172
|
+
- Automatic cleanup after tests
|
|
173
|
+
- Just like Hardhat - zero manual setup
|
|
156
174
|
|
|
157
175
|
## Writing Deployment Scripts
|
|
158
176
|
|
|
159
177
|
```typescript
|
|
160
|
-
import {
|
|
178
|
+
import { getMovehat } from "movehat";
|
|
161
179
|
|
|
162
180
|
async function main() {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
console.log(
|
|
174
|
-
|
|
181
|
+
const mh = await getMovehat();
|
|
182
|
+
|
|
183
|
+
console.log("Deploying from:", mh.account.accountAddress.toString());
|
|
184
|
+
console.log("Network:", mh.config.network);
|
|
185
|
+
|
|
186
|
+
// Deploy (publish) the module
|
|
187
|
+
// Movehat automatically checks if already deployed
|
|
188
|
+
const deployment = await mh.deployContract("counter");
|
|
189
|
+
|
|
190
|
+
console.log("Module deployed at:", deployment.address);
|
|
191
|
+
console.log("Transaction:", deployment.txHash);
|
|
192
|
+
|
|
193
|
+
// Get contract instance
|
|
194
|
+
const contract = mh.getContract(deployment.address, "counter");
|
|
195
|
+
|
|
175
196
|
// Initialize the counter
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
console.log(`Counter initialized successfully!`);
|
|
181
|
-
|
|
197
|
+
await contract.call(mh.account, "init", []);
|
|
198
|
+
|
|
199
|
+
console.log("Counter initialized!");
|
|
200
|
+
|
|
182
201
|
// Verify
|
|
183
|
-
const value = await
|
|
184
|
-
|
|
202
|
+
const value = await contract.view<string>("get", [
|
|
203
|
+
mh.account.accountAddress.toString()
|
|
185
204
|
]);
|
|
186
|
-
|
|
205
|
+
|
|
187
206
|
console.log(`Initial counter value: ${value}`);
|
|
188
207
|
}
|
|
189
208
|
|
|
190
209
|
main().catch((error) => {
|
|
191
|
-
console.error(
|
|
210
|
+
console.error(error);
|
|
192
211
|
process.exit(1);
|
|
193
212
|
});
|
|
194
213
|
```
|
|
195
214
|
|
|
196
215
|
## API Reference
|
|
197
216
|
|
|
198
|
-
### Helpers
|
|
217
|
+
### Testing Helpers
|
|
199
218
|
|
|
200
|
-
#### `
|
|
219
|
+
#### `setupTestFixture(modules, accountLabels, options?)`
|
|
201
220
|
|
|
202
|
-
|
|
221
|
+
High-level API for setting up local testing with auto-deployment. Returns type-safe fixture with contracts and accounts.
|
|
203
222
|
|
|
204
223
|
```typescript
|
|
205
|
-
|
|
206
|
-
|
|
224
|
+
// Setup with type inference
|
|
225
|
+
const fixture = await setupTestFixture(
|
|
226
|
+
['counter'] as const, // Modules to deploy
|
|
227
|
+
['alice', 'bob'] // Additional account labels
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
// Access type-safe contracts (no `!` needed)
|
|
231
|
+
const counter = fixture.contracts.counter;
|
|
232
|
+
|
|
233
|
+
// Access accounts
|
|
234
|
+
const deployer = fixture.accounts.deployer;
|
|
235
|
+
const alice = fixture.accounts.alice;
|
|
236
|
+
|
|
237
|
+
// Options (all optional)
|
|
238
|
+
const fixture = await setupTestFixture(['counter'] as const, ['alice'], {
|
|
239
|
+
mode: 'fork', // 'local-node' (default) or 'fork'
|
|
240
|
+
defaultBalance: 100_000_000, // Balance per account in octas
|
|
241
|
+
nodeForceRestart: true, // Restart node on each run
|
|
242
|
+
// ... see LocalTestOptions for more
|
|
243
|
+
});
|
|
207
244
|
```
|
|
208
245
|
|
|
209
|
-
#### `
|
|
246
|
+
#### `setupLocalTesting(options?)`
|
|
210
247
|
|
|
211
|
-
|
|
248
|
+
Lower-level API for setting up local testing environment. Returns MovehatRuntime.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { setupLocalTesting } from "movehat/helpers";
|
|
252
|
+
|
|
253
|
+
// Local node mode (default) - Full blockchain
|
|
254
|
+
const mh = await setupLocalTesting({
|
|
255
|
+
mode: 'local-node',
|
|
256
|
+
accountLabels: ['deployer', 'alice', 'bob'],
|
|
257
|
+
autoDeploy: ['counter'], // Auto-deploy modules
|
|
258
|
+
autoFund: true,
|
|
259
|
+
defaultBalance: 100_000_000
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// Fork mode - Read-only snapshot
|
|
263
|
+
const mh = await setupLocalTesting({
|
|
264
|
+
mode: 'fork',
|
|
265
|
+
forkNetwork: 'testnet',
|
|
266
|
+
forkName: 'my-fork',
|
|
267
|
+
accountLabels: ['alice', 'bob'],
|
|
268
|
+
// Note: autoDeploy doesn't work in fork mode
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### `teardownTestFixture()`
|
|
273
|
+
|
|
274
|
+
Cleanup function to stop local node and clear accounts.
|
|
212
275
|
|
|
213
276
|
```typescript
|
|
214
|
-
|
|
277
|
+
after(async () => {
|
|
278
|
+
await teardownTestFixture();
|
|
279
|
+
});
|
|
215
280
|
```
|
|
216
281
|
|
|
217
|
-
#### `
|
|
282
|
+
#### `stopLocalTesting()`
|
|
218
283
|
|
|
219
|
-
|
|
284
|
+
Stops the local testing environment (for lower-level API).
|
|
220
285
|
|
|
221
286
|
```typescript
|
|
222
|
-
|
|
287
|
+
await stopLocalTesting();
|
|
223
288
|
```
|
|
224
289
|
|
|
225
|
-
|
|
290
|
+
### Contract Interaction
|
|
226
291
|
|
|
227
|
-
|
|
292
|
+
#### `mh.getContract(moduleAddress, moduleName)`
|
|
293
|
+
|
|
294
|
+
Creates a contract wrapper for easy interaction.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
const mh = await getMovehat();
|
|
298
|
+
const counter = mh.getContract(deployment.address, "counter");
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
#### `contract.call(signer, functionName, args, typeArgs?)`
|
|
302
|
+
|
|
303
|
+
Executes an entry function (transaction).
|
|
228
304
|
|
|
229
305
|
```typescript
|
|
230
|
-
const
|
|
306
|
+
const tx = await counter.call(account, "increment", []);
|
|
307
|
+
console.log(`Transaction: ${tx.hash}`);
|
|
231
308
|
```
|
|
232
309
|
|
|
233
|
-
#### `
|
|
310
|
+
#### `contract.view<T>(functionName, args, typeArgs?)`
|
|
234
311
|
|
|
235
|
-
|
|
312
|
+
Reads data from a view function (no transaction).
|
|
236
313
|
|
|
237
314
|
```typescript
|
|
238
|
-
|
|
315
|
+
// Note: View functions return strings
|
|
316
|
+
const value = await counter.view<string>("get", [address]);
|
|
317
|
+
console.log(`Value: ${parseInt(value)}`);
|
|
239
318
|
```
|
|
240
319
|
|
|
241
320
|
## Available Commands
|
package/bin/movehat.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// Suppress experimental JSON module warning
|
|
4
|
+
process.removeAllListeners('warning');
|
|
5
|
+
process.on('warning', (warning) => {
|
|
6
|
+
if (warning.name === 'ExperimentalWarning' &&
|
|
7
|
+
warning.message.includes('Importing JSON modules')) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
console.warn(warning);
|
|
11
|
+
});
|
|
12
|
+
|
|
3
13
|
import { fileURLToPath } from 'url';
|
|
4
14
|
import { dirname, join } from 'path';
|
|
5
15
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAMA,wBAA8B,UAAU,CAAC,UAAU,EAAE,MAAM,iBA4F1D"}
|
package/dist/commands/run.js
CHANGED
|
@@ -2,6 +2,7 @@ import { spawn } from "child_process";
|
|
|
2
2
|
import { resolve, extname, dirname, join } from "path";
|
|
3
3
|
import { existsSync } from "fs";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
|
+
import { createRequire } from "module";
|
|
5
6
|
export default async function runCommand(scriptPath) {
|
|
6
7
|
if (!scriptPath) {
|
|
7
8
|
console.error("❌ Error: No script path provided");
|
|
@@ -28,12 +29,48 @@ export default async function runCommand(scriptPath) {
|
|
|
28
29
|
console.log(` Network: ${network}`);
|
|
29
30
|
}
|
|
30
31
|
console.log();
|
|
31
|
-
// Find tsx
|
|
32
|
+
// Find tsx binary - try multiple locations for compatibility
|
|
33
|
+
// Uses require.resolve for cross-platform compatibility (works on Windows, macOS, Linux)
|
|
32
34
|
const __filename = fileURLToPath(import.meta.url);
|
|
33
35
|
const __dirname = dirname(__filename);
|
|
34
|
-
|
|
36
|
+
// Create require function for ESM (needed to use require.resolve in ESM modules)
|
|
37
|
+
const require = createRequire(import.meta.url);
|
|
38
|
+
let tsxPath;
|
|
39
|
+
try {
|
|
40
|
+
// Try to resolve tsx package from user's project first
|
|
41
|
+
const tsxPackagePath = require.resolve("tsx", { paths: [process.cwd()] });
|
|
42
|
+
// require.resolve("tsx") returns .../tsx/dist/loader.mjs
|
|
43
|
+
// We need to go up to the tsx package root, then into dist/cli.mjs
|
|
44
|
+
const tsxPackageRoot = dirname(dirname(tsxPackagePath));
|
|
45
|
+
tsxPath = join(tsxPackageRoot, "dist", "cli.mjs");
|
|
46
|
+
// Verify the file exists
|
|
47
|
+
if (!existsSync(tsxPath)) {
|
|
48
|
+
throw new Error("cli.mjs not found");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
try {
|
|
53
|
+
// Fallback to movehat's own tsx
|
|
54
|
+
const tsxPackagePath = require.resolve("tsx", { paths: [__dirname] });
|
|
55
|
+
const tsxPackageRoot = dirname(dirname(tsxPackagePath));
|
|
56
|
+
tsxPath = join(tsxPackageRoot, "dist", "cli.mjs");
|
|
57
|
+
if (!existsSync(tsxPath)) {
|
|
58
|
+
throw new Error("cli.mjs not found");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
tsxPath = "";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (!tsxPath) {
|
|
66
|
+
console.error("❌ Error: tsx binary not found");
|
|
67
|
+
console.error(" Make sure 'tsx' is installed in your project:");
|
|
68
|
+
console.error(" npm install --save-dev tsx");
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
35
71
|
// Execute script with tsx (handles both .ts and .js files)
|
|
36
|
-
|
|
72
|
+
// Using 'node' to execute tsx for cross-platform compatibility
|
|
73
|
+
const child = spawn("node", [tsxPath, fullPath], {
|
|
37
74
|
stdio: "inherit",
|
|
38
75
|
env: {
|
|
39
76
|
...process.env,
|
package/dist/commands/run.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { Account } from "@aptos-labs/ts-sdk";
|
|
2
|
+
import { MovehatConfig } from "../types/config.js";
|
|
3
|
+
/**
|
|
4
|
+
* Represents a stored account in the pool
|
|
5
|
+
*/
|
|
6
|
+
export interface StoredAccount {
|
|
7
|
+
label?: string;
|
|
8
|
+
privateKey: string;
|
|
9
|
+
address: string;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Centralized Account Manager for movehat
|
|
14
|
+
*
|
|
15
|
+
* Manages all account creation, loading, and lifecycle operations.
|
|
16
|
+
* Provides a pool of reusable test accounts with labels for better test readability.
|
|
17
|
+
*/
|
|
18
|
+
export declare class AccountManager {
|
|
19
|
+
private static pool;
|
|
20
|
+
private static privateKeys;
|
|
21
|
+
private static labelMap;
|
|
22
|
+
private static poolLoaded;
|
|
23
|
+
private static defaultPoolPath;
|
|
24
|
+
/**
|
|
25
|
+
* Get a test account from the pool. If label is provided and exists, returns that account.
|
|
26
|
+
* Otherwise creates a new account with the optional label.
|
|
27
|
+
*
|
|
28
|
+
* @param label Optional label for the account (e.g., "alice", "bob", "deployer")
|
|
29
|
+
* @returns An Account instance
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* const alice = AccountManager.getTestAccount("alice");
|
|
33
|
+
* const randomAccount = AccountManager.getTestAccount();
|
|
34
|
+
*/
|
|
35
|
+
static getTestAccount(label?: string): Account;
|
|
36
|
+
/**
|
|
37
|
+
* Create a new account and optionally add it to the pool with a label
|
|
38
|
+
*
|
|
39
|
+
* @param label Optional label for the account
|
|
40
|
+
* @param fund Whether to fund the account (handled externally)
|
|
41
|
+
* @returns A new Account instance
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const deployer = AccountManager.createAccount("deployer");
|
|
45
|
+
* const bob = AccountManager.createAccount("bob", true);
|
|
46
|
+
*/
|
|
47
|
+
static createAccount(label?: string, fund?: boolean): Account;
|
|
48
|
+
/**
|
|
49
|
+
* Get an account by its label
|
|
50
|
+
*
|
|
51
|
+
* @param label The label to look up
|
|
52
|
+
* @returns The Account if found, undefined otherwise
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const alice = AccountManager.getAccountByLabel("alice");
|
|
56
|
+
* if (alice) {
|
|
57
|
+
* console.log(`Alice's address: ${alice.accountAddress.toString()}`);
|
|
58
|
+
* }
|
|
59
|
+
*/
|
|
60
|
+
static getAccountByLabel(label: string): Account | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Load account from environment variable
|
|
63
|
+
*
|
|
64
|
+
* @param envVar The environment variable name (defaults to "PRIVATE_KEY")
|
|
65
|
+
* @returns Account instance
|
|
66
|
+
* @throws Error if environment variable is not set
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* const account = AccountManager.loadAccountFromEnv("MH_PRIVATE_KEY");
|
|
70
|
+
*/
|
|
71
|
+
static loadAccountFromEnv(envVar?: string): Account;
|
|
72
|
+
/**
|
|
73
|
+
* Load account from a private key hex string
|
|
74
|
+
*
|
|
75
|
+
* @param privateKeyHex The private key as a hex string (with or without 0x prefix)
|
|
76
|
+
* @returns Account instance
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* const account = AccountManager.loadAccountFromPrivateKey("0xabc123...");
|
|
80
|
+
*/
|
|
81
|
+
static loadAccountFromPrivateKey(privateKeyHex: string): Account;
|
|
82
|
+
/**
|
|
83
|
+
* Load all accounts from movehat config
|
|
84
|
+
*
|
|
85
|
+
* @param config The resolved MovehatConfig
|
|
86
|
+
* @returns Array of Account instances
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* const config = await resolveNetworkConfig(userConfig);
|
|
90
|
+
* const accounts = AccountManager.loadAccountsFromConfig(config);
|
|
91
|
+
*/
|
|
92
|
+
static loadAccountsFromConfig(config: MovehatConfig): Account[];
|
|
93
|
+
/**
|
|
94
|
+
* Get all labeled accounts in the pool
|
|
95
|
+
*
|
|
96
|
+
* @returns Record of label to Account mappings
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* const labeled = AccountManager.getLabeledAccounts();
|
|
100
|
+
* console.log(`Deployer: ${labeled.deployer?.accountAddress.toString()}`);
|
|
101
|
+
*/
|
|
102
|
+
static getLabeledAccounts(): Record<string, Account>;
|
|
103
|
+
/**
|
|
104
|
+
* Save the current account pool to disk for persistence
|
|
105
|
+
*
|
|
106
|
+
* @param poolPath Optional custom path (defaults to .movehat/accounts)
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* AccountManager.saveAccountPool();
|
|
110
|
+
*/
|
|
111
|
+
static saveAccountPool(poolPath?: string): void;
|
|
112
|
+
/**
|
|
113
|
+
* Load account pool from disk
|
|
114
|
+
*
|
|
115
|
+
* @param poolPath Optional custom path (defaults to .movehat/accounts)
|
|
116
|
+
* @returns true if pool was loaded, false if file doesn't exist
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* if (AccountManager.loadAccountPool()) {
|
|
120
|
+
* console.log("Pool loaded successfully");
|
|
121
|
+
* }
|
|
122
|
+
*/
|
|
123
|
+
static loadAccountPool(poolPath?: string): boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Clear the entire account pool
|
|
126
|
+
* Useful for test isolation
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* after(() => {
|
|
130
|
+
* AccountManager.clearPool();
|
|
131
|
+
* });
|
|
132
|
+
*/
|
|
133
|
+
static clearPool(): void;
|
|
134
|
+
/**
|
|
135
|
+
* Get the current size of the account pool
|
|
136
|
+
*
|
|
137
|
+
* @returns Number of accounts in the pool
|
|
138
|
+
*/
|
|
139
|
+
static getPoolSize(): number;
|
|
140
|
+
/**
|
|
141
|
+
* Get all accounts in the pool
|
|
142
|
+
*
|
|
143
|
+
* @returns Array of all Account instances
|
|
144
|
+
*/
|
|
145
|
+
static getAllAccounts(): Account[];
|
|
146
|
+
/**
|
|
147
|
+
* Check if a label is already in use
|
|
148
|
+
*
|
|
149
|
+
* @param label The label to check
|
|
150
|
+
* @returns true if label exists, false otherwise
|
|
151
|
+
*/
|
|
152
|
+
static hasLabel(label: string): boolean;
|
|
153
|
+
/**
|
|
154
|
+
* Get or create an account with a specific label
|
|
155
|
+
* If the label exists, returns the existing account
|
|
156
|
+
* Otherwise creates a new account with that label
|
|
157
|
+
*
|
|
158
|
+
* @param label The label for the account
|
|
159
|
+
* @returns Account instance
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* const alice = AccountManager.getOrCreateLabeled("alice");
|
|
163
|
+
* const aliceAgain = AccountManager.getOrCreateLabeled("alice"); // Same account
|
|
164
|
+
*/
|
|
165
|
+
static getOrCreateLabeled(label: string): Account;
|
|
166
|
+
/**
|
|
167
|
+
* Batch create multiple labeled accounts
|
|
168
|
+
*
|
|
169
|
+
* @param labels Array of labels to create
|
|
170
|
+
* @returns Record of label to Account mappings
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* const accounts = AccountManager.createBatch(["alice", "bob", "charlie"]);
|
|
174
|
+
* console.log(accounts.alice.accountAddress.toString());
|
|
175
|
+
*/
|
|
176
|
+
static createBatch(labels: readonly string[]): Record<string, Account>;
|
|
177
|
+
/**
|
|
178
|
+
* Export account private keys for backup/sharing
|
|
179
|
+
* WARNING: Only use this for test accounts, never production keys
|
|
180
|
+
*
|
|
181
|
+
* @param labels Optional array of labels to export (exports all if not provided)
|
|
182
|
+
* @returns Record of label/address to private key hex string
|
|
183
|
+
*/
|
|
184
|
+
static exportPrivateKeys(labels?: string[]): Record<string, string>;
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=AccountManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccountManager.d.ts","sourceRoot":"","sources":["../../src/core/AccountManager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EAER,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAUD;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAmC;IACtD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAkC;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IACzD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAS;IAClC,OAAO,CAAC,MAAM,CAAC,eAAe,CAA+C;IAE7E;;;;;;;;;;OAUG;IACH,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IAa9C;;;;;;;;;;OAUG;IACH,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,OAAe,GAAG,OAAO;IAkBpE;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAQ5D;;;;;;;;;OASG;IACH,MAAM,CAAC,kBAAkB,CAAC,MAAM,GAAE,MAAsB,GAAG,OAAO;IAalE;;;;;;;;OAQG;IACH,MAAM,CAAC,yBAAyB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAchE;;;;;;;;;OASG;IACH,MAAM,CAAC,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,EAAE;IAiB/D;;;;;;;;OAQG;IACH,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAapD;;;;;;;OAOG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IA+C/C;;;;;;;;;;OAUG;IACH,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAgDlD;;;;;;;;OAQG;IACH,MAAM,CAAC,SAAS,IAAI,IAAI;IAOxB;;;;OAIG;IACH,MAAM,CAAC,WAAW,IAAI,MAAM;IAI5B;;;;OAIG;IACH,MAAM,CAAC,cAAc,IAAI,OAAO,EAAE;IAIlC;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIvC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAQjD;;;;;;;;;OASG;IACH,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAUtE;;;;;;OAMG;IACH,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CA0BpE"}
|