@btc-vision/cli 1.0.0

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 (110) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/dependabot.yml +9 -0
  3. package/.github/workflows/ci.yml +48 -0
  4. package/.prettierrc.json +12 -0
  5. package/CONTRIBUTING.md +56 -0
  6. package/LICENSE +190 -0
  7. package/NOTICE +17 -0
  8. package/README.md +509 -0
  9. package/SECURITY.md +35 -0
  10. package/build/commands/AcceptCommand.d.ts +7 -0
  11. package/build/commands/AcceptCommand.js +110 -0
  12. package/build/commands/BaseCommand.d.ts +12 -0
  13. package/build/commands/BaseCommand.js +27 -0
  14. package/build/commands/CompileCommand.d.ts +7 -0
  15. package/build/commands/CompileCommand.js +138 -0
  16. package/build/commands/ConfigCommand.d.ts +17 -0
  17. package/build/commands/ConfigCommand.js +124 -0
  18. package/build/commands/DeprecateCommand.d.ts +7 -0
  19. package/build/commands/DeprecateCommand.js +112 -0
  20. package/build/commands/InfoCommand.d.ts +10 -0
  21. package/build/commands/InfoCommand.js +223 -0
  22. package/build/commands/InitCommand.d.ts +16 -0
  23. package/build/commands/InitCommand.js +336 -0
  24. package/build/commands/InstallCommand.d.ts +7 -0
  25. package/build/commands/InstallCommand.js +130 -0
  26. package/build/commands/KeygenCommand.d.ts +13 -0
  27. package/build/commands/KeygenCommand.js +133 -0
  28. package/build/commands/ListCommand.d.ts +7 -0
  29. package/build/commands/ListCommand.js +117 -0
  30. package/build/commands/LoginCommand.d.ts +9 -0
  31. package/build/commands/LoginCommand.js +139 -0
  32. package/build/commands/LogoutCommand.d.ts +7 -0
  33. package/build/commands/LogoutCommand.js +57 -0
  34. package/build/commands/PublishCommand.d.ts +7 -0
  35. package/build/commands/PublishCommand.js +163 -0
  36. package/build/commands/SearchCommand.d.ts +7 -0
  37. package/build/commands/SearchCommand.js +97 -0
  38. package/build/commands/SignCommand.d.ts +7 -0
  39. package/build/commands/SignCommand.js +80 -0
  40. package/build/commands/TransferCommand.d.ts +8 -0
  41. package/build/commands/TransferCommand.js +179 -0
  42. package/build/commands/UndeprecateCommand.d.ts +7 -0
  43. package/build/commands/UndeprecateCommand.js +95 -0
  44. package/build/commands/UpdateCommand.d.ts +7 -0
  45. package/build/commands/UpdateCommand.js +130 -0
  46. package/build/commands/VerifyCommand.d.ts +7 -0
  47. package/build/commands/VerifyCommand.js +167 -0
  48. package/build/commands/WhoamiCommand.d.ts +7 -0
  49. package/build/commands/WhoamiCommand.js +84 -0
  50. package/build/index.d.ts +2 -0
  51. package/build/index.js +64 -0
  52. package/build/lib/PackageRegistry.abi.d.ts +2 -0
  53. package/build/lib/PackageRegistry.abi.js +356 -0
  54. package/build/lib/binary.d.ts +16 -0
  55. package/build/lib/binary.js +165 -0
  56. package/build/lib/config.d.ts +11 -0
  57. package/build/lib/config.js +160 -0
  58. package/build/lib/credentials.d.ts +10 -0
  59. package/build/lib/credentials.js +89 -0
  60. package/build/lib/ipfs.d.ts +16 -0
  61. package/build/lib/ipfs.js +209 -0
  62. package/build/lib/manifest.d.ts +14 -0
  63. package/build/lib/manifest.js +88 -0
  64. package/build/lib/provider.d.ts +9 -0
  65. package/build/lib/provider.js +48 -0
  66. package/build/lib/registry.d.ts +58 -0
  67. package/build/lib/registry.js +197 -0
  68. package/build/lib/wallet.d.ts +32 -0
  69. package/build/lib/wallet.js +114 -0
  70. package/build/types/PackageRegistry.d.ts +177 -0
  71. package/build/types/PackageRegistry.js +1 -0
  72. package/build/types/index.d.ts +30 -0
  73. package/build/types/index.js +52 -0
  74. package/eslint.config.js +41 -0
  75. package/gulpfile.js +41 -0
  76. package/package.json +83 -0
  77. package/src/commands/AcceptCommand.ts +151 -0
  78. package/src/commands/BaseCommand.ts +59 -0
  79. package/src/commands/CompileCommand.ts +196 -0
  80. package/src/commands/ConfigCommand.ts +144 -0
  81. package/src/commands/DeprecateCommand.ts +156 -0
  82. package/src/commands/InfoCommand.ts +293 -0
  83. package/src/commands/InitCommand.ts +465 -0
  84. package/src/commands/InstallCommand.ts +179 -0
  85. package/src/commands/KeygenCommand.ts +157 -0
  86. package/src/commands/ListCommand.ts +169 -0
  87. package/src/commands/LoginCommand.ts +197 -0
  88. package/src/commands/LogoutCommand.ts +76 -0
  89. package/src/commands/PublishCommand.ts +230 -0
  90. package/src/commands/SearchCommand.ts +141 -0
  91. package/src/commands/SignCommand.ts +122 -0
  92. package/src/commands/TransferCommand.ts +235 -0
  93. package/src/commands/UndeprecateCommand.ts +134 -0
  94. package/src/commands/UpdateCommand.ts +200 -0
  95. package/src/commands/VerifyCommand.ts +228 -0
  96. package/src/commands/WhoamiCommand.ts +113 -0
  97. package/src/index.ts +86 -0
  98. package/src/lib/PackageRegistry.abi.json +765 -0
  99. package/src/lib/PackageRegistry.abi.ts +365 -0
  100. package/src/lib/binary.ts +336 -0
  101. package/src/lib/config.ts +265 -0
  102. package/src/lib/credentials.ts +176 -0
  103. package/src/lib/ipfs.ts +369 -0
  104. package/src/lib/manifest.ts +172 -0
  105. package/src/lib/provider.ts +121 -0
  106. package/src/lib/registry.ts +464 -0
  107. package/src/lib/wallet.ts +271 -0
  108. package/src/types/PackageRegistry.ts +344 -0
  109. package/src/types/index.ts +145 -0
  110. package/tsconfig.json +25 -0
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Info command - Display plugin or .opnet file information
3
+ *
4
+ * @module commands/InfoCommand
5
+ */
6
+
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import * as crypto from 'crypto';
10
+ import { IPluginPermissions } from '@btc-vision/plugin-sdk';
11
+ import { BaseCommand } from './BaseCommand.js';
12
+ import { formatFileSize, getParsedMldsaLevel, parseOpnetBinary } from '../lib/binary.js';
13
+ import { getManifestPath, loadManifest } from '../lib/manifest.js';
14
+
15
+ interface InfoOptions {
16
+ json?: boolean;
17
+ }
18
+
19
+ export class InfoCommand extends BaseCommand {
20
+ constructor() {
21
+ super('info', 'Display information about a plugin or .opnet file');
22
+ }
23
+
24
+ protected configure(): void {
25
+ this.command
26
+ .argument(
27
+ '[path]',
28
+ 'Path to plugin directory or .opnet file (default: current directory)',
29
+ )
30
+ .option('--json', 'Output as JSON')
31
+ .action((inputPath?: string, options?: InfoOptions) =>
32
+ this.execute(inputPath, options),
33
+ );
34
+ }
35
+
36
+ private execute(inputPath?: string, options?: InfoOptions): void {
37
+ try {
38
+ const targetPath = inputPath ? path.resolve(inputPath) : process.cwd();
39
+
40
+ if (!fs.existsSync(targetPath)) {
41
+ this.exitWithError(`Path not found: ${targetPath}`);
42
+ }
43
+
44
+ const stat = fs.statSync(targetPath);
45
+
46
+ if (stat.isFile() && targetPath.endsWith('.opnet')) {
47
+ this.displayBinaryInfo(targetPath, options?.json);
48
+ } else if (stat.isDirectory()) {
49
+ this.displayProjectInfo(targetPath, options?.json);
50
+ } else if (stat.isFile() && targetPath.endsWith('plugin.json')) {
51
+ this.displayProjectInfo(path.dirname(targetPath), options?.json);
52
+ } else {
53
+ this.exitWithError('Invalid path. Provide a plugin directory or .opnet file.');
54
+ }
55
+ } catch (error) {
56
+ this.exitWithError(this.formatError(error));
57
+ }
58
+ }
59
+
60
+ private displayBinaryInfo(filePath: string, json?: boolean): void {
61
+ const data = fs.readFileSync(filePath);
62
+ const parsed = parseOpnetBinary(data);
63
+ const mldsaLevel = getParsedMldsaLevel(parsed);
64
+
65
+ const isUnsigned = parsed.publicKey.every((b) => b === 0);
66
+ const publicKeyHash = crypto.createHash('sha256').update(parsed.publicKey).digest('hex');
67
+
68
+ if (json) {
69
+ const output = {
70
+ type: 'binary',
71
+ file: filePath,
72
+ fileSize: data.length,
73
+ formatVersion: parsed.formatVersion,
74
+ mldsaLevel,
75
+ signed: !isUnsigned,
76
+ publicKeyHash: isUnsigned ? null : publicKeyHash,
77
+ metadata: parsed.metadata,
78
+ sizes: {
79
+ metadata: parsed.rawMetadata.length,
80
+ bytecode: parsed.bytecode.length,
81
+ proto: parsed.proto?.length ?? 0,
82
+ publicKey: parsed.publicKey.length,
83
+ signature: parsed.signature.length,
84
+ },
85
+ };
86
+ this.logger.log(JSON.stringify(output, null, 2));
87
+ return;
88
+ }
89
+
90
+ const meta = parsed.metadata;
91
+
92
+ this.logger.info('\nOPNet Binary Information\n');
93
+ this.logger.log('─'.repeat(60));
94
+
95
+ this.logger.log(`File: ${filePath}`);
96
+ this.logger.log(`Size: ${formatFileSize(data.length)}`);
97
+ this.logger.log(`Format: v${parsed.formatVersion}`);
98
+ this.logger.log('');
99
+
100
+ this.logger.log('Plugin:');
101
+ this.logger.log(` Name: ${meta.name}`);
102
+ this.logger.log(` Version: ${meta.version}`);
103
+ this.logger.log(` Type: ${meta.pluginType}`);
104
+ this.logger.log(` OPNet: ${meta.opnetVersion}`);
105
+ if (meta.description) {
106
+ this.logger.log(` Description: ${meta.description}`);
107
+ }
108
+ this.logger.log('');
109
+
110
+ this.logger.log('Author:');
111
+ this.logger.log(` Name: ${meta.author.name}`);
112
+ if (meta.author.email) {
113
+ this.logger.log(` Email: ${meta.author.email}`);
114
+ }
115
+ this.logger.log('');
116
+
117
+ this.logger.log('Cryptography:');
118
+ this.logger.log(` MLDSA Level: MLDSA-${mldsaLevel}`);
119
+ this.logger.log(` Signed: ${isUnsigned ? 'No' : 'Yes'}`);
120
+ if (!isUnsigned) {
121
+ this.logger.log(` Publisher: ${publicKeyHash.substring(0, 32)}...`);
122
+ }
123
+ this.logger.log('');
124
+
125
+ this.logger.log('Sizes:');
126
+ this.logger.log(` Bytecode: ${formatFileSize(parsed.bytecode.length)}`);
127
+ this.logger.log(` Metadata: ${formatFileSize(parsed.rawMetadata.length)}`);
128
+ this.logger.log(` Proto: ${formatFileSize(parsed.proto?.length ?? 0)}`);
129
+ this.logger.log('');
130
+
131
+ this.logger.log('Permissions:');
132
+ this.displayPermissions(meta.permissions);
133
+ this.logger.log('');
134
+
135
+ if (Object.keys(meta.dependencies || {}).length > 0) {
136
+ this.logger.log('Dependencies:');
137
+ for (const [name, version] of Object.entries(meta.dependencies || {})) {
138
+ this.logger.log(` ${name}: ${version}`);
139
+ }
140
+ this.logger.log('');
141
+ }
142
+ }
143
+
144
+ private displayProjectInfo(projectDir: string, json?: boolean): void {
145
+ const manifestPath = getManifestPath(projectDir);
146
+
147
+ if (!fs.existsSync(manifestPath)) {
148
+ this.logger.fail('No plugin.json found in this directory.');
149
+ this.logger.info('Run `opnet init` to create a new plugin project.');
150
+ process.exit(1);
151
+ }
152
+
153
+ const manifest = loadManifest(manifestPath);
154
+
155
+ // Check for compiled binary
156
+ const binaryPath = path.join(
157
+ projectDir,
158
+ 'build',
159
+ `${manifest.name.replace(/^@/, '').replace(/\//g, '-')}.opnet`,
160
+ );
161
+ const hasBinary = fs.existsSync(binaryPath);
162
+ let binarySize: number | null = null;
163
+ if (hasBinary) {
164
+ binarySize = fs.statSync(binaryPath).size;
165
+ }
166
+
167
+ // Check for source files
168
+ const srcDir = path.join(projectDir, 'src');
169
+ const hasSrc = fs.existsSync(srcDir);
170
+
171
+ // Check for node_modules
172
+ const hasNodeModules = fs.existsSync(path.join(projectDir, 'node_modules'));
173
+
174
+ if (json) {
175
+ const output = {
176
+ type: 'project',
177
+ directory: projectDir,
178
+ manifest,
179
+ compiled: hasBinary,
180
+ binaryPath: hasBinary ? binaryPath : null,
181
+ binarySize,
182
+ hasSource: hasSrc,
183
+ hasNodeModules,
184
+ };
185
+ this.logger.log(JSON.stringify(output, null, 2));
186
+ return;
187
+ }
188
+
189
+ this.logger.info('\nOPNet Plugin Project\n');
190
+ this.logger.log('─'.repeat(60));
191
+
192
+ this.logger.log(`Directory: ${projectDir}`);
193
+ this.logger.log('');
194
+
195
+ this.logger.log('Plugin:');
196
+ this.logger.log(` Name: ${manifest.name}`);
197
+ this.logger.log(` Version: ${manifest.version}`);
198
+ this.logger.log(` Type: ${manifest.pluginType}`);
199
+ this.logger.log(` OPNet: ${manifest.opnetVersion}`);
200
+ if (manifest.description) {
201
+ this.logger.log(` Description: ${manifest.description}`);
202
+ }
203
+ this.logger.log('');
204
+
205
+ this.logger.log('Author:');
206
+ this.logger.log(` Name: ${manifest.author.name}`);
207
+ if (manifest.author.email) {
208
+ this.logger.log(` Email: ${manifest.author.email}`);
209
+ }
210
+ this.logger.log('');
211
+
212
+ this.logger.log('Status:');
213
+ this.logger.log(` Source: ${hasSrc ? 'Found' : 'Missing'}`);
214
+ this.logger.log(` Dependencies: ${hasNodeModules ? 'Installed' : 'Not installed'}`);
215
+ this.logger.log(
216
+ ` Compiled: ${hasBinary && binarySize !== null ? `Yes (${formatFileSize(binarySize)})` : 'No'}`,
217
+ );
218
+ this.logger.log('');
219
+
220
+ this.logger.log('Permissions:');
221
+ this.displayPermissions(manifest.permissions);
222
+ this.logger.log('');
223
+
224
+ if (manifest.resources) {
225
+ this.logger.log('Resources:');
226
+ if (manifest.resources.memory) {
227
+ this.logger.log(
228
+ ` Max Heap: ${manifest.resources.memory.maxHeapMB ?? 'N/A'} MB`,
229
+ );
230
+ }
231
+ if (manifest.resources.cpu) {
232
+ this.logger.log(` Max Threads: ${manifest.resources.cpu.maxThreads ?? 'N/A'}`);
233
+ this.logger.log(` Priority: ${manifest.resources.cpu.priority ?? 'normal'}`);
234
+ }
235
+ if (manifest.resources.timeout) {
236
+ this.logger.log(
237
+ ` Init Timeout: ${manifest.resources.timeout.initMs ?? 'N/A'} ms`,
238
+ );
239
+ this.logger.log(
240
+ ` Hook Timeout: ${manifest.resources.timeout.hookMs ?? 'N/A'} ms`,
241
+ );
242
+ }
243
+ this.logger.log('');
244
+ }
245
+
246
+ if (Object.keys(manifest.dependencies || {}).length > 0) {
247
+ this.logger.log('Plugin Dependencies:');
248
+ for (const [name, version] of Object.entries(manifest.dependencies || {})) {
249
+ this.logger.log(` ${name}: ${version}`);
250
+ }
251
+ this.logger.log('');
252
+ }
253
+
254
+ if (manifest.lifecycle) {
255
+ this.logger.log('Lifecycle:');
256
+ this.logger.log(` Load Priority: ${manifest.lifecycle.loadPriority ?? 100}`);
257
+ this.logger.log(
258
+ ` Enabled: ${manifest.lifecycle.enabledByDefault !== false ? 'Yes' : 'No'}`,
259
+ );
260
+ this.logger.log(
261
+ ` Requires Restart: ${manifest.lifecycle.requiresRestart ? 'Yes' : 'No'}`,
262
+ );
263
+ this.logger.log('');
264
+ }
265
+ }
266
+
267
+ private displayPermissions(permissions?: IPluginPermissions): void {
268
+ if (!permissions) {
269
+ this.logger.log(' (none configured)');
270
+ return;
271
+ }
272
+ const db = permissions.database?.enabled ?? false;
273
+ const blocks =
274
+ permissions.blocks?.preProcess ||
275
+ permissions.blocks?.postProcess ||
276
+ permissions.blocks?.onChange ||
277
+ false;
278
+ const epochs = permissions.epochs?.onChange || permissions.epochs?.onFinalized || false;
279
+ const mempool = permissions.mempool?.txFeed ?? false;
280
+ const api = permissions.api?.addEndpoints || permissions.api?.addWebsocket || false;
281
+ const fsPerms =
282
+ permissions.filesystem?.configDir || permissions.filesystem?.tempDir || false;
283
+
284
+ this.logger.log(` Database: ${db ? 'Yes' : 'No'}`);
285
+ this.logger.log(` Block Hooks: ${blocks ? 'Yes' : 'No'}`);
286
+ this.logger.log(` Epoch Hooks: ${epochs ? 'Yes' : 'No'}`);
287
+ this.logger.log(` Mempool Feed: ${mempool ? 'Yes' : 'No'}`);
288
+ this.logger.log(` API Endpoints: ${api ? 'Yes' : 'No'}`);
289
+ this.logger.log(` Filesystem: ${fsPerms ? 'Yes' : 'No'}`);
290
+ }
291
+ }
292
+
293
+ export const infoCommand = new InfoCommand().getCommand();