@btc-vision/cli 1.0.1 → 1.0.3

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/README.md +55 -23
  2. package/build/commands/AcceptCommand.js +62 -15
  3. package/build/commands/CompileCommand.js +9 -10
  4. package/build/commands/ConfigCommand.js +2 -27
  5. package/build/commands/DeprecateCommand.js +32 -11
  6. package/build/commands/InitCommand.js +1 -7
  7. package/build/commands/PublishCommand.js +82 -27
  8. package/build/commands/ScopeRegisterCommand.d.ts +7 -0
  9. package/build/commands/ScopeRegisterCommand.js +115 -0
  10. package/build/commands/SignCommand.js +6 -9
  11. package/build/commands/TransferCommand.js +118 -30
  12. package/build/commands/UndeprecateCommand.js +31 -10
  13. package/build/index.js +2 -0
  14. package/build/lib/binary.d.ts +5 -2
  15. package/build/lib/binary.js +11 -6
  16. package/build/lib/config.d.ts +1 -0
  17. package/build/lib/config.js +3 -2
  18. package/build/lib/ipfs.js +85 -76
  19. package/build/lib/manifest.js +1 -1
  20. package/build/lib/registry.d.ts +1 -1
  21. package/build/lib/registry.js +3 -3
  22. package/build/lib/transaction.d.ts +27 -0
  23. package/build/lib/transaction.js +91 -0
  24. package/build/lib/wallet.d.ts +7 -7
  25. package/build/lib/wallet.js +3 -6
  26. package/build/types/index.d.ts +1 -0
  27. package/package.json +2 -1
  28. package/src/commands/AcceptCommand.ts +89 -16
  29. package/src/commands/CompileCommand.ts +13 -14
  30. package/src/commands/ConfigCommand.ts +2 -29
  31. package/src/commands/DeprecateCommand.ts +48 -11
  32. package/src/commands/InitCommand.ts +1 -7
  33. package/src/commands/PublishCommand.ts +138 -28
  34. package/src/commands/ScopeRegisterCommand.ts +164 -0
  35. package/src/commands/SignCommand.ts +9 -21
  36. package/src/commands/TransferCommand.ts +159 -31
  37. package/src/commands/UndeprecateCommand.ts +43 -10
  38. package/src/index.ts +2 -0
  39. package/src/lib/binary.ts +24 -22
  40. package/src/lib/config.ts +3 -2
  41. package/src/lib/ipfs.ts +113 -99
  42. package/src/lib/manifest.ts +1 -1
  43. package/src/lib/registry.ts +5 -2
  44. package/src/lib/transaction.ts +205 -0
  45. package/src/lib/wallet.ts +10 -19
  46. package/src/types/index.ts +3 -1
@@ -0,0 +1,115 @@
1
+ import { confirm } from '@inquirer/prompts';
2
+ import { BaseCommand } from './BaseCommand.js';
3
+ import { getRegistryContract, getScope, getScopePrice } from '../lib/registry.js';
4
+ import { canSign, loadCredentials } from '../lib/credentials.js';
5
+ import { CLIWallet } from '../lib/wallet.js';
6
+ import { buildTransactionParams, checkBalance, formatSats, getWalletAddress, } from '../lib/transaction.js';
7
+ export class ScopeRegisterCommand extends BaseCommand {
8
+ constructor() {
9
+ super('scope:register', 'Register a new scope in the registry');
10
+ }
11
+ configure() {
12
+ this.command
13
+ .argument('<name>', 'Scope name (without @)')
14
+ .option('-n, --network <network>', 'Network', 'mainnet')
15
+ .option('-y, --yes', 'Skip confirmation')
16
+ .action((name, options) => this.execute(name, options || { network: 'mainnet' }));
17
+ }
18
+ async execute(name, options) {
19
+ try {
20
+ const scopeName = name.startsWith('@') ? name.substring(1) : name;
21
+ if (!/^[a-z][a-z0-9-]*[a-z0-9]$/.test(scopeName) && !/^[a-z]$/.test(scopeName)) {
22
+ this.logger.fail('Invalid scope name');
23
+ this.logger.error('Scope name must:');
24
+ this.logger.error(' - Start with a lowercase letter');
25
+ this.logger.error(' - Contain only lowercase letters, numbers, and hyphens');
26
+ this.logger.error(' - End with a letter or number');
27
+ process.exit(1);
28
+ }
29
+ this.logger.info('Loading wallet...');
30
+ const credentials = loadCredentials();
31
+ if (!credentials || !canSign(credentials)) {
32
+ this.logger.fail('No credentials configured');
33
+ this.logger.warn('Run `opnet login` to configure your wallet.');
34
+ process.exit(1);
35
+ }
36
+ const wallet = CLIWallet.fromCredentials(credentials);
37
+ this.logger.success('Wallet loaded');
38
+ const network = (options?.network || 'mainnet');
39
+ this.logger.info(`Checking if @${scopeName} is available...`);
40
+ const existingScope = await getScope(scopeName, network);
41
+ if (existingScope) {
42
+ this.logger.fail('Scope already registered');
43
+ this.logger.error(`Scope @${scopeName} is already registered.`);
44
+ this.logger.log(`Owner: ${existingScope.owner}`);
45
+ process.exit(1);
46
+ }
47
+ this.logger.success(`Scope @${scopeName} is available`);
48
+ this.logger.info('Fetching registration price...');
49
+ const scopePrice = await getScopePrice(network);
50
+ this.logger.success(`Registration price: ${formatSats(scopePrice)}`);
51
+ this.logger.info('Checking wallet balance...');
52
+ const minRequired = scopePrice + 50000n;
53
+ const { sufficient, balance } = await checkBalance(wallet, network, minRequired);
54
+ if (!sufficient) {
55
+ this.logger.fail('Insufficient balance');
56
+ this.logger.error(`Wallet balance: ${formatSats(balance)}`);
57
+ this.logger.error(`Required (approx): ${formatSats(minRequired)}`);
58
+ this.logger.error('Please fund your wallet before registering a scope.');
59
+ process.exit(1);
60
+ }
61
+ this.logger.success(`Wallet balance: ${formatSats(balance)}`);
62
+ this.logger.log('');
63
+ this.logger.info('Scope Registration Summary');
64
+ this.logger.log('─'.repeat(50));
65
+ this.logger.log(`Scope: @${scopeName}`);
66
+ this.logger.log(`Price: ${formatSats(scopePrice)}`);
67
+ this.logger.log(`Network: ${options?.network}`);
68
+ this.logger.log(`Address: ${wallet.p2trAddress}`);
69
+ this.logger.log('');
70
+ if (!options?.yes) {
71
+ const confirmed = await confirm({
72
+ message: `Register scope @${scopeName}?`,
73
+ default: true,
74
+ });
75
+ if (!confirmed) {
76
+ this.logger.warn('Registration cancelled.');
77
+ return;
78
+ }
79
+ }
80
+ this.logger.info('Registering scope...');
81
+ const sender = getWalletAddress(wallet);
82
+ const contract = getRegistryContract(network, sender);
83
+ const txParams = buildTransactionParams(wallet, network);
84
+ const registerResult = await contract.registerScope(scopeName);
85
+ if (registerResult.revert) {
86
+ this.logger.fail('Registration would fail');
87
+ this.logger.error(`Reason: ${registerResult.revert}`);
88
+ process.exit(1);
89
+ }
90
+ if (registerResult.estimatedGas) {
91
+ this.logger.info(`Estimated gas: ${registerResult.estimatedGas} sats`);
92
+ }
93
+ const receipt = await registerResult.sendTransaction(txParams);
94
+ this.logger.log('');
95
+ this.logger.success('Scope registered successfully!');
96
+ this.logger.log('');
97
+ this.logger.log(`Scope: @${scopeName}`);
98
+ this.logger.log(`Owner: ${wallet.p2trAddress}`);
99
+ this.logger.log(`Transaction ID: ${receipt.transactionId}`);
100
+ this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
101
+ this.logger.log('');
102
+ this.logger.info('You can now publish packages under this scope using: opnet publish');
103
+ this.logger.log('');
104
+ }
105
+ catch (error) {
106
+ this.logger.fail('Scope registration failed');
107
+ if (this.isUserCancelled(error)) {
108
+ this.logger.warn('Registration cancelled.');
109
+ process.exit(0);
110
+ }
111
+ this.exitWithError(this.formatError(error));
112
+ }
113
+ }
114
+ }
115
+ export const scopeRegisterCommand = new ScopeRegisterCommand().getCommand();
@@ -1,7 +1,7 @@
1
1
  import * as fs from 'fs';
2
2
  import * as crypto from 'crypto';
3
3
  import { BaseCommand } from './BaseCommand.js';
4
- import { buildOpnetBinary, computeChecksum, formatFileSize, parseOpnetBinary, } from '../lib/binary.js';
4
+ import { buildOpnetBinary, formatFileSize, parseOpnetBinary } from '../lib/binary.js';
5
5
  import { CLIWallet } from '../lib/wallet.js';
6
6
  import { canSign, loadCredentials } from '../lib/credentials.js';
7
7
  export class SignCommand extends BaseCommand {
@@ -48,20 +48,17 @@ export class SignCommand extends BaseCommand {
48
48
  this.logger.log('Use --force to re-sign with your key.');
49
49
  process.exit(1);
50
50
  }
51
- this.logger.info('Signing...');
52
- const metadataBytes = Buffer.from(parsed.rawMetadata, 'utf-8');
53
- const checksum = computeChecksum(metadataBytes, parsed.bytecode, parsed.proto ?? Buffer.alloc(0));
54
- const signature = wallet.signMLDSA(checksum);
55
- this.logger.success(`Signed (${formatFileSize(signature.length)} signature)`);
56
- this.logger.info('Rebuilding binary...');
57
- const newBinary = buildOpnetBinary({
51
+ this.logger.info('Signing and rebuilding binary...');
52
+ const signFn = (checksum) => wallet.signMLDSA(checksum);
53
+ const { binary: newBinary, checksum } = buildOpnetBinary({
58
54
  mldsaLevel: wallet.securityLevel,
59
55
  publicKey: wallet.mldsaPublicKey,
60
- signature,
61
56
  metadata: parsed.metadata,
62
57
  bytecode: parsed.bytecode,
63
58
  proto: parsed.proto ?? Buffer.alloc(0),
59
+ signFn,
64
60
  });
61
+ this.logger.success(`Signed (checksum: sha256:${checksum.toString('hex').substring(0, 16)}...)`);
65
62
  this.logger.success(`Binary rebuilt (${formatFileSize(newBinary.length)})`);
66
63
  const outputPath = options.output || file;
67
64
  fs.writeFileSync(outputPath, newBinary);
@@ -1,8 +1,10 @@
1
1
  import { confirm, input } from '@inquirer/prompts';
2
+ import { Address } from '@btc-vision/transaction';
2
3
  import { BaseCommand } from './BaseCommand.js';
3
- import { getPackage, getPendingScopeTransfer, getPendingTransfer, getScope, } from '../lib/registry.js';
4
+ import { getPackage, getPendingScopeTransfer, getPendingTransfer, getRegistryContract, getScope, } from '../lib/registry.js';
4
5
  import { canSign, loadCredentials } from '../lib/credentials.js';
5
6
  import { CLIWallet } from '../lib/wallet.js';
7
+ import { buildTransactionParams, checkBalance, formatSats, getWalletAddress, } from '../lib/transaction.js';
6
8
  export class TransferCommand extends BaseCommand {
7
9
  constructor() {
8
10
  super('transfer', 'Initiate ownership transfer of a package or scope');
@@ -25,7 +27,7 @@ export class TransferCommand extends BaseCommand {
25
27
  this.logger.warn('Run `opnet login` to configure your wallet.');
26
28
  process.exit(1);
27
29
  }
28
- CLIWallet.fromCredentials(credentials);
30
+ const wallet = CLIWallet.fromCredentials(credentials);
29
31
  this.logger.success('Wallet loaded');
30
32
  const network = (options?.network || 'mainnet');
31
33
  const isScope = name.startsWith('@') && !name.includes('/');
@@ -86,26 +88,63 @@ export class TransferCommand extends BaseCommand {
86
88
  return;
87
89
  }
88
90
  }
91
+ this.logger.info('Checking wallet balance...');
92
+ const { sufficient, balance } = await checkBalance(wallet, network);
93
+ if (!sufficient) {
94
+ this.logger.fail('Insufficient balance');
95
+ this.logger.error(`Wallet balance: ${formatSats(balance)}`);
96
+ this.logger.error('Please fund your wallet before initiating transfer.');
97
+ process.exit(1);
98
+ }
99
+ this.logger.success(`Wallet balance: ${formatSats(balance)}`);
89
100
  this.logger.info('Initiating transfer...');
101
+ const sender = getWalletAddress(wallet);
102
+ const contract = getRegistryContract(network, sender);
103
+ const txParams = buildTransactionParams(wallet, network);
104
+ const newOwnerAddress = Address.fromString(targetOwner);
90
105
  if (isScope) {
91
106
  const scopeName = name.substring(1);
92
- this.logger.warn('Transfer transaction required.');
93
- this.logger.log('Transaction would call: initiateScopeTransfer(');
94
- this.logger.log(` scopeName: "${scopeName}",`);
95
- this.logger.log(` newOwner: "${targetOwner}"`);
96
- this.logger.log(')');
107
+ const transferResult = await contract.initiateScopeTransfer(scopeName, newOwnerAddress);
108
+ if (transferResult.revert) {
109
+ this.logger.fail('Transfer initiation would fail');
110
+ this.logger.error(`Reason: ${transferResult.revert}`);
111
+ process.exit(1);
112
+ }
113
+ if (transferResult.estimatedGas) {
114
+ this.logger.info(`Estimated gas: ${transferResult.estimatedGas} sats`);
115
+ }
116
+ const receipt = await transferResult.sendTransaction(txParams);
117
+ this.logger.log('');
118
+ this.logger.success('Scope transfer initiated successfully!');
119
+ this.logger.log('');
120
+ this.logger.log(`Scope: ${name}`);
121
+ this.logger.log(`New Owner: ${targetOwner}`);
122
+ this.logger.log(`Transaction ID: ${receipt.transactionId}`);
123
+ this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
124
+ this.logger.log('');
125
+ this.logger.warn('Note: The new owner must call `opnet accept` to complete the transfer.');
97
126
  }
98
127
  else {
99
- this.logger.warn('Transfer transaction required.');
100
- this.logger.log('Transaction would call: initiateTransfer(');
101
- this.logger.log(` packageName: "${name}",`);
102
- this.logger.log(` newOwner: "${targetOwner}"`);
103
- this.logger.log(')');
128
+ const transferResult = await contract.initiateTransfer(name, newOwnerAddress);
129
+ if (transferResult.revert) {
130
+ this.logger.fail('Transfer initiation would fail');
131
+ this.logger.error(`Reason: ${transferResult.revert}`);
132
+ process.exit(1);
133
+ }
134
+ if (transferResult.estimatedGas) {
135
+ this.logger.info(`Estimated gas: ${transferResult.estimatedGas} sats`);
136
+ }
137
+ const receipt = await transferResult.sendTransaction(txParams);
138
+ this.logger.log('');
139
+ this.logger.success('Package transfer initiated successfully!');
140
+ this.logger.log('');
141
+ this.logger.log(`Package: ${name}`);
142
+ this.logger.log(`New Owner: ${targetOwner}`);
143
+ this.logger.log(`Transaction ID: ${receipt.transactionId}`);
144
+ this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
145
+ this.logger.log('');
146
+ this.logger.warn('Note: The new owner must call `opnet accept` to complete the transfer.');
104
147
  }
105
- this.logger.info('Transfer (transaction pending)');
106
- this.logger.log('');
107
- this.logger.success('Transfer initiated!');
108
- this.logger.warn('Note: Registry transaction support is coming soon.');
109
148
  this.logger.log('');
110
149
  }
111
150
  catch (error) {
@@ -119,6 +158,13 @@ export class TransferCommand extends BaseCommand {
119
158
  }
120
159
  async handleCancel(name, isScope, network, options) {
121
160
  this.logger.info('Checking pending transfer...');
161
+ const credentials = loadCredentials();
162
+ if (!credentials || !canSign(credentials)) {
163
+ this.logger.fail('No credentials configured');
164
+ this.logger.warn('Run `opnet login` to configure your wallet.');
165
+ process.exit(1);
166
+ }
167
+ const wallet = CLIWallet.fromCredentials(credentials);
122
168
  if (isScope) {
123
169
  const scopeName = name.substring(1);
124
170
  const pending = await getPendingScopeTransfer(scopeName, network);
@@ -138,12 +184,35 @@ export class TransferCommand extends BaseCommand {
138
184
  return;
139
185
  }
140
186
  }
187
+ this.logger.info('Checking wallet balance...');
188
+ const { sufficient, balance } = await checkBalance(wallet, network);
189
+ if (!sufficient) {
190
+ this.logger.fail('Insufficient balance');
191
+ this.logger.error(`Wallet balance: ${formatSats(balance)}`);
192
+ process.exit(1);
193
+ }
194
+ this.logger.success(`Wallet balance: ${formatSats(balance)}`);
141
195
  this.logger.info('Cancelling transfer...');
142
- this.logger.warn('Cancellation transaction required.');
143
- this.logger.log('Transaction would call: cancelScopeTransfer(');
144
- this.logger.log(` scopeName: "${scopeName}"`);
145
- this.logger.log(')');
146
- this.logger.info('Cancellation (transaction pending)');
196
+ const sender = getWalletAddress(wallet);
197
+ const contract = getRegistryContract(network, sender);
198
+ const txParams = buildTransactionParams(wallet, network);
199
+ const cancelResult = await contract.cancelScopeTransfer(scopeName);
200
+ if (cancelResult.revert) {
201
+ this.logger.fail('Cancellation would fail');
202
+ this.logger.error(`Reason: ${cancelResult.revert}`);
203
+ process.exit(1);
204
+ }
205
+ if (cancelResult.estimatedGas) {
206
+ this.logger.info(`Estimated gas: ${cancelResult.estimatedGas} sats`);
207
+ }
208
+ const receipt = await cancelResult.sendTransaction(txParams);
209
+ this.logger.log('');
210
+ this.logger.success('Scope transfer cancelled successfully!');
211
+ this.logger.log('');
212
+ this.logger.log(`Scope: ${name}`);
213
+ this.logger.log(`Transaction ID: ${receipt.transactionId}`);
214
+ this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
215
+ this.logger.log('');
147
216
  }
148
217
  else {
149
218
  const pending = await getPendingTransfer(name, network);
@@ -163,17 +232,36 @@ export class TransferCommand extends BaseCommand {
163
232
  return;
164
233
  }
165
234
  }
235
+ this.logger.info('Checking wallet balance...');
236
+ const { sufficient, balance } = await checkBalance(wallet, network);
237
+ if (!sufficient) {
238
+ this.logger.fail('Insufficient balance');
239
+ this.logger.error(`Wallet balance: ${formatSats(balance)}`);
240
+ process.exit(1);
241
+ }
242
+ this.logger.success(`Wallet balance: ${formatSats(balance)}`);
166
243
  this.logger.info('Cancelling transfer...');
167
- this.logger.warn('Cancellation transaction required.');
168
- this.logger.log('Transaction would call: cancelTransfer(');
169
- this.logger.log(` packageName: "${name}"`);
170
- this.logger.log(')');
171
- this.logger.info('Cancellation (transaction pending)');
244
+ const sender = getWalletAddress(wallet);
245
+ const contract = getRegistryContract(network, sender);
246
+ const txParams = buildTransactionParams(wallet, network);
247
+ const cancelResult = await contract.cancelTransfer(name);
248
+ if (cancelResult.revert) {
249
+ this.logger.fail('Cancellation would fail');
250
+ this.logger.error(`Reason: ${cancelResult.revert}`);
251
+ process.exit(1);
252
+ }
253
+ if (cancelResult.estimatedGas) {
254
+ this.logger.info(`Estimated gas: ${cancelResult.estimatedGas} sats`);
255
+ }
256
+ const receipt = await cancelResult.sendTransaction(txParams);
257
+ this.logger.log('');
258
+ this.logger.success('Package transfer cancelled successfully!');
259
+ this.logger.log('');
260
+ this.logger.log(`Package: ${name}`);
261
+ this.logger.log(`Transaction ID: ${receipt.transactionId}`);
262
+ this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
263
+ this.logger.log('');
172
264
  }
173
- this.logger.log('');
174
- this.logger.success('Transfer cancellation submitted!');
175
- this.logger.warn('Note: Registry transaction support is coming soon.');
176
- this.logger.log('');
177
265
  }
178
266
  }
179
267
  export const transferCommand = new TransferCommand().getCommand();
@@ -1,8 +1,9 @@
1
1
  import { confirm } from '@inquirer/prompts';
2
2
  import { BaseCommand } from './BaseCommand.js';
3
- import { getPackage, getVersion, isVersionImmutable } from '../lib/registry.js';
3
+ import { getPackage, getRegistryContract, getVersion, isVersionImmutable } from '../lib/registry.js';
4
4
  import { canSign, loadCredentials } from '../lib/credentials.js';
5
5
  import { CLIWallet } from '../lib/wallet.js';
6
+ import { buildTransactionParams, checkBalance, formatSats, getWalletAddress, } from '../lib/transaction.js';
6
7
  export class UndeprecateCommand extends BaseCommand {
7
8
  constructor() {
8
9
  super('undeprecate', 'Remove deprecation from a package version');
@@ -24,7 +25,7 @@ export class UndeprecateCommand extends BaseCommand {
24
25
  this.logger.warn('Run `opnet login` to configure your wallet.');
25
26
  process.exit(1);
26
27
  }
27
- CLIWallet.fromCredentials(credentials);
28
+ const wallet = CLIWallet.fromCredentials(credentials);
28
29
  this.logger.success('Wallet loaded');
29
30
  this.logger.info('Fetching package info...');
30
31
  const network = (options?.network || 'mainnet');
@@ -70,16 +71,36 @@ export class UndeprecateCommand extends BaseCommand {
70
71
  return;
71
72
  }
72
73
  }
74
+ this.logger.info('Checking wallet balance...');
75
+ const { sufficient, balance } = await checkBalance(wallet, network);
76
+ if (!sufficient) {
77
+ this.logger.fail('Insufficient balance');
78
+ this.logger.error(`Wallet balance: ${formatSats(balance)}`);
79
+ this.logger.error('Please fund your wallet before undeprecating.');
80
+ process.exit(1);
81
+ }
82
+ this.logger.success(`Wallet balance: ${formatSats(balance)}`);
73
83
  this.logger.info('Removing deprecation...');
74
- this.logger.warn('Undeprecation transaction required.');
75
- this.logger.log('Transaction would call: undeprecateVersion(');
76
- this.logger.log(` packageName: "${packageName}",`);
77
- this.logger.log(` version: "${version}"`);
78
- this.logger.log(')');
79
- this.logger.info('Undeprecation (transaction pending)');
84
+ const sender = getWalletAddress(wallet);
85
+ const contract = getRegistryContract(network, sender);
86
+ const txParams = buildTransactionParams(wallet, network);
87
+ const undeprecateResult = await contract.undeprecateVersion(packageName, version);
88
+ if (undeprecateResult.revert) {
89
+ this.logger.fail('Undeprecation would fail');
90
+ this.logger.error(`Reason: ${undeprecateResult.revert}`);
91
+ process.exit(1);
92
+ }
93
+ if (undeprecateResult.estimatedGas) {
94
+ this.logger.info(`Estimated gas: ${undeprecateResult.estimatedGas} sats`);
95
+ }
96
+ const receipt = await undeprecateResult.sendTransaction(txParams);
97
+ this.logger.log('');
98
+ this.logger.success('Deprecation removed successfully!');
80
99
  this.logger.log('');
81
- this.logger.success('Undeprecation submitted!');
82
- this.logger.warn('Note: Registry transaction support is coming soon.');
100
+ this.logger.log(`Package: ${packageName}`);
101
+ this.logger.log(`Version: ${version}`);
102
+ this.logger.log(`Transaction ID: ${receipt.transactionId}`);
103
+ this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
83
104
  this.logger.log('');
84
105
  }
85
106
  catch (error) {
package/build/index.js CHANGED
@@ -16,6 +16,7 @@ import { deprecateCommand } from './commands/DeprecateCommand.js';
16
16
  import { undeprecateCommand } from './commands/UndeprecateCommand.js';
17
17
  import { transferCommand } from './commands/TransferCommand.js';
18
18
  import { acceptCommand } from './commands/AcceptCommand.js';
19
+ import { scopeRegisterCommand } from './commands/ScopeRegisterCommand.js';
19
20
  import { installCommand } from './commands/InstallCommand.js';
20
21
  import { updateCommand } from './commands/UpdateCommand.js';
21
22
  import { listCommand } from './commands/ListCommand.js';
@@ -41,6 +42,7 @@ program.addCommand(deprecateCommand);
41
42
  program.addCommand(undeprecateCommand);
42
43
  program.addCommand(transferCommand);
43
44
  program.addCommand(acceptCommand);
45
+ program.addCommand(scopeRegisterCommand);
44
46
  program.addCommand(installCommand);
45
47
  program.addCommand(updateCommand);
46
48
  program.addCommand(listCommand);
@@ -6,11 +6,14 @@ export declare function verifyChecksum(parsed: IParsedPluginFile): boolean;
6
6
  export declare function buildOpnetBinary(options: {
7
7
  mldsaLevel: CLIMldsaLevel;
8
8
  publicKey: Buffer;
9
- signature: Buffer;
10
9
  metadata: IPluginMetadata;
11
10
  bytecode: Buffer;
12
11
  proto?: Buffer;
13
- }): Buffer;
12
+ signFn?: (checksum: Buffer) => Buffer;
13
+ }): {
14
+ binary: Buffer;
15
+ checksum: Buffer;
16
+ };
14
17
  export declare function extractMetadata(data: Buffer): IPluginMetadata | null;
15
18
  export declare function getParsedMldsaLevel(parsed: IParsedPluginFile): CLIMldsaLevel;
16
19
  export declare function formatFileSize(bytes: number): string;
@@ -91,19 +91,24 @@ export function verifyChecksum(parsed) {
91
91
  return computed.equals(parsed.checksum);
92
92
  }
93
93
  export function buildOpnetBinary(options) {
94
- const { mldsaLevel, publicKey, signature, metadata, bytecode, proto = Buffer.alloc(0), } = options;
94
+ const { mldsaLevel, publicKey, metadata, bytecode, proto = Buffer.alloc(0), signFn } = options;
95
95
  const sdkLevel = cliLevelToMLDSALevel(mldsaLevel);
96
96
  const expectedPkSize = MLDSA_PUBLIC_KEY_SIZES[sdkLevel];
97
97
  const expectedSigSize = MLDSA_SIGNATURE_SIZES[sdkLevel];
98
98
  if (publicKey.length !== expectedPkSize) {
99
99
  throw new Error(`Public key size mismatch: expected ${expectedPkSize}, got ${publicKey.length}`);
100
100
  }
101
+ const tempMetadata = { ...metadata, checksum: '' };
102
+ const tempMetadataBytes = Buffer.from(JSON.stringify(tempMetadata), 'utf-8');
103
+ const checksum = computeChecksum(tempMetadataBytes, bytecode, proto);
104
+ const checksumHex = `sha256:${checksum.toString('hex')}`;
105
+ const finalMetadata = { ...metadata, checksum: checksumHex };
106
+ const metadataBytes = Buffer.from(JSON.stringify(finalMetadata), 'utf-8');
107
+ const finalChecksum = computeChecksum(metadataBytes, bytecode, proto);
108
+ const signature = signFn ? signFn(finalChecksum) : Buffer.alloc(expectedSigSize);
101
109
  if (signature.length !== expectedSigSize) {
102
110
  throw new Error(`Signature size mismatch: expected ${expectedSigSize}, got ${signature.length}`);
103
111
  }
104
- const metadataStr = JSON.stringify(metadata);
105
- const metadataBytes = Buffer.from(metadataStr, 'utf-8');
106
- const checksum = computeChecksum(metadataBytes, bytecode, proto);
107
112
  const totalSize = 8 +
108
113
  4 +
109
114
  1 +
@@ -140,8 +145,8 @@ export function buildOpnetBinary(options) {
140
145
  offset += 4;
141
146
  proto.copy(buffer, offset);
142
147
  offset += proto.length;
143
- checksum.copy(buffer, offset);
144
- return buffer;
148
+ finalChecksum.copy(buffer, offset);
149
+ return { binary: buffer, checksum: finalChecksum };
145
150
  }
146
151
  export function extractMetadata(data) {
147
152
  try {
@@ -1,4 +1,5 @@
1
1
  import { CLIConfig, CLIMldsaLevel, NetworkName } from '../types/index.js';
2
+ export declare const DEFAULT_CONFIG: CLIConfig;
2
3
  export declare function ensureConfigDir(): void;
3
4
  export declare function loadConfig(): CLIConfig;
4
5
  export declare function saveConfig(config: CLIConfig): void;
@@ -3,7 +3,7 @@ import * as path from 'path';
3
3
  import * as os from 'os';
4
4
  const CONFIG_DIR = path.join(os.homedir(), '.opnet');
5
5
  const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
6
- const DEFAULT_CONFIG = {
6
+ export const DEFAULT_CONFIG = {
7
7
  defaultNetwork: 'regtest',
8
8
  rpcUrls: {
9
9
  mainnet: 'https://api.opnet.org',
@@ -19,11 +19,12 @@ const DEFAULT_CONFIG = {
19
19
  ],
20
20
  ipfsPinningEndpoint: 'https://ipfs.opnet.org/api/v0/add',
21
21
  ipfsPinningApiKey: '',
22
+ ipfsPinningSecret: '',
22
23
  ipfsPinningAuthHeader: 'Authorization',
23
24
  registryAddresses: {
24
25
  mainnet: '',
25
26
  testnet: '',
26
- regtest: '',
27
+ regtest: '0x0737d17d0eff9915208f3c20ed7659587889bc94d25972672b3a6c03ff4ddbcc',
27
28
  },
28
29
  defaultMldsaLevel: 44,
29
30
  indexerUrl: 'https://indexer.opnet.org',