@btc-vision/cli 1.0.5 → 1.0.7

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 (51) hide show
  1. package/build/index.js +3 -4
  2. package/build/lib/config.js +1 -6
  3. package/build/lib/ipfs.d.ts +0 -2
  4. package/build/lib/ipfs.js +29 -32
  5. package/build/lib/wallet.js +1 -1
  6. package/package.json +4 -1
  7. package/.gitattributes +0 -2
  8. package/.github/dependabot.yml +0 -9
  9. package/.github/workflows/ci.yml +0 -48
  10. package/.prettierrc.json +0 -12
  11. package/CONTRIBUTING.md +0 -56
  12. package/NOTICE +0 -17
  13. package/SECURITY.md +0 -35
  14. package/eslint.config.js +0 -41
  15. package/gulpfile.js +0 -41
  16. package/src/commands/AcceptCommand.ts +0 -224
  17. package/src/commands/BaseCommand.ts +0 -59
  18. package/src/commands/CompileCommand.ts +0 -195
  19. package/src/commands/ConfigCommand.ts +0 -117
  20. package/src/commands/DeprecateCommand.ts +0 -193
  21. package/src/commands/InfoCommand.ts +0 -293
  22. package/src/commands/InitCommand.ts +0 -541
  23. package/src/commands/InstallCommand.ts +0 -179
  24. package/src/commands/KeygenCommand.ts +0 -157
  25. package/src/commands/ListCommand.ts +0 -169
  26. package/src/commands/LoginCommand.ts +0 -197
  27. package/src/commands/LogoutCommand.ts +0 -76
  28. package/src/commands/PublishCommand.ts +0 -340
  29. package/src/commands/ScopeRegisterCommand.ts +0 -164
  30. package/src/commands/SearchCommand.ts +0 -140
  31. package/src/commands/SignCommand.ts +0 -110
  32. package/src/commands/TransferCommand.ts +0 -363
  33. package/src/commands/UndeprecateCommand.ts +0 -167
  34. package/src/commands/UpdateCommand.ts +0 -200
  35. package/src/commands/VerifyCommand.ts +0 -228
  36. package/src/commands/WhoamiCommand.ts +0 -113
  37. package/src/index.ts +0 -88
  38. package/src/lib/PackageRegistry.abi.json +0 -765
  39. package/src/lib/PackageRegistry.abi.ts +0 -365
  40. package/src/lib/binary.ts +0 -338
  41. package/src/lib/config.ts +0 -265
  42. package/src/lib/credentials.ts +0 -176
  43. package/src/lib/ipfs.ts +0 -382
  44. package/src/lib/manifest.ts +0 -195
  45. package/src/lib/provider.ts +0 -121
  46. package/src/lib/registry.ts +0 -467
  47. package/src/lib/transaction.ts +0 -205
  48. package/src/lib/wallet.ts +0 -262
  49. package/src/types/PackageRegistry.ts +0 -344
  50. package/src/types/index.ts +0 -147
  51. 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();