@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,164 +0,0 @@
1
- /**
2
- * Scope Register command - Register a new scope in the registry
3
- *
4
- * @module commands/ScopeRegisterCommand
5
- */
6
-
7
- import { confirm } from '@inquirer/prompts';
8
- import { BaseCommand } from './BaseCommand.js';
9
- import { getRegistryContract, getScope, getScopePrice } from '../lib/registry.js';
10
- import { canSign, loadCredentials } from '../lib/credentials.js';
11
- import { CLIWallet } from '../lib/wallet.js';
12
- import {
13
- buildTransactionParams,
14
- checkBalance,
15
- formatSats,
16
- getWalletAddress,
17
- } from '../lib/transaction.js';
18
- import { NetworkName } from '../types/index.js';
19
-
20
- interface ScopeRegisterOptions {
21
- network: string;
22
- yes?: boolean;
23
- }
24
-
25
- export class ScopeRegisterCommand extends BaseCommand {
26
- constructor() {
27
- super('scope:register', 'Register a new scope in the registry');
28
- }
29
-
30
- protected configure(): void {
31
- this.command
32
- .argument('<name>', 'Scope name (without @)')
33
- .option('-n, --network <network>', 'Network', 'mainnet')
34
- .option('-y, --yes', 'Skip confirmation')
35
- .action((name: string, options?: ScopeRegisterOptions) =>
36
- this.execute(name, options || { network: 'mainnet' }),
37
- );
38
- }
39
-
40
- private async execute(name: string, options?: ScopeRegisterOptions): Promise<void> {
41
- try {
42
- // Remove @ prefix if provided
43
- const scopeName = name.startsWith('@') ? name.substring(1) : name;
44
-
45
- // Validate scope name
46
- if (!/^[a-z][a-z0-9-]*[a-z0-9]$/.test(scopeName) && !/^[a-z]$/.test(scopeName)) {
47
- this.logger.fail('Invalid scope name');
48
- this.logger.error('Scope name must:');
49
- this.logger.error(' - Start with a lowercase letter');
50
- this.logger.error(' - Contain only lowercase letters, numbers, and hyphens');
51
- this.logger.error(' - End with a letter or number');
52
- process.exit(1);
53
- }
54
-
55
- // Load credentials
56
- this.logger.info('Loading wallet...');
57
- const credentials = loadCredentials();
58
- if (!credentials || !canSign(credentials)) {
59
- this.logger.fail('No credentials configured');
60
- this.logger.warn('Run `opnet login` to configure your wallet.');
61
- process.exit(1);
62
- }
63
- const wallet = CLIWallet.fromCredentials(credentials);
64
- this.logger.success('Wallet loaded');
65
-
66
- const network = (options?.network || 'mainnet') as NetworkName;
67
-
68
- // Check if scope already exists
69
- this.logger.info(`Checking if @${scopeName} is available...`);
70
- const existingScope = await getScope(scopeName, network);
71
- if (existingScope) {
72
- this.logger.fail('Scope already registered');
73
- this.logger.error(`Scope @${scopeName} is already registered.`);
74
- this.logger.log(`Owner: ${existingScope.owner}`);
75
- process.exit(1);
76
- }
77
- this.logger.success(`Scope @${scopeName} is available`);
78
-
79
- // Get scope registration price
80
- this.logger.info('Fetching registration price...');
81
- const scopePrice = await getScopePrice(network);
82
- this.logger.success(`Registration price: ${formatSats(scopePrice)}`);
83
-
84
- // Check wallet balance
85
- this.logger.info('Checking wallet balance...');
86
- const minRequired = scopePrice + 50_000n; // Price + estimated fees
87
- const { sufficient, balance } = await checkBalance(wallet, network, minRequired);
88
- if (!sufficient) {
89
- this.logger.fail('Insufficient balance');
90
- this.logger.error(`Wallet balance: ${formatSats(balance)}`);
91
- this.logger.error(`Required (approx): ${formatSats(minRequired)}`);
92
- this.logger.error('Please fund your wallet before registering a scope.');
93
- process.exit(1);
94
- }
95
- this.logger.success(`Wallet balance: ${formatSats(balance)}`);
96
-
97
- // Display summary
98
- this.logger.log('');
99
- this.logger.info('Scope Registration Summary');
100
- this.logger.log('─'.repeat(50));
101
- this.logger.log(`Scope: @${scopeName}`);
102
- this.logger.log(`Price: ${formatSats(scopePrice)}`);
103
- this.logger.log(`Network: ${options?.network}`);
104
- this.logger.log(`Address: ${wallet.p2trAddress}`);
105
- this.logger.log('');
106
-
107
- // Confirmation
108
- if (!options?.yes) {
109
- const confirmed = await confirm({
110
- message: `Register scope @${scopeName}?`,
111
- default: true,
112
- });
113
-
114
- if (!confirmed) {
115
- this.logger.warn('Registration cancelled.');
116
- return;
117
- }
118
- }
119
-
120
- // Execute registration
121
- this.logger.info('Registering scope...');
122
-
123
- const sender = getWalletAddress(wallet);
124
- const contract = getRegistryContract(network, sender);
125
- const txParams = buildTransactionParams(wallet, network);
126
-
127
- const registerResult = await contract.registerScope(scopeName);
128
-
129
- if (registerResult.revert) {
130
- this.logger.fail('Registration would fail');
131
- this.logger.error(`Reason: ${registerResult.revert}`);
132
- process.exit(1);
133
- }
134
-
135
- if (registerResult.estimatedGas) {
136
- this.logger.info(`Estimated gas: ${registerResult.estimatedGas} sats`);
137
- }
138
-
139
- const receipt = await registerResult.sendTransaction(txParams);
140
-
141
- this.logger.log('');
142
- this.logger.success('Scope registered successfully!');
143
- this.logger.log('');
144
- this.logger.log(`Scope: @${scopeName}`);
145
- this.logger.log(`Owner: ${wallet.p2trAddress}`);
146
- this.logger.log(`Transaction ID: ${receipt.transactionId}`);
147
- this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
148
- this.logger.log('');
149
- this.logger.info(
150
- 'You can now publish packages under this scope using: opnet publish',
151
- );
152
- this.logger.log('');
153
- } catch (error) {
154
- this.logger.fail('Scope registration failed');
155
- if (this.isUserCancelled(error)) {
156
- this.logger.warn('Registration cancelled.');
157
- process.exit(0);
158
- }
159
- this.exitWithError(this.formatError(error));
160
- }
161
- }
162
- }
163
-
164
- export const scopeRegisterCommand = new ScopeRegisterCommand().getCommand();
@@ -1,140 +0,0 @@
1
- /**
2
- * Search command - Search for plugins in the registry
3
- *
4
- * @module commands/SearchCommand
5
- */
6
-
7
- import { BaseCommand } from './BaseCommand.js';
8
- import {
9
- getPackage,
10
- getVersion,
11
- registryToMldsaLevel,
12
- registryToPluginType,
13
- VersionInfo,
14
- } from '../lib/registry.js';
15
- import { NetworkName } from '../types/index.js';
16
-
17
- interface SearchOptions {
18
- network: string;
19
- json?: boolean;
20
- }
21
-
22
- export class SearchCommand extends BaseCommand {
23
- constructor() {
24
- super('search', 'Search for plugins in the registry');
25
- }
26
-
27
- protected configure(): void {
28
- this.command
29
- .argument('<query>', 'Package name or search query')
30
- .option('-n, --network <network>', 'Network', 'mainnet')
31
- .option('--json', 'Output as JSON')
32
- .action((query: string, options?: SearchOptions) =>
33
- this.execute(query, options || { network: 'mainnet' }),
34
- );
35
- }
36
-
37
- private async execute(query: string, options?: SearchOptions): Promise<void> {
38
- try {
39
- const network = (options?.network || 'mainnet') as NetworkName;
40
-
41
- // Direct package lookup
42
- this.logger.info(`Searching for "${query}"...`);
43
-
44
- const packageInfo = await getPackage(query, network);
45
-
46
- if (!packageInfo) {
47
- this.logger.fail('No results');
48
-
49
- if (options?.json) {
50
- this.logger.log(JSON.stringify({ results: [], query }));
51
- } else {
52
- this.logger.log('');
53
- this.logger.warn(`No package found matching "${query}".`);
54
- this.logger.log('');
55
- this.logger.info('Tips:');
56
- this.logger.info(' - For scoped packages, use @scope/name');
57
- this.logger.info(' - Package names are case-sensitive');
58
- this.logger.info(' - Try searching without the version');
59
- }
60
- return;
61
- }
62
-
63
- // Get latest version details
64
- let latestVersionInfo: VersionInfo | null = null;
65
- if (packageInfo.latestVersion) {
66
- latestVersionInfo = await getVersion(query, packageInfo.latestVersion, network);
67
- }
68
-
69
- this.logger.success('Package found');
70
-
71
- if (options?.json) {
72
- const output = {
73
- results: [
74
- {
75
- name: query,
76
- latestVersion: packageInfo.latestVersion,
77
- versionCount: Number(packageInfo.versionCount),
78
- createdAt: Number(packageInfo.createdAt),
79
- owner: packageInfo.owner.toString(),
80
- details: latestVersionInfo
81
- ? {
82
- ipfsCid: latestVersionInfo.ipfsCid,
83
- mldsaLevel: registryToMldsaLevel(
84
- latestVersionInfo.mldsaLevel,
85
- ),
86
- pluginType: registryToPluginType(
87
- latestVersionInfo.pluginType,
88
- ),
89
- opnetVersion: latestVersionInfo.opnetVersionRange,
90
- deprecated: latestVersionInfo.deprecated,
91
- publishedAt: Number(latestVersionInfo.publishedAt),
92
- }
93
- : null,
94
- },
95
- ],
96
- query,
97
- };
98
- this.logger.log(JSON.stringify(output, null, 2));
99
- return;
100
- }
101
-
102
- // Display results
103
- this.logger.log('');
104
- this.logger.info('Package Information');
105
- this.logger.info('─'.repeat(60));
106
- this.logger.log('');
107
- this.logger.info(`Name: ${query}`);
108
- this.logger.info(`Latest: ${packageInfo.latestVersion || 'N/A'}`);
109
- this.logger.info(`Versions: ${packageInfo.versionCount}`);
110
- this.logger.info(`Owner: ${packageInfo.owner}`);
111
-
112
- if (latestVersionInfo) {
113
- this.logger.log('');
114
- this.logger.info('Latest Version Details:');
115
- this.logger.info(
116
- ` Type: ${registryToPluginType(latestVersionInfo.pluginType)}`,
117
- );
118
- this.logger.info(
119
- ` MLDSA Level: ${registryToMldsaLevel(latestVersionInfo.mldsaLevel)}`,
120
- );
121
- this.logger.info(` OPNet Range: ${latestVersionInfo.opnetVersionRange}`);
122
- this.logger.info(` IPFS CID: ${latestVersionInfo.ipfsCid}`);
123
- this.logger.info(` Deprecated: ${latestVersionInfo.deprecated ? 'Yes' : 'No'}`);
124
-
125
- this.logger.info(` Published at: Block ${latestVersionInfo.publishedAt}`);
126
- }
127
-
128
- this.logger.log('');
129
- this.logger.info('Install with:');
130
- this.logger.info(` opnet install ${query}`);
131
- this.logger.info(` opnet install ${query}@${packageInfo.latestVersion}`);
132
- this.logger.log('');
133
- } catch (error) {
134
- this.logger.fail('Search failed');
135
- this.exitWithError(this.formatError(error));
136
- }
137
- }
138
- }
139
-
140
- export const searchCommand = new SearchCommand().getCommand();
@@ -1,110 +0,0 @@
1
- /**
2
- * Sign command - Sign or re-sign a .opnet binary
3
- *
4
- * @module commands/SignCommand
5
- */
6
-
7
- import * as fs from 'fs';
8
- import * as crypto from 'crypto';
9
- import { BaseCommand } from './BaseCommand.js';
10
- import { buildOpnetBinary, formatFileSize, parseOpnetBinary } from '../lib/binary.js';
11
- import { CLIWallet } from '../lib/wallet.js';
12
- import { canSign, loadCredentials } from '../lib/credentials.js';
13
-
14
- interface SignOptions {
15
- output?: string;
16
- force?: boolean;
17
- }
18
-
19
- export class SignCommand extends BaseCommand {
20
- constructor() {
21
- super('sign', 'Sign or re-sign a .opnet binary with your MLDSA key');
22
- }
23
-
24
- protected configure(): void {
25
- this.command
26
- .argument('<file>', 'Path to .opnet file')
27
- .option('-o, --output <path>', 'Output file path (default: overwrites input)')
28
- .option('--force', 'Force re-signing even if already signed by different key')
29
- .action((file: string, options: SignOptions) => this.execute(file, options));
30
- }
31
-
32
- private execute(file: string, options: SignOptions): void {
33
- try {
34
- if (!fs.existsSync(file)) {
35
- this.exitWithError(`File not found: ${file}`);
36
- }
37
-
38
- // Load credentials
39
- this.logger.info('Loading wallet...');
40
- const credentials = loadCredentials();
41
-
42
- if (!credentials || !canSign(credentials)) {
43
- this.logger.fail('No credentials configured');
44
- this.logger.warn('To sign plugins, run: opnet login');
45
- process.exit(1);
46
- }
47
-
48
- const wallet = CLIWallet.fromCredentials(credentials);
49
- this.logger.success(`Wallet loaded (MLDSA-${wallet.securityLevel})`);
50
-
51
- // Parse existing binary
52
- this.logger.info('Parsing binary...');
53
- const data = fs.readFileSync(file);
54
- const parsed = parseOpnetBinary(data);
55
- this.logger.success(`Parsed: ${parsed.metadata.name}@${parsed.metadata.version}`);
56
-
57
- // Check if already signed by a different key
58
- const isUnsigned = parsed.publicKey.every((b) => b === 0);
59
- const currentPkHash = crypto
60
- .createHash('sha256')
61
- .update(parsed.publicKey)
62
- .digest('hex');
63
- const newPkHash = wallet.mldsaPublicKeyHash;
64
-
65
- if (!isUnsigned && currentPkHash !== newPkHash && !options.force) {
66
- this.logger.log('');
67
- this.logger.warn('Warning: This binary is already signed by a different key.');
68
- this.logger.log(` Current signer: ${currentPkHash.substring(0, 32)}...`);
69
- this.logger.log(` Your key: ${newPkHash.substring(0, 32)}...`);
70
- this.logger.log('');
71
- this.logger.log('Use --force to re-sign with your key.');
72
- process.exit(1);
73
- }
74
-
75
- // Rebuild binary with signing
76
- this.logger.info('Signing and rebuilding binary...');
77
- const signFn = (checksum: Buffer) => wallet.signMLDSA(checksum);
78
- const { binary: newBinary, checksum } = buildOpnetBinary({
79
- mldsaLevel: wallet.securityLevel,
80
- publicKey: wallet.mldsaPublicKey,
81
- metadata: parsed.metadata,
82
- bytecode: parsed.bytecode,
83
- proto: parsed.proto ?? Buffer.alloc(0),
84
- signFn,
85
- });
86
- this.logger.success(
87
- `Signed (checksum: sha256:${checksum.toString('hex').substring(0, 16)}...)`,
88
- );
89
- this.logger.success(`Binary rebuilt (${formatFileSize(newBinary.length)})`);
90
-
91
- // Write output
92
- const outputPath = options.output || file;
93
- fs.writeFileSync(outputPath, newBinary);
94
-
95
- this.logger.log('');
96
- this.logger.success('Plugin signed successfully!');
97
- this.logger.log('');
98
- this.logger.log(`Output: ${outputPath}`);
99
- this.logger.log(`Plugin: ${parsed.metadata.name}@${parsed.metadata.version}`);
100
- this.logger.log(`MLDSA Level: ${wallet.securityLevel}`);
101
- this.logger.log(`Publisher: ${newPkHash.substring(0, 32)}...`);
102
- this.logger.log('');
103
- } catch (error) {
104
- this.logger.fail('Signing failed');
105
- this.exitWithError(this.formatError(error));
106
- }
107
- }
108
- }
109
-
110
- export const signCommand = new SignCommand().getCommand();