@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
package/README.md ADDED
@@ -0,0 +1,509 @@
1
+ # @btc-vision/cli
2
+
3
+ ![Bitcoin](https://img.shields.io/badge/Bitcoin-000?style=for-the-badge&logo=bitcoin&logoColor=white)
4
+ ![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge&logo=typescript&logoColor=white)
5
+ ![NodeJS](https://img.shields.io/badge/Node%20js-339933?style=for-the-badge&logo=nodedotjs&logoColor=white)
6
+ ![MongoDB](https://img.shields.io/badge/MongoDB-%234ea94b.svg?style=for-the-badge&logo=mongodb&logoColor=white)
7
+ ![NPM](https://img.shields.io/badge/npm-CB3837?style=for-the-badge&logo=npm&logoColor=white)
8
+ ![Gulp](https://img.shields.io/badge/GULP-%23CF4647.svg?style=for-the-badge&logo=gulp&logoColor=white)
9
+ ![ESLint](https://img.shields.io/badge/ESLint-4B3263?style=for-the-badge&logo=eslint&logoColor=white)
10
+
11
+ [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
12
+
13
+ Official command-line interface for the OPNet plugin ecosystem. Build, sign, verify, and publish plugins with quantum-resistant MLDSA signatures.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install -g @btc-vision/cli
19
+ ```
20
+
21
+ Or use npx:
22
+ ```bash
23
+ npx @btc-vision/cli <command>
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ```bash
29
+ # Initialize a new plugin project
30
+ opnet init my-plugin
31
+
32
+ # Build and compile to .opnet binary
33
+ cd my-plugin
34
+ npm install
35
+ npm run build
36
+ opnet compile
37
+
38
+ # Verify the compiled binary
39
+ opnet verify build/my-plugin.opnet
40
+
41
+ # Configure your wallet for signing
42
+ opnet login
43
+
44
+ # Publish to the registry
45
+ opnet publish
46
+ ```
47
+
48
+ ## Commands
49
+
50
+ ### Configuration
51
+
52
+ #### `opnet config`
53
+
54
+ Manage CLI configuration.
55
+
56
+ ```bash
57
+ # Show all configuration
58
+ opnet config list
59
+
60
+ # Get a specific value
61
+ opnet config get defaultNetwork
62
+ opnet config get rpcUrls.mainnet
63
+
64
+ # Set a value
65
+ opnet config set defaultNetwork testnet
66
+ opnet config set ipfsPinningApiKey "your-api-key"
67
+
68
+ # Reset to defaults
69
+ opnet config reset --yes
70
+
71
+ # Show config file path
72
+ opnet config path
73
+ ```
74
+
75
+ ### Authentication
76
+
77
+ #### `opnet login`
78
+
79
+ Configure wallet credentials for signing and publishing.
80
+
81
+ ```bash
82
+ # Interactive mode
83
+ opnet login
84
+
85
+ # With mnemonic phrase
86
+ opnet login --mnemonic "your 24 word phrase..."
87
+
88
+ # With specific network and MLDSA level
89
+ opnet login --network testnet --mldsa-level 65
90
+
91
+ # Advanced: WIF + standalone MLDSA key
92
+ opnet login --wif "KwDiBf..." --mldsa "hex-key..."
93
+ ```
94
+
95
+ **Options:**
96
+ - `-m, --mnemonic <phrase>` - BIP-39 mnemonic phrase (24 words)
97
+ - `--wif <key>` - Bitcoin WIF private key (advanced)
98
+ - `--mldsa <key>` - MLDSA private key hex (advanced, requires --wif)
99
+ - `-l, --mldsa-level <level>` - MLDSA security level (44, 65, 87) [default: 44]
100
+ - `-n, --network <network>` - Network (mainnet, testnet, regtest) [default: mainnet]
101
+ - `-y, --yes` - Skip confirmation prompts
102
+
103
+ #### `opnet logout`
104
+
105
+ Remove stored wallet credentials.
106
+
107
+ ```bash
108
+ opnet logout
109
+ opnet logout --yes
110
+ ```
111
+
112
+ #### `opnet whoami`
113
+
114
+ Display current wallet identity and configuration.
115
+
116
+ ```bash
117
+ opnet whoami
118
+ opnet whoami --verbose
119
+ opnet whoami --public-key
120
+ ```
121
+
122
+ ### Key Generation
123
+
124
+ #### `opnet keygen`
125
+
126
+ Generate cryptographic keys.
127
+
128
+ ```bash
129
+ # Generate a new mnemonic phrase
130
+ opnet keygen mnemonic
131
+ opnet keygen mnemonic --output my-mnemonic.txt
132
+
133
+ # Generate standalone MLDSA keypair
134
+ opnet keygen mldsa
135
+ opnet keygen mldsa --level 65
136
+ opnet keygen mldsa --output my-key --json
137
+
138
+ # Show MLDSA key size information
139
+ opnet keygen info
140
+ ```
141
+
142
+ ### Plugin Development
143
+
144
+ #### `opnet init`
145
+
146
+ Initialize a new OPNet plugin project.
147
+
148
+ ```bash
149
+ # Interactive mode
150
+ opnet init
151
+
152
+ # With name
153
+ opnet init my-plugin
154
+
155
+ # With options
156
+ opnet init my-plugin --template library --yes
157
+
158
+ # Force overwrite
159
+ opnet init --force
160
+ ```
161
+
162
+ **Options:**
163
+ - `-t, --template <type>` - Template type (standalone, library) [default: standalone]
164
+ - `-y, --yes` - Skip prompts and use defaults
165
+ - `--force` - Overwrite existing files
166
+
167
+ #### `opnet compile`
168
+
169
+ Compile plugin to .opnet binary format.
170
+
171
+ ```bash
172
+ # Compile current directory
173
+ opnet compile
174
+
175
+ # Compile specific directory
176
+ opnet compile --dir ./my-plugin
177
+
178
+ # Custom output path
179
+ opnet compile --output ./dist/plugin.opnet
180
+
181
+ # Skip signing (for testing)
182
+ opnet compile --no-sign
183
+ ```
184
+
185
+ **Options:**
186
+ - `-o, --output <path>` - Output file path
187
+ - `-d, --dir <path>` - Plugin directory [default: current]
188
+ - `--no-sign` - Skip signing (produce unsigned binary)
189
+ - `--minify` - Minify the bundled code [default: true]
190
+ - `--sourcemap` - Generate source maps
191
+
192
+ #### `opnet verify`
193
+
194
+ Verify a .opnet binary signature and integrity.
195
+
196
+ ```bash
197
+ opnet verify plugin.opnet
198
+ opnet verify plugin.opnet --verbose
199
+ opnet verify plugin.opnet --json
200
+ ```
201
+
202
+ **Options:**
203
+ - `-v, --verbose` - Show detailed information
204
+ - `--json` - Output as JSON
205
+
206
+ #### `opnet info`
207
+
208
+ Display information about a plugin or .opnet file.
209
+
210
+ ```bash
211
+ # Show project info
212
+ opnet info
213
+
214
+ # Show binary info
215
+ opnet info plugin.opnet
216
+
217
+ # JSON output
218
+ opnet info --json
219
+ ```
220
+
221
+ #### `opnet sign`
222
+
223
+ Sign or re-sign a .opnet binary with your MLDSA key.
224
+
225
+ ```bash
226
+ opnet sign plugin.opnet
227
+ opnet sign plugin.opnet --output signed.opnet
228
+ opnet sign plugin.opnet --force # Re-sign with different key
229
+ ```
230
+
231
+ **Options:**
232
+ - `-o, --output <path>` - Output file path [default: overwrites input]
233
+ - `--force` - Force re-signing even if already signed by different key
234
+
235
+ ### Registry Commands
236
+
237
+ #### `opnet publish`
238
+
239
+ Publish a plugin to the OPNet registry.
240
+
241
+ ```bash
242
+ # Publish from current directory
243
+ opnet publish
244
+
245
+ # Publish specific file
246
+ opnet publish plugin.opnet
247
+
248
+ # Dry run
249
+ opnet publish --dry-run
250
+
251
+ # Specific network
252
+ opnet publish --network testnet
253
+ ```
254
+
255
+ **Options:**
256
+ - `-n, --network <network>` - Network to publish to [default: mainnet]
257
+ - `--dry-run` - Show what would be published without publishing
258
+ - `-y, --yes` - Skip confirmation prompts
259
+
260
+ #### `opnet deprecate`
261
+
262
+ Mark a package version as deprecated.
263
+
264
+ ```bash
265
+ opnet deprecate @scope/plugin
266
+ opnet deprecate @scope/plugin 1.0.0
267
+ opnet deprecate @scope/plugin 1.0.0 --message "Security vulnerability"
268
+ ```
269
+
270
+ **Options:**
271
+ - `-m, --message <message>` - Deprecation reason/message
272
+ - `-n, --network <network>` - Network [default: mainnet]
273
+ - `-y, --yes` - Skip confirmation
274
+
275
+ #### `opnet undeprecate`
276
+
277
+ Remove deprecation from a package version.
278
+
279
+ ```bash
280
+ opnet undeprecate @scope/plugin 1.0.0
281
+ ```
282
+
283
+ #### `opnet transfer`
284
+
285
+ Initiate ownership transfer of a package or scope.
286
+
287
+ ```bash
288
+ # Transfer a package
289
+ opnet transfer my-plugin bc1q...
290
+
291
+ # Transfer a scope
292
+ opnet transfer @myscope bc1q...
293
+
294
+ # Cancel pending transfer
295
+ opnet transfer my-plugin --cancel
296
+ ```
297
+
298
+ **Options:**
299
+ - `-n, --network <network>` - Network [default: mainnet]
300
+ - `-y, --yes` - Skip confirmation
301
+ - `--cancel` - Cancel pending transfer
302
+
303
+ #### `opnet accept`
304
+
305
+ Accept pending ownership transfer.
306
+
307
+ ```bash
308
+ opnet accept my-plugin
309
+ opnet accept @myscope
310
+ ```
311
+
312
+ #### `opnet install`
313
+
314
+ Download and verify a plugin from the registry.
315
+
316
+ ```bash
317
+ # Install latest version
318
+ opnet install @scope/plugin
319
+
320
+ # Install specific version
321
+ opnet install @scope/plugin@1.0.0
322
+
323
+ # Install from IPFS CID
324
+ opnet install QmXyz...
325
+
326
+ # Custom output directory
327
+ opnet install @scope/plugin --output ./my-plugins
328
+ ```
329
+
330
+ **Options:**
331
+ - `-o, --output <path>` - Output directory [default: ./plugins/]
332
+ - `-n, --network <network>` - Network [default: mainnet]
333
+ - `--skip-verify` - Skip signature verification
334
+
335
+ #### `opnet update`
336
+
337
+ Update installed plugins to latest versions.
338
+
339
+ ```bash
340
+ # Update all plugins
341
+ opnet update
342
+
343
+ # Update specific plugin
344
+ opnet update @scope/plugin
345
+
346
+ # Custom plugins directory
347
+ opnet update --dir ./my-plugins
348
+ ```
349
+
350
+ **Options:**
351
+ - `-d, --dir <path>` - Plugins directory [default: ./plugins/]
352
+ - `-n, --network <network>` - Network [default: mainnet]
353
+ - `--skip-verify` - Skip signature verification
354
+
355
+ #### `opnet list`
356
+
357
+ List installed plugins.
358
+
359
+ ```bash
360
+ opnet list
361
+ opnet ls
362
+ opnet list --verbose
363
+ opnet list --json
364
+ opnet list --dir ./my-plugins
365
+ ```
366
+
367
+ **Options:**
368
+ - `-d, --dir <path>` - Plugins directory [default: ./plugins/]
369
+ - `--json` - Output as JSON
370
+ - `-v, --verbose` - Show detailed information
371
+
372
+ #### `opnet search`
373
+
374
+ Search for plugins in the registry.
375
+
376
+ ```bash
377
+ opnet search plugin-name
378
+ opnet search @scope/plugin
379
+ opnet search plugin-name --json
380
+ ```
381
+
382
+ **Options:**
383
+ - `-n, --network <network>` - Network [default: mainnet]
384
+ - `--json` - Output as JSON
385
+
386
+ ## Configuration
387
+
388
+ Configuration is stored in `~/.opnet/config.json`:
389
+
390
+ ```json
391
+ {
392
+ "defaultNetwork": "mainnet",
393
+ "rpcUrls": {
394
+ "mainnet": "https://api.opnet.org",
395
+ "testnet": "https://testnet.opnet.org",
396
+ "regtest": "http://localhost:9001"
397
+ },
398
+ "ipfsGateway": "https://ipfs.opnet.org/ipfs/",
399
+ "ipfsGateways": [
400
+ "https://ipfs.opnet.org/ipfs/",
401
+ "https://ipfs.io/ipfs/"
402
+ ],
403
+ "ipfsPinningEndpoint": "https://ipfs.opnet.org/api/v0/add",
404
+ "ipfsPinningApiKey": "",
405
+ "registryAddresses": {
406
+ "mainnet": "",
407
+ "testnet": "",
408
+ "regtest": ""
409
+ },
410
+ "defaultMldsaLevel": 44,
411
+ "indexerUrl": "https://indexer.opnet.org"
412
+ }
413
+ ```
414
+
415
+ ## Environment Variables
416
+
417
+ | Variable | Description |
418
+ |----------|-------------|
419
+ | `OPNET_MNEMONIC` | BIP-39 mnemonic phrase |
420
+ | `OPNET_PRIVATE_KEY` | Bitcoin WIF private key |
421
+ | `OPNET_MLDSA_KEY` | MLDSA private key (hex) |
422
+ | `OPNET_MLDSA_LEVEL` | MLDSA security level (44, 65, 87) |
423
+ | `OPNET_NETWORK` | Network (mainnet, testnet, regtest) |
424
+ | `OPNET_RPC_URL` | RPC endpoint URL |
425
+ | `OPNET_IPFS_GATEWAY` | IPFS gateway URL |
426
+ | `OPNET_IPFS_PINNING_ENDPOINT` | IPFS pinning service endpoint |
427
+ | `OPNET_IPFS_PINNING_KEY` | IPFS pinning API key |
428
+ | `OPNET_REGISTRY_ADDRESS` | Registry contract address |
429
+ | `OPNET_INDEXER_URL` | Indexer API URL |
430
+
431
+ ## MLDSA Security Levels
432
+
433
+ | Level | Public Key | Signature | Security |
434
+ |-------|------------|-----------|----------|
435
+ | MLDSA-44 | 1,312 bytes | 2,420 bytes | ~128-bit |
436
+ | MLDSA-65 | 1,952 bytes | 3,309 bytes | ~192-bit |
437
+ | MLDSA-87 | 2,592 bytes | 4,627 bytes | ~256-bit |
438
+
439
+ ## .opnet Binary Format (OIP-0003)
440
+
441
+ The `.opnet` binary format consists of:
442
+
443
+ 1. **Magic bytes** (8 bytes): `OPNETPLG`
444
+ 2. **Format version** (4 bytes): uint32 LE
445
+ 3. **MLDSA level** (1 byte): 0=44, 1=65, 2=87
446
+ 4. **Public key** (variable): Based on MLDSA level
447
+ 5. **Signature** (variable): Based on MLDSA level
448
+ 6. **Metadata length** (4 bytes): uint32 LE
449
+ 7. **Metadata** (variable): JSON bytes
450
+ 8. **Bytecode length** (4 bytes): uint32 LE
451
+ 9. **Bytecode** (variable): V8 bytecode
452
+ 10. **Proto length** (4 bytes): uint32 LE
453
+ 11. **Proto** (variable): Protobuf definitions
454
+ 12. **Checksum** (32 bytes): SHA-256 of metadata + bytecode + proto
455
+
456
+ ## Plugin Manifest (plugin.json)
457
+
458
+ ```json
459
+ {
460
+ "name": "my-plugin",
461
+ "version": "1.0.0",
462
+ "opnetVersion": "^1.0.0",
463
+ "main": "dist/index.jsc",
464
+ "target": "bytenode",
465
+ "type": "plugin",
466
+ "author": {
467
+ "name": "Developer Name",
468
+ "email": "dev@example.com"
469
+ },
470
+ "description": "My OPNet plugin",
471
+ "pluginType": "standalone",
472
+ "permissions": {
473
+ "database": { "enabled": false, "collections": [] },
474
+ "blocks": { "preProcess": false, "postProcess": false, "onChange": false },
475
+ "epochs": { "onChange": false, "onFinalized": false },
476
+ "mempool": { "txFeed": false },
477
+ "api": { "addEndpoints": false, "addWebsocket": false },
478
+ "filesystem": { "configDir": false, "tempDir": false }
479
+ },
480
+ "resources": {
481
+ "maxMemoryMB": 256,
482
+ "maxCpuPercent": 25,
483
+ "maxStorageMB": 100
484
+ },
485
+ "dependencies": {},
486
+ "lifecycle": {
487
+ "autoStart": true,
488
+ "restartOnCrash": true,
489
+ "maxRestarts": 3
490
+ }
491
+ }
492
+ ```
493
+
494
+ ## Security
495
+
496
+ - Credentials are stored with restricted permissions (0600)
497
+ - All binaries are signed with quantum-resistant MLDSA signatures
498
+ - Checksums verify binary integrity
499
+ - IPFS CIDs provide content-addressed storage
500
+
501
+ ## License
502
+
503
+ Apache-2.0
504
+
505
+ ## Links
506
+
507
+ - [OPNet Documentation](https://docs.opnet.org)
508
+ - [Plugin SDK](https://github.com/btc-vision/plugin-sdk)
509
+ - [OPNet Node](https://github.com/btc-vision/opnet-node)
package/SECURITY.md ADDED
@@ -0,0 +1,35 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Use this section to tell people about which versions of your project are
6
+ currently being supported with security updates.
7
+
8
+ | Version | Supported |
9
+ |---------|--------------------|
10
+ | 1.0.x | :white_check_mark: |
11
+
12
+ ## Reporting a Vulnerability
13
+
14
+ To report a security vulnerability, please email [anakun@opnet.org](mailto:anakun@opnet.org).
15
+
16
+ Please include the following information in your report:
17
+
18
+ - Description of the vulnerability
19
+ - Steps to reproduce the vulnerability
20
+ - Suggested mitigation or remediation steps
21
+ - Your name and contact information
22
+ - Your company or organization name (if applicable)
23
+ - Your preferred method of contact
24
+ - Any other relevant information
25
+ - Attach any supporting documents, screenshots, or other files that may help us understand the issue
26
+
27
+ ## Security Best Practices
28
+
29
+ When using the OPNet CLI:
30
+
31
+ 1. **Protect your mnemonic**: Never share your BIP-39 mnemonic phrase. Store it securely offline.
32
+ 2. **Use secure networks**: Avoid using public Wi-Fi when performing sensitive operations.
33
+ 3. **Verify downloads**: Always verify plugin signatures before installing.
34
+ 4. **Keep credentials secure**: The CLI stores credentials in `~/.opnet/credentials.json` with restricted permissions (0600).
35
+ 5. **Use testnet first**: Test your plugins on testnet before deploying to mainnet.
@@ -0,0 +1,7 @@
1
+ import { BaseCommand } from './BaseCommand.js';
2
+ export declare class AcceptCommand extends BaseCommand {
3
+ constructor();
4
+ protected configure(): void;
5
+ private execute;
6
+ }
7
+ export declare const acceptCommand: import("commander").Command;
@@ -0,0 +1,110 @@
1
+ import { confirm } from '@inquirer/prompts';
2
+ import { BaseCommand } from './BaseCommand.js';
3
+ import { getPendingTransfer, getPendingScopeTransfer } from '../lib/registry.js';
4
+ import { loadCredentials, canSign } from '../lib/credentials.js';
5
+ import { CLIWallet } from '../lib/wallet.js';
6
+ export class AcceptCommand extends BaseCommand {
7
+ constructor() {
8
+ super('accept', 'Accept pending ownership transfer');
9
+ }
10
+ configure() {
11
+ this.command
12
+ .argument('<name>', 'Package name or @scope')
13
+ .option('-n, --network <network>', 'Network', 'mainnet')
14
+ .option('-y, --yes', 'Skip confirmation')
15
+ .action((name, options) => this.execute(name, options || { network: 'mainnet' }));
16
+ }
17
+ async execute(name, options) {
18
+ try {
19
+ this.logger.info('Loading wallet...');
20
+ const credentials = loadCredentials();
21
+ if (!credentials || !canSign(credentials)) {
22
+ this.logger.fail('No credentials configured');
23
+ this.logger.warn('Run `opnet login` to configure your wallet.');
24
+ process.exit(1);
25
+ }
26
+ CLIWallet.fromCredentials(credentials);
27
+ this.logger.success('Wallet loaded');
28
+ const network = (options?.network || 'mainnet');
29
+ const isScope = name.startsWith('@') && !name.includes('/');
30
+ this.logger.info('Checking pending transfer...');
31
+ if (isScope) {
32
+ const scopeName = name.substring(1);
33
+ const pending = await getPendingScopeTransfer(scopeName, network);
34
+ if (!pending) {
35
+ this.logger.warn('No pending transfer');
36
+ this.logger.log(`No pending transfer for ${name}.`);
37
+ return;
38
+ }
39
+ this.logger.success('Found pending transfer');
40
+ this.logger.log('');
41
+ this.logger.info('Accept Transfer');
42
+ this.logger.log('─'.repeat(50));
43
+ this.logger.log(`Type: Scope`);
44
+ this.logger.log(`Name: ${name}`);
45
+ this.logger.log(`Network: ${options?.network}`);
46
+ this.logger.log('');
47
+ if (!options?.yes) {
48
+ const confirmed = await confirm({
49
+ message: `Accept ownership of ${name}?`,
50
+ default: true,
51
+ });
52
+ if (!confirmed) {
53
+ this.logger.warn('Transfer acceptance cancelled.');
54
+ return;
55
+ }
56
+ }
57
+ this.logger.info('Accepting transfer...');
58
+ this.logger.warn('Acceptance transaction required.');
59
+ this.logger.log('Transaction would call: acceptScopeTransfer(');
60
+ this.logger.log(` scopeName: "${scopeName}"`);
61
+ this.logger.log(')');
62
+ }
63
+ else {
64
+ const pending = await getPendingTransfer(name, network);
65
+ if (!pending) {
66
+ this.logger.warn('No pending transfer');
67
+ this.logger.log(`No pending transfer for ${name}.`);
68
+ return;
69
+ }
70
+ this.logger.success('Found pending transfer');
71
+ this.logger.log('');
72
+ this.logger.info('Accept Transfer');
73
+ this.logger.log('─'.repeat(50));
74
+ this.logger.log(`Type: Package`);
75
+ this.logger.log(`Name: ${name}`);
76
+ this.logger.log(`Network: ${options?.network}`);
77
+ this.logger.log('');
78
+ if (!options?.yes) {
79
+ const confirmed = await confirm({
80
+ message: `Accept ownership of ${name}?`,
81
+ default: true,
82
+ });
83
+ if (!confirmed) {
84
+ this.logger.warn('Transfer acceptance cancelled.');
85
+ return;
86
+ }
87
+ }
88
+ this.logger.info('Accepting transfer...');
89
+ this.logger.warn('Acceptance transaction required.');
90
+ this.logger.log('Transaction would call: acceptTransfer(');
91
+ this.logger.log(` packageName: "${name}"`);
92
+ this.logger.log(')');
93
+ }
94
+ this.logger.info('Acceptance (transaction pending)');
95
+ this.logger.log('');
96
+ this.logger.success('Transfer acceptance submitted!');
97
+ this.logger.warn('Note: Registry transaction support is coming soon.');
98
+ this.logger.log('');
99
+ }
100
+ catch (error) {
101
+ this.logger.fail('Acceptance failed');
102
+ if (this.isUserCancelled(error)) {
103
+ this.logger.warn('Acceptance cancelled.');
104
+ process.exit(0);
105
+ }
106
+ this.exitWithError(this.formatError(error));
107
+ }
108
+ }
109
+ }
110
+ export const acceptCommand = new AcceptCommand().getCommand();
@@ -0,0 +1,12 @@
1
+ import { Command } from 'commander';
2
+ import { Logger } from '@btc-vision/logger';
3
+ export declare abstract class BaseCommand {
4
+ protected readonly logger: Logger;
5
+ protected readonly command: Command;
6
+ constructor(name: string, description: string);
7
+ getCommand(): Command;
8
+ protected abstract configure(): void;
9
+ protected formatError(error: unknown): string;
10
+ protected exitWithError(message: string, code?: number): never;
11
+ protected isUserCancelled(error: unknown): boolean;
12
+ }
@@ -0,0 +1,27 @@
1
+ import { Command } from 'commander';
2
+ import { Logger } from '@btc-vision/logger';
3
+ export class BaseCommand {
4
+ logger;
5
+ command;
6
+ constructor(name, description) {
7
+ this.logger = new Logger();
8
+ this.command = new Command(name).description(description);
9
+ this.configure();
10
+ }
11
+ getCommand() {
12
+ return this.command;
13
+ }
14
+ formatError(error) {
15
+ if (error instanceof Error) {
16
+ return error.message;
17
+ }
18
+ return String(error);
19
+ }
20
+ exitWithError(message, code = 1) {
21
+ this.logger.error(message);
22
+ process.exit(code);
23
+ }
24
+ isUserCancelled(error) {
25
+ return error instanceof Error && error.message.includes('User force closed');
26
+ }
27
+ }
@@ -0,0 +1,7 @@
1
+ import { BaseCommand } from './BaseCommand.js';
2
+ export declare class CompileCommand extends BaseCommand {
3
+ constructor();
4
+ protected configure(): void;
5
+ private execute;
6
+ }
7
+ export declare const compileCommand: import("commander").Command;