@btc-vision/cli 1.0.5 → 1.0.6

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 (46) hide show
  1. package/package.json +4 -1
  2. package/.gitattributes +0 -2
  3. package/.github/dependabot.yml +0 -9
  4. package/.github/workflows/ci.yml +0 -48
  5. package/.prettierrc.json +0 -12
  6. package/CONTRIBUTING.md +0 -56
  7. package/NOTICE +0 -17
  8. package/SECURITY.md +0 -35
  9. package/eslint.config.js +0 -41
  10. package/gulpfile.js +0 -41
  11. package/src/commands/AcceptCommand.ts +0 -224
  12. package/src/commands/BaseCommand.ts +0 -59
  13. package/src/commands/CompileCommand.ts +0 -195
  14. package/src/commands/ConfigCommand.ts +0 -117
  15. package/src/commands/DeprecateCommand.ts +0 -193
  16. package/src/commands/InfoCommand.ts +0 -293
  17. package/src/commands/InitCommand.ts +0 -541
  18. package/src/commands/InstallCommand.ts +0 -179
  19. package/src/commands/KeygenCommand.ts +0 -157
  20. package/src/commands/ListCommand.ts +0 -169
  21. package/src/commands/LoginCommand.ts +0 -197
  22. package/src/commands/LogoutCommand.ts +0 -76
  23. package/src/commands/PublishCommand.ts +0 -340
  24. package/src/commands/ScopeRegisterCommand.ts +0 -164
  25. package/src/commands/SearchCommand.ts +0 -140
  26. package/src/commands/SignCommand.ts +0 -110
  27. package/src/commands/TransferCommand.ts +0 -363
  28. package/src/commands/UndeprecateCommand.ts +0 -167
  29. package/src/commands/UpdateCommand.ts +0 -200
  30. package/src/commands/VerifyCommand.ts +0 -228
  31. package/src/commands/WhoamiCommand.ts +0 -113
  32. package/src/index.ts +0 -88
  33. package/src/lib/PackageRegistry.abi.json +0 -765
  34. package/src/lib/PackageRegistry.abi.ts +0 -365
  35. package/src/lib/binary.ts +0 -338
  36. package/src/lib/config.ts +0 -265
  37. package/src/lib/credentials.ts +0 -176
  38. package/src/lib/ipfs.ts +0 -382
  39. package/src/lib/manifest.ts +0 -195
  40. package/src/lib/provider.ts +0 -121
  41. package/src/lib/registry.ts +0 -467
  42. package/src/lib/transaction.ts +0 -205
  43. package/src/lib/wallet.ts +0 -262
  44. package/src/types/PackageRegistry.ts +0 -344
  45. package/src/types/index.ts +0 -147
  46. package/tsconfig.json +0 -25
@@ -1,179 +0,0 @@
1
- /**
2
- * Install command - Download and verify plugins from registry
3
- *
4
- * @module commands/InstallCommand
5
- */
6
-
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
- import { BaseCommand } from './BaseCommand.js';
10
- import { getPackage, getVersion, registryToMldsaLevel } from '../lib/registry.js';
11
- import { fetchFromIPFS, isValidCid } from '../lib/ipfs.js';
12
- import { formatFileSize, parseOpnetBinary, verifyChecksum } from '../lib/binary.js';
13
- import { CLIWallet } from '../lib/wallet.js';
14
- import { NetworkName } from '../types/index.js';
15
-
16
- interface InstallOptions {
17
- output?: string;
18
- network: string;
19
- skipVerify?: boolean;
20
- }
21
-
22
- export class InstallCommand extends BaseCommand {
23
- constructor() {
24
- super('install', 'Download and verify a plugin from the registry');
25
- }
26
-
27
- protected configure(): void {
28
- this.command
29
- .argument('<package>', 'Package name[@version] or IPFS CID')
30
- .option('-o, --output <path>', 'Output directory (default: ./plugins/)')
31
- .option('-n, --network <network>', 'Network', 'mainnet')
32
- .option('--skip-verify', 'Skip signature verification')
33
- .action((packageInput: string, options?: InstallOptions) =>
34
- this.execute(packageInput, options || { network: 'mainnet' }),
35
- );
36
- }
37
-
38
- private async execute(packageInput: string, options?: InstallOptions): Promise<void> {
39
- try {
40
- let cid: string;
41
- let packageName: string;
42
- let version: string;
43
-
44
- // Check if input is a CID
45
- if (isValidCid(packageInput)) {
46
- cid = packageInput;
47
- packageName = 'unknown';
48
- version = 'unknown';
49
- this.logger.info(`Installing from CID: ${cid}`);
50
- } else {
51
- // Parse package name and version
52
- const atIndex = packageInput.lastIndexOf('@');
53
- if (atIndex > 0 && !packageInput.startsWith('@')) {
54
- packageName = packageInput.substring(0, atIndex);
55
- version = packageInput.substring(atIndex + 1);
56
- } else if (packageInput.startsWith('@') && packageInput.indexOf('@', 1) > 0) {
57
- const secondAt = packageInput.indexOf('@', 1);
58
- packageName = packageInput.substring(0, secondAt);
59
- version = packageInput.substring(secondAt + 1);
60
- } else {
61
- packageName = packageInput;
62
- version = 'latest';
63
- }
64
-
65
- // Fetch from registry
66
- this.logger.info(`Fetching ${packageName}...`);
67
- const network = (options?.network || 'mainnet') as NetworkName;
68
-
69
- const packageInfo = await getPackage(packageName, network);
70
- if (!packageInfo) {
71
- this.logger.fail('Package not found');
72
- this.logger.error(`Package "${packageName}" does not exist.`);
73
- process.exit(1);
74
- }
75
-
76
- // Resolve version
77
- if (version === 'latest') {
78
- version = packageInfo.latestVersion;
79
- }
80
-
81
- const versionInfo = await getVersion(packageName, version, network);
82
- if (!versionInfo) {
83
- this.logger.fail('Version not found');
84
- this.logger.error(`Version "${version}" does not exist.`);
85
- process.exit(1);
86
- }
87
-
88
- if (versionInfo.deprecated) {
89
- this.logger.warn(`Version ${version} is deprecated`);
90
- }
91
-
92
- cid = versionInfo.ipfsCid;
93
- this.logger.success(`Found: ${packageName}@${version}`);
94
-
95
- // Display info
96
- this.logger.log('');
97
- this.logger.log(`IPFS CID: ${cid}`);
98
- this.logger.log(`MLDSA Level: ${registryToMldsaLevel(versionInfo.mldsaLevel)}`);
99
- this.logger.log(`Publisher: ${versionInfo.publisher}`);
100
- this.logger.log('');
101
- }
102
-
103
- // Download from IPFS
104
- this.logger.info('Downloading from IPFS...');
105
- const result = await fetchFromIPFS(cid);
106
- this.logger.success(`Downloaded (${formatFileSize(result.size)})`);
107
-
108
- // Parse and verify
109
- this.logger.info('Verifying binary...');
110
- const parsed = parseOpnetBinary(result.data);
111
-
112
- // Verify checksum
113
- if (!verifyChecksum(parsed)) {
114
- this.logger.fail('Checksum verification failed');
115
- this.logger.error('The binary appears to be corrupted.');
116
- process.exit(1);
117
- }
118
-
119
- // Verify signature
120
- if (!options?.skipVerify) {
121
- const isUnsigned = parsed.publicKey.every((b) => b === 0);
122
- if (isUnsigned) {
123
- this.logger.warn('Binary is unsigned');
124
- } else {
125
- const actualMldsaLevel = ([44, 65, 87] as const)[parsed.mldsaLevel];
126
- const signatureValid = CLIWallet.verifyMLDSA(
127
- parsed.checksum,
128
- parsed.signature,
129
- parsed.publicKey,
130
- actualMldsaLevel,
131
- );
132
-
133
- if (!signatureValid) {
134
- this.logger.fail('Signature verification failed');
135
- this.logger.error('The binary signature is invalid.');
136
- process.exit(1);
137
- }
138
- this.logger.success('Signature verified');
139
- }
140
- } else {
141
- this.logger.warn('Skipping signature verification');
142
- }
143
-
144
- // Update package name from metadata
145
- if (packageName === 'unknown') {
146
- packageName = parsed.metadata.name;
147
- version = parsed.metadata.version;
148
- }
149
-
150
- // Determine output path
151
- const outputDir = options?.output || path.join(process.cwd(), 'plugins');
152
- fs.mkdirSync(outputDir, { recursive: true });
153
-
154
- const fileName = `${packageName.replace(/^@/, '').replace(/\//g, '-')}-${version}.opnet`;
155
- const outputPath = path.join(outputDir, fileName);
156
-
157
- // Save file
158
- this.logger.info('Saving plugin...');
159
- fs.writeFileSync(outputPath, result.data);
160
- this.logger.success('Plugin installed');
161
-
162
- // Summary
163
- this.logger.log('');
164
- this.logger.success('Plugin installed successfully!');
165
- this.logger.log('');
166
- this.logger.log(`Package: ${parsed.metadata.name}`);
167
- this.logger.log(`Version: ${parsed.metadata.version}`);
168
- this.logger.log(`Type: ${parsed.metadata.pluginType}`);
169
- this.logger.log(`Size: ${formatFileSize(result.size)}`);
170
- this.logger.log(`Output: ${outputPath}`);
171
- this.logger.log('');
172
- } catch (error) {
173
- this.logger.fail('Installation failed');
174
- this.exitWithError(this.formatError(error));
175
- }
176
- }
177
- }
178
-
179
- export const installCommand = new InstallCommand().getCommand();
@@ -1,157 +0,0 @@
1
- /**
2
- * Keygen command - Generate MLDSA keypairs and mnemonics
3
- *
4
- * @module commands/KeygenCommand
5
- */
6
-
7
- import { Command } from 'commander';
8
- import * as fs from 'fs';
9
- import { BaseCommand } from './BaseCommand.js';
10
- import { computePublicKeyHash, generateMLDSAKeypair, generateMnemonic } from '../lib/wallet.js';
11
- import { isValidMldsaLevel } from '../lib/credentials.js';
12
-
13
- export class KeygenCommand extends BaseCommand {
14
- constructor() {
15
- super('keygen', 'Generate cryptographic keys');
16
- }
17
-
18
- protected configure(): void {
19
- this.command
20
- .addCommand(this.createMnemonicCommand())
21
- .addCommand(this.createMldsaCommand())
22
- .addCommand(this.createInfoCommand());
23
- }
24
-
25
- private createMnemonicCommand(): Command {
26
- return new Command('mnemonic')
27
- .description('Generate a new BIP-39 mnemonic phrase')
28
- .option('-o, --output <file>', 'Write mnemonic to file (secure permissions)')
29
- .action((options: { output?: string }) => this.handleMnemonic(options));
30
- }
31
-
32
- private createMldsaCommand(): Command {
33
- return new Command('mldsa')
34
- .description('Generate a standalone MLDSA keypair')
35
- .option('-l, --level <level>', 'MLDSA security level (44, 65, 87)', '44')
36
- .option('-o, --output <prefix>', 'Write keys to files with prefix')
37
- .option('--json', 'Output as JSON')
38
- .action((options: { level: string; output?: string; json?: boolean }) => {
39
- this.handleMldsa(options);
40
- });
41
- }
42
-
43
- private createInfoCommand(): Command {
44
- return new Command('info')
45
- .description('Show information about MLDSA key sizes')
46
- .action(() => this.handleInfo());
47
- }
48
-
49
- private handleMnemonic(options: { output?: string }): void {
50
- try {
51
- const mnemonic = generateMnemonic();
52
-
53
- if (options.output) {
54
- fs.writeFileSync(options.output, mnemonic + '\n', { mode: 0o600 });
55
- this.logger.success(`Mnemonic saved to: ${options.output}`);
56
- this.logger.warn('Keep this file secure and backed up!');
57
- } else {
58
- this.logger.info('\nNew BIP-39 Mnemonic Phrase:\n');
59
- this.logger.log(mnemonic);
60
- this.logger.log('');
61
- this.logger.warn('IMPORTANT: Write down these words and store them securely.');
62
- this.logger.warn('Anyone with this phrase can access your wallet.');
63
- this.logger.warn('Never share this phrase with anyone.');
64
- }
65
- } catch (error) {
66
- this.exitWithError(this.formatError(error));
67
- }
68
- }
69
-
70
- private handleMldsa(options: { level: string; output?: string; json?: boolean }): void {
71
- try {
72
- const levelNum = parseInt(options.level, 10);
73
- if (!isValidMldsaLevel(levelNum)) {
74
- this.exitWithError(`Invalid MLDSA level: ${options.level}. Valid: 44, 65, 87`);
75
- return; // Unreachable, but helps TypeScript
76
- }
77
-
78
- this.logger.info(`Generating MLDSA-${levelNum} keypair...`);
79
-
80
- const keypair = generateMLDSAKeypair(levelNum);
81
- const publicKeyHash = computePublicKeyHash(keypair.publicKey);
82
-
83
- if (options.output) {
84
- const privateKeyPath = `${options.output}.private.key`;
85
- const publicKeyPath = `${options.output}.public.key`;
86
-
87
- fs.writeFileSync(privateKeyPath, keypair.privateKey.toString('hex') + '\n', {
88
- mode: 0o600,
89
- });
90
- fs.writeFileSync(publicKeyPath, keypair.publicKey.toString('hex') + '\n', {
91
- mode: 0o644,
92
- });
93
-
94
- this.logger.success('Keys generated successfully!');
95
- this.logger.info(` Private key: ${privateKeyPath}`);
96
- this.logger.info(` Public key: ${publicKeyPath}`);
97
- this.logger.log('');
98
- this.logger.log(`Public Key Hash: ${publicKeyHash}`);
99
- this.logger.log('');
100
- this.logger.warn('IMPORTANT: Keep the private key secure!');
101
- } else if (options.json) {
102
- const output = {
103
- level: levelNum,
104
- privateKey: keypair.privateKey.toString('hex'),
105
- publicKey: keypair.publicKey.toString('hex'),
106
- publicKeyHash,
107
- privateKeySize: keypair.privateKey.length,
108
- publicKeySize: keypair.publicKey.length,
109
- };
110
- this.logger.log(JSON.stringify(output, null, 2));
111
- } else {
112
- this.logger.info(`\nMLDSA-${levelNum} Keypair:\n`);
113
- this.logger.log(`Public Key Hash: ${publicKeyHash}`);
114
- this.logger.log(`Public Key Size: ${keypair.publicKey.length} bytes`);
115
- this.logger.log(`Private Key Size: ${keypair.privateKey.length} bytes`);
116
- this.logger.log('');
117
- this.logger.log('Public Key (hex):');
118
- this.logger.log(keypair.publicKey.toString('hex'));
119
- this.logger.log('');
120
- this.logger.log('Private Key (hex):');
121
- this.logger.log(keypair.privateKey.toString('hex'));
122
- this.logger.log('');
123
- this.logger.warn('IMPORTANT: Store the private key securely!');
124
- this.logger.warn('Use --output <prefix> to save to files.');
125
- }
126
- } catch (error) {
127
- this.exitWithError(this.formatError(error));
128
- }
129
- }
130
-
131
- private handleInfo(): void {
132
- this.logger.info('\nMLDSA Key Sizes:\n');
133
- this.logger.log('─'.repeat(60));
134
- this.logger.log(
135
- `${'Level'.padEnd(12)}${'Public Key'.padEnd(15)}${'Private Key'.padEnd(15)}${'Signature'.padEnd(15)}`,
136
- );
137
- this.logger.log('─'.repeat(60));
138
- this.logger.log(
139
- `${'MLDSA-44'.padEnd(12)}${'1,312 bytes'.padEnd(15)}${'2,560 bytes'.padEnd(15)}${'2,420 bytes'.padEnd(15)}`,
140
- );
141
- this.logger.log(
142
- `${'MLDSA-65'.padEnd(12)}${'1,952 bytes'.padEnd(15)}${'4,032 bytes'.padEnd(15)}${'3,309 bytes'.padEnd(15)}`,
143
- );
144
- this.logger.log(
145
- `${'MLDSA-87'.padEnd(12)}${'2,592 bytes'.padEnd(15)}${'4,896 bytes'.padEnd(15)}${'4,627 bytes'.padEnd(15)}`,
146
- );
147
- this.logger.log('─'.repeat(60));
148
- this.logger.log('');
149
- this.logger.log('Security levels:');
150
- this.logger.log(' MLDSA-44: ~128-bit security (fastest, smallest)');
151
- this.logger.log(' MLDSA-65: ~192-bit security (balanced)');
152
- this.logger.log(' MLDSA-87: ~256-bit security (highest security)');
153
- this.logger.log('');
154
- }
155
- }
156
-
157
- export const keygenCommand = new KeygenCommand().getCommand();
@@ -1,169 +0,0 @@
1
- /**
2
- * List command - List installed plugins
3
- *
4
- * @module commands/ListCommand
5
- */
6
-
7
- import * as fs from 'fs';
8
- import * as path from 'path';
9
- import { BaseCommand } from './BaseCommand.js';
10
- import { formatFileSize, parseOpnetBinary } from '../lib/binary.js';
11
- import { CLIMldsaLevel } from '../types/index.js';
12
-
13
- interface ListOptions {
14
- dir?: string;
15
- json?: boolean;
16
- verbose?: boolean;
17
- }
18
-
19
- interface PluginInfo {
20
- file: string;
21
- name: string;
22
- version: string;
23
- type: string;
24
- size: number;
25
- signed: boolean;
26
- mldsaLevel: CLIMldsaLevel;
27
- author: string;
28
- description?: string;
29
- }
30
-
31
- export class ListCommand extends BaseCommand {
32
- constructor() {
33
- super('list', 'List installed plugins');
34
- }
35
-
36
- protected configure(): void {
37
- this.command
38
- .alias('ls')
39
- .option('-d, --dir <path>', 'Plugins directory (default: ./plugins/)')
40
- .option('--json', 'Output as JSON')
41
- .option('-v, --verbose', 'Show detailed information')
42
- .action((options?: ListOptions) => this.execute(options));
43
- }
44
-
45
- private execute(options?: ListOptions): void {
46
- try {
47
- const pluginsDir = options?.dir || path.join(process.cwd(), 'plugins');
48
-
49
- if (!fs.existsSync(pluginsDir)) {
50
- if (options?.json) {
51
- this.logger.log(JSON.stringify({ plugins: [], directory: pluginsDir }));
52
- } else {
53
- this.logger.warn('No plugins directory found.');
54
- this.logger.info(`Expected: ${pluginsDir}`);
55
- }
56
- return;
57
- }
58
-
59
- // Find all .opnet files
60
- const files = fs.readdirSync(pluginsDir).filter((f) => f.endsWith('.opnet'));
61
-
62
- if (files.length === 0) {
63
- if (options?.json) {
64
- this.logger.log(JSON.stringify({ plugins: [], directory: pluginsDir }));
65
- } else {
66
- this.logger.warn('No plugins installed.');
67
- }
68
- return;
69
- }
70
-
71
- const plugins: PluginInfo[] = [];
72
-
73
- // Parse each plugin
74
- for (const file of files) {
75
- const filePath = path.join(pluginsDir, file);
76
-
77
- try {
78
- const data = fs.readFileSync(filePath);
79
- const parsed = parseOpnetBinary(data);
80
- const isUnsigned = parsed.publicKey.every((b) => b === 0);
81
- const mldsaLevel = ([44, 65, 87] as const)[parsed.mldsaLevel];
82
-
83
- plugins.push({
84
- file,
85
- name: parsed.metadata.name,
86
- version: parsed.metadata.version,
87
- type: parsed.metadata.pluginType,
88
- size: data.length,
89
- signed: !isUnsigned,
90
- mldsaLevel,
91
- author: parsed.metadata.author.name,
92
- description: parsed.metadata.description,
93
- });
94
- } catch {
95
- plugins.push({
96
- file,
97
- name: '(invalid)',
98
- version: '-',
99
- type: '-',
100
- size: fs.statSync(filePath).size,
101
- signed: false,
102
- mldsaLevel: 44,
103
- author: '-',
104
- });
105
- }
106
- }
107
-
108
- // Sort by name
109
- plugins.sort((a, b) => a.name.localeCompare(b.name));
110
-
111
- if (options?.json) {
112
- this.logger.log(JSON.stringify({ plugins, directory: pluginsDir }, null, 2));
113
- return;
114
- }
115
-
116
- // Display
117
- this.logger.info('\nInstalled Plugins\n');
118
- this.logger.info(`Directory: ${pluginsDir}`);
119
- this.logger.log('');
120
-
121
- if (options?.verbose) {
122
- // Detailed list
123
- for (const plugin of plugins) {
124
- this.logger.info('─'.repeat(60));
125
- this.logger.info(`${plugin.name} @ ${plugin.version}`);
126
- this.logger.info(` Type: ${plugin.type}`);
127
- this.logger.info(` Size: ${formatFileSize(plugin.size)}`);
128
- this.logger.info(` Signed: ${plugin.signed ? 'Yes' : 'No'}`);
129
- this.logger.info(` MLDSA: ${plugin.mldsaLevel}`);
130
- this.logger.info(` Author: ${plugin.author}`);
131
- if (plugin.description) {
132
- this.logger.info(` Desc: ${plugin.description}`);
133
- }
134
- this.logger.info(` File: ${plugin.file}`);
135
- }
136
- } else {
137
- // Simple table
138
- const nameWidth = Math.max(20, ...plugins.map((p) => p.name.length)) + 2;
139
- const versionWidth = 12;
140
- const typeWidth = 12;
141
- const sizeWidth = 10;
142
-
143
- this.logger.info(
144
- 'Name'.padEnd(nameWidth) +
145
- 'Version'.padEnd(versionWidth) +
146
- 'Type'.padEnd(typeWidth) +
147
- 'Size'.padEnd(sizeWidth) +
148
- 'Signed',
149
- );
150
- this.logger.info('─'.repeat(nameWidth + versionWidth + typeWidth + sizeWidth + 8));
151
-
152
- for (const plugin of plugins) {
153
- const signedText = plugin.signed ? 'Yes' : 'No';
154
- this.logger.info(
155
- `${plugin.name.padEnd(nameWidth)}${plugin.version.padEnd(versionWidth)}${plugin.type.padEnd(typeWidth)}${formatFileSize(plugin.size).padEnd(sizeWidth)}${signedText}`,
156
- );
157
- }
158
- }
159
-
160
- this.logger.log('');
161
- this.logger.info(`Total: ${plugins.length} plugin${plugins.length === 1 ? '' : 's'}`);
162
- this.logger.log('');
163
- } catch (error) {
164
- this.exitWithError(this.formatError(error));
165
- }
166
- }
167
- }
168
-
169
- export const listCommand = new ListCommand().getCommand();