movehat 0.1.1 → 0.1.2
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/commands/compile.d.ts +13 -0
- package/dist/commands/compile.d.ts.map +1 -1
- package/dist/commands/compile.js +31 -11
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/fork/create.d.ts +20 -1
- package/dist/commands/fork/create.d.ts.map +1 -1
- package/dist/commands/fork/create.js +54 -20
- package/dist/commands/fork/create.js.map +1 -1
- package/dist/commands/fork/list.d.ts +12 -1
- package/dist/commands/fork/list.d.ts.map +1 -1
- package/dist/commands/fork/list.js +50 -22
- package/dist/commands/fork/list.js.map +1 -1
- package/dist/commands/init.d.ts +19 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +64 -29
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/update.d.ts +11 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +44 -18
- package/dist/commands/update.js.map +1 -1
- package/dist/helpers/banner.d.ts +17 -0
- package/dist/helpers/banner.d.ts.map +1 -1
- package/dist/helpers/banner.js +38 -23
- package/dist/helpers/banner.js.map +1 -1
- package/dist/helpers/version-check.d.ts +12 -1
- package/dist/helpers/version-check.d.ts.map +1 -1
- package/dist/helpers/version-check.js +17 -7
- package/dist/helpers/version-check.js.map +1 -1
- package/dist/ui/colors.d.ts +77 -0
- package/dist/ui/colors.d.ts.map +1 -0
- package/dist/ui/colors.js +121 -0
- package/dist/ui/colors.js.map +1 -0
- package/dist/ui/formatters.d.ts +171 -0
- package/dist/ui/formatters.d.ts.map +1 -0
- package/dist/ui/formatters.js +186 -0
- package/dist/ui/formatters.js.map +1 -0
- package/dist/ui/index.d.ts +58 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +60 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/logger.d.ts +160 -0
- package/dist/ui/logger.d.ts.map +1 -0
- package/dist/ui/logger.js +206 -0
- package/dist/ui/logger.js.map +1 -0
- package/dist/ui/spinner.d.ts +106 -0
- package/dist/ui/spinner.d.ts.map +1 -0
- package/dist/ui/spinner.js +120 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/symbols.d.ts +50 -0
- package/dist/ui/symbols.d.ts.map +1 -0
- package/dist/ui/symbols.js +64 -0
- package/dist/ui/symbols.js.map +1 -0
- package/dist/ui/table.d.ts +67 -0
- package/dist/ui/table.d.ts.map +1 -0
- package/dist/ui/table.js +143 -0
- package/dist/ui/table.js.map +1 -0
- package/package.json +8 -1
- package/src/commands/compile.ts +32 -11
- package/src/commands/fork/create.ts +59 -20
- package/src/commands/fork/list.ts +52 -22
- package/src/commands/init.ts +111 -74
- package/src/commands/update.ts +52 -19
- package/src/helpers/banner.ts +45 -29
- package/src/helpers/version-check.ts +20 -8
- package/src/ui/colors.ts +141 -0
- package/src/ui/formatters.ts +246 -0
- package/src/ui/index.ts +62 -0
- package/src/ui/logger.ts +226 -0
- package/src/ui/spinner.ts +171 -0
- package/src/ui/symbols.ts +74 -0
- package/src/ui/table.ts +191 -0
package/dist/ui/table.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import Table from 'cli-table3';
|
|
2
|
+
import { shouldUseColor, colors } from './colors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get preset configuration for table styling
|
|
5
|
+
* Automatically respects color settings (NO_COLOR, TTY)
|
|
6
|
+
*
|
|
7
|
+
* @param preset - Preset name
|
|
8
|
+
* @returns Partial cli-table3 configuration
|
|
9
|
+
*/
|
|
10
|
+
const getPresetConfig = (preset) => {
|
|
11
|
+
const hasColor = shouldUseColor();
|
|
12
|
+
const presets = {
|
|
13
|
+
/**
|
|
14
|
+
* Default preset - Full borders with colors
|
|
15
|
+
* Best for: Complex tables with multiple columns
|
|
16
|
+
*/
|
|
17
|
+
default: {
|
|
18
|
+
chars: {
|
|
19
|
+
'top': '─', 'top-mid': '┬', 'top-left': '┌', 'top-right': '┐',
|
|
20
|
+
'bottom': '─', 'bottom-mid': '┴', 'bottom-left': '└', 'bottom-right': '┘',
|
|
21
|
+
'left': '│', 'left-mid': '├', 'mid': '─', 'mid-mid': '┼',
|
|
22
|
+
'right': '│', 'right-mid': '┤', 'middle': '│',
|
|
23
|
+
},
|
|
24
|
+
style: {
|
|
25
|
+
head: hasColor ? ['cyan'] : [],
|
|
26
|
+
border: hasColor ? ['gray'] : [],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* Compact preset - Minimal borders, max readability
|
|
31
|
+
* Best for: Fork list and similar data displays
|
|
32
|
+
*/
|
|
33
|
+
compact: {
|
|
34
|
+
chars: {
|
|
35
|
+
'top': '', 'top-mid': '', 'top-left': '', 'top-right': '',
|
|
36
|
+
'bottom': '', 'bottom-mid': '', 'bottom-left': '', 'bottom-right': '',
|
|
37
|
+
'left': '', 'left-mid': '', 'mid': '', 'mid-mid': '',
|
|
38
|
+
'right': '', 'right-mid': '', 'middle': ' │ ',
|
|
39
|
+
},
|
|
40
|
+
style: {
|
|
41
|
+
head: hasColor ? ['cyan', 'bold'] : [],
|
|
42
|
+
border: [],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* Markdown preset - Markdown-compatible table format
|
|
47
|
+
* Best for: Copy-paste to documentation
|
|
48
|
+
*/
|
|
49
|
+
markdown: {
|
|
50
|
+
chars: {
|
|
51
|
+
'top': '', 'top-mid': '', 'top-left': '', 'top-right': '',
|
|
52
|
+
'bottom': '', 'bottom-mid': '', 'bottom-left': '', 'bottom-right': '',
|
|
53
|
+
'left': '|', 'left-mid': '', 'mid': '', 'mid-mid': '',
|
|
54
|
+
'right': '|', 'right-mid': '', 'middle': '|',
|
|
55
|
+
},
|
|
56
|
+
style: {
|
|
57
|
+
head: hasColor ? ['cyan'] : [],
|
|
58
|
+
border: [],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Borderless preset - Clean, minimal appearance
|
|
63
|
+
* Best for: Key-value displays and metadata
|
|
64
|
+
*/
|
|
65
|
+
borderless: {
|
|
66
|
+
chars: {
|
|
67
|
+
'top': '', 'top-mid': '', 'top-left': '', 'top-right': '',
|
|
68
|
+
'bottom': '', 'bottom-mid': '', 'bottom-left': '', 'bottom-right': '',
|
|
69
|
+
'left': '', 'left-mid': '', 'mid': '', 'mid-mid': '',
|
|
70
|
+
'right': '', 'right-mid': '', 'middle': ' ',
|
|
71
|
+
},
|
|
72
|
+
style: {
|
|
73
|
+
head: hasColor ? ['cyan', 'bold'] : [],
|
|
74
|
+
border: [],
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
return presets[preset];
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Create a table with preset configuration
|
|
82
|
+
* Wrapper around cli-table3 with Movehat-specific styling
|
|
83
|
+
*
|
|
84
|
+
* @param config - Table configuration
|
|
85
|
+
* @returns cli-table3 Table instance
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const table = createTable({
|
|
89
|
+
* head: ['Name', 'Network', 'Chain ID', 'Accounts'],
|
|
90
|
+
* preset: 'compact'
|
|
91
|
+
* });
|
|
92
|
+
*
|
|
93
|
+
* table.push(['testnet-fork', 'testnet', '126', '5']);
|
|
94
|
+
* table.push(['mainnet-fork', 'mainnet', '1', '3']);
|
|
95
|
+
*
|
|
96
|
+
* console.log(table.toString());
|
|
97
|
+
*/
|
|
98
|
+
export const createTable = (config = {}) => {
|
|
99
|
+
const { head, preset = 'default', colWidths, colAligns, style = {}, } = config;
|
|
100
|
+
const presetConfig = getPresetConfig(preset);
|
|
101
|
+
const tableConfig = {
|
|
102
|
+
...presetConfig,
|
|
103
|
+
style: {
|
|
104
|
+
...presetConfig.style,
|
|
105
|
+
...style,
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
// Only add optional properties if they are defined
|
|
109
|
+
if (head)
|
|
110
|
+
tableConfig.head = head;
|
|
111
|
+
if (colWidths)
|
|
112
|
+
tableConfig.colWidths = colWidths;
|
|
113
|
+
if (colAligns)
|
|
114
|
+
tableConfig.colAligns = colAligns;
|
|
115
|
+
return new Table(tableConfig);
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Create a simple key-value table
|
|
119
|
+
* Perfect for displaying metadata and configuration
|
|
120
|
+
*
|
|
121
|
+
* @param data - Object with key-value pairs
|
|
122
|
+
* @param preset - Table preset to use (default: 'borderless')
|
|
123
|
+
* @returns cli-table3 Table instance ready for display
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* const metadata = {
|
|
127
|
+
* 'Chain ID': '126',
|
|
128
|
+
* 'Network': 'testnet',
|
|
129
|
+
* 'Ledger Version': '12345',
|
|
130
|
+
* 'Created At': new Date().toLocaleString()
|
|
131
|
+
* };
|
|
132
|
+
*
|
|
133
|
+
* const table = createKVTable(metadata);
|
|
134
|
+
* console.log(table.toString());
|
|
135
|
+
*/
|
|
136
|
+
export const createKVTable = (data, preset = 'borderless') => {
|
|
137
|
+
const table = createTable({ preset });
|
|
138
|
+
for (const [key, value] of Object.entries(data)) {
|
|
139
|
+
table.push([colors.dim(key), String(value)]);
|
|
140
|
+
}
|
|
141
|
+
return table;
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table.js","sourceRoot":"","sources":["../../src/ui/table.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "movehat",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Hardhat-like development framework for Movement L1 and Aptos Move smart contracts",
|
|
6
6
|
"bin": {
|
|
@@ -49,11 +49,18 @@
|
|
|
49
49
|
],
|
|
50
50
|
"author": "Gilberts Ahumada",
|
|
51
51
|
"license": "MIT",
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=20.0.0"
|
|
54
|
+
},
|
|
52
55
|
"dependencies": {
|
|
53
56
|
"@aptos-labs/ts-sdk": "^5.1.5",
|
|
57
|
+
"cli-table3": "^0.6.5",
|
|
54
58
|
"commander": "^14.0.2",
|
|
55
59
|
"dotenv": "^17.2.3",
|
|
60
|
+
"figures": "^6.1.0",
|
|
56
61
|
"js-yaml": "^4.1.1",
|
|
62
|
+
"ora": "^9.0.0",
|
|
63
|
+
"picocolors": "^1.1.1",
|
|
57
64
|
"prompts": "^2.4.2",
|
|
58
65
|
"tsx": "^4.7.0"
|
|
59
66
|
},
|
package/src/commands/compile.ts
CHANGED
|
@@ -3,6 +3,7 @@ import path from "path";
|
|
|
3
3
|
import { exec } from "child_process";
|
|
4
4
|
import { loadUserConfig } from "../core/config.js";
|
|
5
5
|
import { validateAndEscapePath, escapeShellArg } from "../core/shell.js";
|
|
6
|
+
import { logger } from "../ui/index.js";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Recursively find all .move files in a directory
|
|
@@ -84,18 +85,33 @@ function run(command: string, cwd: string) {
|
|
|
84
85
|
});
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Compile Move smart contracts using the Movement CLI
|
|
90
|
+
*
|
|
91
|
+
* This command:
|
|
92
|
+
* - Detects named addresses used in Move modules
|
|
93
|
+
* - Merges auto-detected addresses with user-configured addresses
|
|
94
|
+
* - Auto-assigns development addresses (0xcafe) for missing addresses
|
|
95
|
+
* - Executes `movement move build` with proper named address mappings
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Compile contracts in default ./move directory
|
|
99
|
+
* await compileCommand();
|
|
100
|
+
*/
|
|
87
101
|
export default async function compileCommand() {
|
|
88
102
|
try {
|
|
89
103
|
// Compile is network-independent - only uses global config
|
|
90
104
|
const userConfig = await loadUserConfig();
|
|
91
105
|
|
|
92
|
-
|
|
106
|
+
logger.newline();
|
|
107
|
+
logger.info('Compiling Move contracts...');
|
|
93
108
|
|
|
94
109
|
const moveDir = path.resolve(process.cwd(), userConfig.moveDir || "./move");
|
|
95
110
|
if (!fs.existsSync(moveDir)) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
111
|
+
logger.error(`Move directory not found: ${moveDir}`);
|
|
112
|
+
logger.plain(` Update movehat.config.ts -> moveDir`);
|
|
113
|
+
logger.newline();
|
|
114
|
+
process.exit(1);
|
|
99
115
|
}
|
|
100
116
|
|
|
101
117
|
// Validate and escape to prevent command injection
|
|
@@ -148,22 +164,27 @@ export default async function compileCommand() {
|
|
|
148
164
|
|
|
149
165
|
const command = `movement move build --package-dir ${safeMoveDir} ${namedAddressesArg}`.trim();
|
|
150
166
|
|
|
151
|
-
|
|
167
|
+
logger.kv('Move directory', moveDir, 2);
|
|
152
168
|
if (detectedAddresses.size > 0) {
|
|
153
|
-
|
|
169
|
+
logger.kv('Detected addresses', Array.from(detectedAddresses).join(", "), 2);
|
|
154
170
|
}
|
|
155
171
|
if (Object.keys(userConfig.namedAddresses ?? {}).length > 0) {
|
|
156
|
-
|
|
172
|
+
logger.kv('Configured addresses', Object.keys(userConfig.namedAddresses!).join(", "), 2);
|
|
157
173
|
}
|
|
158
174
|
if (autoAssignedAddresses.length > 0) {
|
|
159
|
-
|
|
175
|
+
logger.kv('Auto-assigned (0xcafe)', autoAssignedAddresses.join(", "), 2);
|
|
160
176
|
}
|
|
161
|
-
|
|
177
|
+
logger.newline();
|
|
162
178
|
|
|
163
179
|
await run(command, moveDir);
|
|
164
|
-
|
|
180
|
+
|
|
181
|
+
logger.newline();
|
|
182
|
+
logger.success('Compilation finished successfully');
|
|
183
|
+
logger.newline();
|
|
165
184
|
} catch (err: any) {
|
|
166
|
-
|
|
185
|
+
logger.newline();
|
|
186
|
+
logger.error(`Compilation failed: ${err.message ?? err}`);
|
|
187
|
+
logger.newline();
|
|
167
188
|
process.exit(1);
|
|
168
189
|
}
|
|
169
190
|
}
|
|
@@ -3,6 +3,7 @@ import { existsSync } from 'fs';
|
|
|
3
3
|
import prompts from 'prompts';
|
|
4
4
|
import { loadUserConfig, resolveNetworkConfig } from '../../core/config.js';
|
|
5
5
|
import { ForkManager } from '../../fork/manager.js';
|
|
6
|
+
import { logger, withSpinner, createKVTable, formatCommand } from '../../ui/index.js';
|
|
6
7
|
|
|
7
8
|
interface ForkCreateOptions {
|
|
8
9
|
network?: string;
|
|
@@ -11,7 +12,26 @@ interface ForkCreateOptions {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
*
|
|
15
|
+
* Create a local fork of a Movement/Aptos network
|
|
16
|
+
*
|
|
17
|
+
* This command:
|
|
18
|
+
* - Connects to the specified network RPC endpoint
|
|
19
|
+
* - Downloads blockchain state (accounts, modules, resources)
|
|
20
|
+
* - Creates a local fork database for testing
|
|
21
|
+
* - Displays fork metadata (chain ID, ledger version, block height, epoch)
|
|
22
|
+
*
|
|
23
|
+
* @param options - Fork creation options
|
|
24
|
+
* @param options.network - Network to fork from (e.g., 'testnet', 'mainnet')
|
|
25
|
+
* @param options.path - Custom path to store fork data
|
|
26
|
+
* @param options.name - Custom name for the fork
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Fork testnet
|
|
30
|
+
* await forkCreateCommand({ network: 'testnet' });
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Fork with custom name
|
|
34
|
+
* await forkCreateCommand({ network: 'testnet', name: 'my-fork' });
|
|
15
35
|
*/
|
|
16
36
|
export default async function forkCreateCommand(options: ForkCreateOptions = {}) {
|
|
17
37
|
try {
|
|
@@ -24,9 +44,11 @@ export default async function forkCreateCommand(options: ForkCreateOptions = {})
|
|
|
24
44
|
const forkName = options.name || `${networkName}-fork`;
|
|
25
45
|
const forkPath = options.path || join(process.cwd(), '.movehat', 'forks', forkName);
|
|
26
46
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
47
|
+
logger.newline();
|
|
48
|
+
logger.info(`Creating fork of ${networkName}`);
|
|
49
|
+
logger.kv('Network', networkConfig.rpc, 2);
|
|
50
|
+
logger.kv('Fork path', forkPath, 2);
|
|
51
|
+
logger.newline();
|
|
30
52
|
|
|
31
53
|
// Check if fork already exists
|
|
32
54
|
if (existsSync(forkPath)) {
|
|
@@ -38,7 +60,7 @@ export default async function forkCreateCommand(options: ForkCreateOptions = {})
|
|
|
38
60
|
});
|
|
39
61
|
|
|
40
62
|
if (!overwrite) {
|
|
41
|
-
|
|
63
|
+
logger.warning('Fork creation cancelled');
|
|
42
64
|
return;
|
|
43
65
|
}
|
|
44
66
|
}
|
|
@@ -46,25 +68,42 @@ export default async function forkCreateCommand(options: ForkCreateOptions = {})
|
|
|
46
68
|
// Create fork manager
|
|
47
69
|
const forkManager = new ForkManager(forkPath);
|
|
48
70
|
|
|
49
|
-
// Initialize fork
|
|
50
|
-
|
|
51
|
-
|
|
71
|
+
// Initialize fork with spinner
|
|
72
|
+
const metadata = await withSpinner(
|
|
73
|
+
'Initializing fork...',
|
|
74
|
+
async () => {
|
|
75
|
+
await forkManager.initialize(networkConfig.rpc, networkName);
|
|
76
|
+
return forkManager.getMetadata();
|
|
77
|
+
},
|
|
78
|
+
'Fork initialized successfully!'
|
|
79
|
+
);
|
|
52
80
|
|
|
53
|
-
|
|
81
|
+
// Show fork details
|
|
82
|
+
logger.newline();
|
|
83
|
+
logger.success('Fork created successfully!');
|
|
84
|
+
logger.newline();
|
|
54
85
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
console.log(
|
|
63
|
-
|
|
64
|
-
|
|
86
|
+
logger.section('Fork Details');
|
|
87
|
+
const detailsTable = createKVTable({
|
|
88
|
+
'Chain ID': metadata.chainId.toString(),
|
|
89
|
+
'Ledger Version': metadata.ledgerVersion,
|
|
90
|
+
'Block Height': metadata.blockHeight,
|
|
91
|
+
'Epoch': metadata.epoch
|
|
92
|
+
});
|
|
93
|
+
console.log(detailsTable.toString());
|
|
94
|
+
logger.newline();
|
|
95
|
+
|
|
96
|
+
// Usage examples
|
|
97
|
+
logger.section('Usage');
|
|
98
|
+
logger.item(formatCommand(`movehat fork view-resource --fork ${forkPath} --account <ADDRESS> --resource <TYPE>`), 2);
|
|
99
|
+
logger.item(formatCommand(`movehat fork fund --fork ${forkPath} --account <ADDRESS> --amount <AMOUNT>`), 2);
|
|
100
|
+
logger.item(formatCommand('movehat fork list'), 2);
|
|
101
|
+
logger.newline();
|
|
65
102
|
|
|
66
103
|
} catch (error: any) {
|
|
67
|
-
|
|
104
|
+
logger.newline();
|
|
105
|
+
logger.error(`Error: ${error.message}`);
|
|
106
|
+
logger.newline();
|
|
68
107
|
process.exit(1);
|
|
69
108
|
}
|
|
70
109
|
}
|
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
2
|
import { existsSync, readdirSync, statSync } from 'fs';
|
|
3
3
|
import { ForkStorage } from '../../fork/storage.js';
|
|
4
|
+
import { logger, createTable, formatCommand } from '../../ui/index.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
+
* List all available local forks
|
|
8
|
+
*
|
|
9
|
+
* Displays forks in a formatted table showing:
|
|
10
|
+
* - Fork name
|
|
11
|
+
* - Network (testnet, mainnet, etc.)
|
|
12
|
+
* - Chain ID
|
|
13
|
+
* - Number of accounts
|
|
14
|
+
* - Creation timestamp
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // List all forks
|
|
18
|
+
* await forkListCommand();
|
|
7
19
|
*/
|
|
8
20
|
export default async function forkListCommand() {
|
|
9
21
|
try {
|
|
10
22
|
const forksDir = join(process.cwd(), '.movehat', 'forks');
|
|
11
23
|
|
|
12
24
|
if (!existsSync(forksDir)) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
25
|
+
logger.newline();
|
|
26
|
+
logger.info('No forks found');
|
|
27
|
+
logger.newline();
|
|
28
|
+
logger.plain('Create a fork with:');
|
|
29
|
+
logger.item(formatCommand('movehat fork create --network testnet'), 2);
|
|
30
|
+
logger.newline();
|
|
16
31
|
return;
|
|
17
32
|
}
|
|
18
33
|
|
|
@@ -23,11 +38,22 @@ export default async function forkListCommand() {
|
|
|
23
38
|
});
|
|
24
39
|
|
|
25
40
|
if (forkDirs.length === 0) {
|
|
26
|
-
|
|
41
|
+
logger.newline();
|
|
42
|
+
logger.info('No forks found');
|
|
43
|
+
logger.newline();
|
|
27
44
|
return;
|
|
28
45
|
}
|
|
29
46
|
|
|
30
|
-
|
|
47
|
+
logger.newline();
|
|
48
|
+
logger.info(`Found ${forkDirs.length} fork(s)`);
|
|
49
|
+
logger.newline();
|
|
50
|
+
|
|
51
|
+
// Create table for forks
|
|
52
|
+
const table = createTable({
|
|
53
|
+
head: ['Name', 'Network', 'Chain ID', 'Accounts', 'Created'],
|
|
54
|
+
preset: 'default',
|
|
55
|
+
colWidths: [20, 15, 12, 12, 25]
|
|
56
|
+
});
|
|
31
57
|
|
|
32
58
|
for (const forkDir of forkDirs) {
|
|
33
59
|
const forkPath = join(forksDir, forkDir);
|
|
@@ -38,30 +64,34 @@ export default async function forkListCommand() {
|
|
|
38
64
|
const metadata = storage.loadMetadata();
|
|
39
65
|
const accounts = storage.listAccounts();
|
|
40
66
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
console.log('');
|
|
67
|
+
table.push([
|
|
68
|
+
forkDir,
|
|
69
|
+
metadata.network,
|
|
70
|
+
metadata.chainId.toString(),
|
|
71
|
+
accounts.length.toString(),
|
|
72
|
+
new Date(metadata.createdAt).toLocaleString()
|
|
73
|
+
]);
|
|
49
74
|
} else {
|
|
50
|
-
|
|
51
|
-
console.log('');
|
|
75
|
+
table.push([forkDir, 'invalid', '-', '-', 'missing metadata']);
|
|
52
76
|
}
|
|
53
77
|
} catch (error) {
|
|
54
|
-
|
|
55
|
-
console.log('');
|
|
78
|
+
table.push([forkDir, 'error', '-', '-', 'error reading']);
|
|
56
79
|
}
|
|
57
80
|
}
|
|
58
81
|
|
|
59
|
-
console.log(
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
console.log(table.toString());
|
|
83
|
+
logger.newline();
|
|
84
|
+
|
|
85
|
+
// Usage examples
|
|
86
|
+
logger.section('Usage');
|
|
87
|
+
logger.item(formatCommand('movehat fork view-resource --fork <PATH> --account <ADDR> --resource <TYPE>'), 2);
|
|
88
|
+
logger.item(formatCommand('movehat fork fund --fork <PATH> --account <ADDR> --amount <AMOUNT>'), 2);
|
|
89
|
+
logger.newline();
|
|
62
90
|
|
|
63
91
|
} catch (error: any) {
|
|
64
|
-
|
|
92
|
+
logger.newline();
|
|
93
|
+
logger.error(`Error: ${error.message}`);
|
|
94
|
+
logger.newline();
|
|
65
95
|
process.exit(1);
|
|
66
96
|
}
|
|
67
97
|
}
|