@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
package/build/index.js CHANGED
@@ -50,10 +50,9 @@ program.addCommand(searchCommand);
50
50
  program.showHelpAfterError();
51
51
  program.showSuggestionAfterError();
52
52
  program.exitOverride((err) => {
53
- if (err.code === 'commander.help') {
54
- process.exit(0);
55
- }
56
- if (err.code === 'commander.version') {
53
+ if (err.code === 'commander.help' ||
54
+ err.code === 'commander.helpDisplayed' ||
55
+ err.code === 'commander.version') {
57
56
  process.exit(0);
58
57
  }
59
58
  logger.error(`Error: ${err.message}`);
@@ -11,12 +11,7 @@ export const DEFAULT_CONFIG = {
11
11
  regtest: 'https://regtest.opnet.org',
12
12
  },
13
13
  ipfsGateway: 'https://ipfs.opnet.org/ipfs/',
14
- ipfsGateways: [
15
- 'https://ipfs.opnet.org/ipfs/',
16
- 'https://ipfs.io/ipfs/',
17
- 'https://cloudflare-ipfs.com/ipfs/',
18
- 'https://dweb.link/ipfs/',
19
- ],
14
+ ipfsGateways: ['https://ipfs.opnet.org/ipfs/'],
20
15
  ipfsPinningEndpoint: 'https://ipfs.opnet.org/api/v0/add',
21
16
  ipfsPinningApiKey: '',
22
17
  ipfsPinningSecret: '',
@@ -12,5 +12,3 @@ export declare function buildGatewayUrl(gateway: string, cid: string): string;
12
12
  export declare function isValidCid(cid: string): boolean;
13
13
  export declare function downloadPlugin(cid: string, outputPath: string): Promise<number>;
14
14
  export declare function uploadPlugin(filePath: string): Promise<PinResult>;
15
- export declare function checkAvailability(cid: string): Promise<boolean>;
16
- export declare function getGatewayStatus(): Promise<Record<string, boolean>>;
package/build/lib/ipfs.js CHANGED
@@ -2,7 +2,13 @@ import * as https from 'https';
2
2
  import * as http from 'http';
3
3
  import * as fs from 'fs';
4
4
  import { loadConfig } from './config.js';
5
- async function httpRequest(url, options) {
5
+ const DEFAULT_MAX_REDIRECTS = 10;
6
+ async function httpRequest(url, options, redirectCount = 0) {
7
+ const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
8
+ const followRedirect = options.followRedirect ?? false;
9
+ if (redirectCount > maxRedirects) {
10
+ throw new Error(`Maximum redirects (${maxRedirects}) exceeded`);
11
+ }
6
12
  return new Promise((resolve, reject) => {
7
13
  const parsedUrl = new URL(url);
8
14
  const isHttps = parsedUrl.protocol === 'https:';
@@ -16,17 +22,28 @@ async function httpRequest(url, options) {
16
22
  timeout: options.timeout || 30000,
17
23
  };
18
24
  const req = lib.request(reqOptions, (res) => {
25
+ const statusCode = res.statusCode ?? 0;
26
+ if (followRedirect && statusCode >= 300 && statusCode < 400 && res.headers.location) {
27
+ const redirectUrl = new URL(res.headers.location, url).href;
28
+ res.resume();
29
+ httpRequest(redirectUrl, options, redirectCount + 1)
30
+ .then(resolve)
31
+ .catch(reject);
32
+ return;
33
+ }
19
34
  const chunks = [];
20
35
  res.on('data', (chunk) => {
21
36
  chunks.push(chunk);
22
37
  });
23
38
  res.on('end', () => {
24
39
  const body = Buffer.concat(chunks);
25
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
40
+ if (statusCode >= 200 && statusCode < 300) {
26
41
  resolve(body);
27
42
  }
28
43
  else {
29
- reject(new Error(`HTTP ${res.statusCode}: ${res.statusMessage} - ${body.toString()}`));
44
+ const bodyStr = body.toString().slice(0, 200);
45
+ const truncated = body.length > 200 ? '...' : '';
46
+ reject(new Error(`HTTP ${statusCode}: ${res.statusMessage}${bodyStr ? ` - ${bodyStr}${truncated}` : ''}`));
30
47
  }
31
48
  });
32
49
  });
@@ -104,6 +121,7 @@ export async function pinToIPFS(data, name) {
104
121
  headers,
105
122
  body,
106
123
  timeout: 120000,
124
+ followRedirect: true,
107
125
  });
108
126
  const result = JSON.parse(response.toString());
109
127
  let cid;
@@ -140,8 +158,13 @@ export async function fetchFromIPFS(cid) {
140
158
  try {
141
159
  const url = buildGatewayUrl(gateway, cid);
142
160
  const data = await httpRequest(url, {
161
+ headers: {
162
+ Accept: 'application/octet-stream',
163
+ 'User-Agent': 'OPNet-CLI/1.0',
164
+ },
143
165
  method: 'GET',
144
166
  timeout: 60000,
167
+ followRedirect: true,
145
168
  });
146
169
  return {
147
170
  data,
@@ -159,6 +182,9 @@ export function buildGatewayUrl(gateway, cid) {
159
182
  if (base.includes('{cid}')) {
160
183
  return base.replace('{cid}', cid);
161
184
  }
185
+ else if (base.endsWith('/ipfs')) {
186
+ return `${base}/${cid}`;
187
+ }
162
188
  else if (base.includes('/ipfs/')) {
163
189
  return `${base}${cid}`;
164
190
  }
@@ -188,32 +214,3 @@ export async function uploadPlugin(filePath) {
188
214
  const fileName = filePath.split('/').pop() || 'plugin.opnet';
189
215
  return pinToIPFS(data, fileName);
190
216
  }
191
- export async function checkAvailability(cid) {
192
- try {
193
- await fetchFromIPFS(cid);
194
- return true;
195
- }
196
- catch {
197
- return false;
198
- }
199
- }
200
- export async function getGatewayStatus() {
201
- const config = loadConfig();
202
- const gateways = config.ipfsGateways.length > 0 ? config.ipfsGateways : [config.ipfsGateway];
203
- const testCid = 'QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn';
204
- const status = {};
205
- await Promise.all(gateways.map(async (gateway) => {
206
- try {
207
- const url = buildGatewayUrl(gateway, testCid);
208
- await httpRequest(url, {
209
- method: 'HEAD',
210
- timeout: 10000,
211
- });
212
- status[gateway] = true;
213
- }
214
- catch {
215
- status[gateway] = false;
216
- }
217
- }));
218
- return status;
219
- }
@@ -82,7 +82,7 @@ export class CLIWallet {
82
82
  const securityLevel = getMLDSASecurityLevel(level);
83
83
  const dummyChainCode = new Uint8Array(32);
84
84
  const keypair = QuantumBIP32Factory.fromPublicKey(publicKey, dummyChainCode, networks.bitcoin, securityLevel);
85
- return keypair.verify(data, signature);
85
+ return MessageSigner.verifyMLDSASignature(keypair, data, signature);
86
86
  }
87
87
  signMLDSA(data) {
88
88
  const result = MessageSigner.signMLDSAMessage(this.wallet.mldsaKeypair, data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btc-vision/cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "type": "module",
5
5
  "description": "CLI for the OPNet plugin ecosystem - scaffolding, compilation, signing, and registry interaction",
6
6
  "author": "OP_NET",
@@ -34,6 +34,9 @@
34
34
  "access": "public",
35
35
  "tag": "latest"
36
36
  },
37
+ "files": [
38
+ "build"
39
+ ],
37
40
  "scripts": {
38
41
  "build": "gulp build",
39
42
  "postbuild": "node -e \"if(process.platform!=='win32'){require('fs').chmodSync('build/index.js',0o755)}\"",
package/.gitattributes DELETED
@@ -1,2 +0,0 @@
1
- # Auto detect text files and perform LF normalization
2
- * text=auto
@@ -1,9 +0,0 @@
1
- version: 2
2
- updates:
3
- - package-ecosystem: "npm"
4
- directory: "/"
5
- schedule:
6
- interval: "weekly"
7
- open-pull-requests-limit: 5
8
- commit-message:
9
- prefix: "chore(deps)"
@@ -1,48 +0,0 @@
1
- name: CI for @btc-vision/cli
2
-
3
- on:
4
- push:
5
- tags:
6
- - '*'
7
-
8
- jobs:
9
- build_and_publish:
10
- runs-on: ubuntu-latest
11
-
12
- permissions:
13
- contents: write
14
- id-token: write
15
-
16
- steps:
17
- - name: Checkout code
18
- uses: actions/checkout@v4
19
-
20
- - name: Setup Node.js
21
- uses: actions/setup-node@v4
22
- with:
23
- node-version: '24.x'
24
- registry-url: 'https://registry.npmjs.org'
25
-
26
- - name: Update npm
27
- run: npm install -g npm@latest
28
-
29
- - name: Install dependencies
30
- run: npm install
31
-
32
- - name: Build the project
33
- run: npm run build
34
-
35
- - name: Publish to npm
36
- run: npm publish --access public
37
- env:
38
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
39
-
40
- - name: Create GitHub Release
41
- uses: actions/create-release@v1
42
- with:
43
- tag_name: ${{ github.ref_name }}
44
- release_name: Release ${{ github.ref_name }}
45
- body: |
46
- Automated release for @btc-vision/cli.
47
- env:
48
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
package/.prettierrc.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "printWidth": 100,
3
- "trailingComma": "all",
4
- "tabWidth": 4,
5
- "semi": true,
6
- "singleQuote": true,
7
- "quoteProps": "as-needed",
8
- "bracketSpacing": true,
9
- "bracketSameLine": true,
10
- "arrowParens": "always",
11
- "singleAttributePerLine": true
12
- }
package/CONTRIBUTING.md DELETED
@@ -1,56 +0,0 @@
1
- # Contributing to OPNet CLI
2
-
3
- We welcome contributions to the OPNet CLI! This document provides guidelines for contributing.
4
-
5
- ## Getting Started
6
-
7
- 1. Fork the repository
8
- 2. Clone your fork: `git clone https://github.com/YOUR_USERNAME/opnet-cli.git`
9
- 3. Install dependencies: `npm install`
10
- 4. Build: `npm run build`
11
- 5. Create a branch for your changes: `git checkout -b feature/your-feature`
12
-
13
- ## Development
14
-
15
- ### Code Style
16
-
17
- - We use ESLint and Prettier for code formatting
18
- - Run `npm run lint` to check for issues
19
- - Run `npm run format` to auto-format code
20
- - Follow TypeScript strict mode conventions
21
-
22
- ### Testing
23
-
24
- - Write tests for new features
25
- - Ensure all tests pass before submitting a PR
26
- - Run `npm test` to execute tests
27
-
28
- ### Commit Messages
29
-
30
- - Use clear, descriptive commit messages
31
- - Follow conventional commit format: `type(scope): description`
32
- - Types: feat, fix, docs, style, refactor, test, chore
33
-
34
- ## Submitting Changes
35
-
36
- 1. Ensure your code follows the style guidelines
37
- 2. Ensure all tests pass
38
- 3. Update documentation if needed
39
- 4. Submit a pull request with a clear description
40
-
41
- ## Reporting Issues
42
-
43
- - Use the GitHub issue tracker
44
- - Include steps to reproduce the issue
45
- - Include error messages and relevant logs
46
- - Specify your Node.js version and OS
47
-
48
- ## Code of Conduct
49
-
50
- - Be respectful and inclusive
51
- - Focus on constructive feedback
52
- - Help maintain a welcoming community
53
-
54
- ## License
55
-
56
- By contributing, you agree that your contributions will be licensed under the Apache 2.0 License.
package/NOTICE DELETED
@@ -1,17 +0,0 @@
1
- OPNet CLI
2
- Copyright 2025 Orange Pill Labs Holding Ltd.
3
-
4
- This product includes software developed at
5
- Orange Pill Labs Holding Ltd. (https://opnet.org/).
6
-
7
- Third-party dependencies:
8
- - commander: MIT License
9
- - inquirer: MIT License
10
- - chalk: MIT License
11
- - ora: MIT License
12
- - esbuild: MIT License
13
- - bytenode: MIT License
14
- - @btc-vision/transaction: Apache-2.0
15
- - @btc-vision/bitcoin: Apache-2.0
16
- - @btc-vision/bip32: Apache-2.0
17
- - opnet: Apache-2.0
package/SECURITY.md DELETED
@@ -1,35 +0,0 @@
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.
package/eslint.config.js DELETED
@@ -1,41 +0,0 @@
1
- // @ts-check
2
-
3
- import eslint from '@eslint/js';
4
- import tseslint from 'typescript-eslint';
5
-
6
- export default tseslint.config(
7
- eslint.configs.recommended,
8
- ...tseslint.configs.strictTypeChecked,
9
- {
10
- languageOptions: {
11
- parserOptions: {
12
- projectService: true,
13
- tsconfigDirName: import.meta.dirname,
14
- },
15
- },
16
- rules: {
17
- 'no-undef': 'off',
18
- '@typescript-eslint/no-unused-vars': 'off',
19
- 'no-empty': 'off',
20
- '@typescript-eslint/restrict-template-expressions': 'off',
21
- '@typescript-eslint/only-throw-error': 'off',
22
- '@typescript-eslint/no-unnecessary-condition': 'off',
23
- '@typescript-eslint/unbound-method': 'warn',
24
- '@typescript-eslint/no-confusing-void-expression': 'off',
25
- '@typescript-eslint/no-extraneous-class': 'off',
26
- 'no-async-promise-executor': 'off',
27
- '@typescript-eslint/no-misused-promises': 'off',
28
- '@typescript-eslint/no-unnecessary-type-parameters': 'off',
29
- '@typescript-eslint/no-duplicate-enum-values': 'off',
30
- 'prefer-spread': 'off',
31
- '@typescript-eslint/no-empty-object-type': 'off',
32
- '@typescript-eslint/no-base-to-string': 'off',
33
- '@typescript-eslint/no-dynamic-delete': 'off',
34
- '@typescript-eslint/no-redundant-type-constituents': 'off',
35
- },
36
- },
37
- {
38
- files: ['**/*.js'],
39
- ...tseslint.configs.disableTypeChecked,
40
- },
41
- );
package/gulpfile.js DELETED
@@ -1,41 +0,0 @@
1
- import gulp from 'gulp';
2
- import gulpcache from 'gulp-cached';
3
- import gulpClean from 'gulp-clean';
4
- import gulpESLintNew from 'gulp-eslint-new';
5
- import logger from 'gulp-logger-new';
6
- import ts from 'gulp-typescript';
7
-
8
- process.on('uncaughtException', function (err) {
9
- console.log('Caught exception: ', err);
10
- });
11
-
12
- const tsProject = ts.createProject('tsconfig.json');
13
-
14
- function buildESM() {
15
- return tsProject
16
- .src()
17
- .pipe(gulpcache('ts-esm'))
18
- .pipe(
19
- logger({
20
- before: 'Starting...',
21
- after: 'Project compiled!',
22
- extname: '.js',
23
- showChange: true,
24
- }),
25
- )
26
- .pipe(gulpESLintNew())
27
- .pipe(gulpESLintNew.format())
28
- .pipe(tsProject())
29
- .pipe(gulp.dest('build'));
30
- }
31
-
32
- export async function clean() {
33
- return gulp.src('./build', { read: false, allowEmpty: true }).pipe(gulpClean());
34
- }
35
-
36
- export const build = buildESM;
37
- export default build;
38
-
39
- export function watch() {
40
- gulp.watch(['src/**/*.ts'], gulp.series(buildESM));
41
- }
@@ -1,224 +0,0 @@
1
- /**
2
- * Accept command - Accept ownership transfer
3
- *
4
- * @module commands/AcceptCommand
5
- */
6
-
7
- import { confirm } from '@inquirer/prompts';
8
- import { BaseCommand } from './BaseCommand.js';
9
- import {
10
- getPendingScopeTransfer,
11
- getPendingTransfer,
12
- getRegistryContract,
13
- } from '../lib/registry.js';
14
- import { canSign, loadCredentials } from '../lib/credentials.js';
15
- import { CLIWallet } from '../lib/wallet.js';
16
- import {
17
- buildTransactionParams,
18
- checkBalance,
19
- formatSats,
20
- getWalletAddress,
21
- } from '../lib/transaction.js';
22
- import { NetworkName } from '../types/index.js';
23
-
24
- interface AcceptOptions {
25
- network: string;
26
- yes?: boolean;
27
- }
28
-
29
- export class AcceptCommand extends BaseCommand {
30
- constructor() {
31
- super('accept', 'Accept pending ownership transfer');
32
- }
33
-
34
- protected configure(): void {
35
- this.command
36
- .argument('<name>', 'Package name or @scope')
37
- .option('-n, --network <network>', 'Network', 'mainnet')
38
- .option('-y, --yes', 'Skip confirmation')
39
- .action((name: string, options?: AcceptOptions) =>
40
- this.execute(name, options || { network: 'mainnet' }),
41
- );
42
- }
43
-
44
- private async execute(name: string, options?: AcceptOptions): Promise<void> {
45
- try {
46
- // Load credentials
47
- this.logger.info('Loading wallet...');
48
- const credentials = loadCredentials();
49
- if (!credentials || !canSign(credentials)) {
50
- this.logger.fail('No credentials configured');
51
- this.logger.warn('Run `opnet login` to configure your wallet.');
52
- process.exit(1);
53
- }
54
- const wallet = CLIWallet.fromCredentials(credentials);
55
- this.logger.success('Wallet loaded');
56
-
57
- const network = (options?.network || 'mainnet') as NetworkName;
58
- const isScope = name.startsWith('@') && !name.includes('/');
59
-
60
- // Check for pending transfer
61
- this.logger.info('Checking pending transfer...');
62
-
63
- if (isScope) {
64
- const scopeName = name.substring(1);
65
- const pending = await getPendingScopeTransfer(scopeName, network);
66
-
67
- if (!pending) {
68
- this.logger.warn('No pending transfer');
69
- this.logger.log(`No pending transfer for ${name}.`);
70
- return;
71
- }
72
-
73
- this.logger.success('Found pending transfer');
74
-
75
- // Display summary
76
- this.logger.log('');
77
- this.logger.info('Accept Transfer');
78
- this.logger.log('─'.repeat(50));
79
- this.logger.log(`Type: Scope`);
80
- this.logger.log(`Name: ${name}`);
81
- this.logger.log(`Network: ${options?.network}`);
82
- this.logger.log('');
83
-
84
- // Confirmation
85
- if (!options?.yes) {
86
- const confirmed = await confirm({
87
- message: `Accept ownership of ${name}?`,
88
- default: true,
89
- });
90
-
91
- if (!confirmed) {
92
- this.logger.warn('Transfer acceptance cancelled.');
93
- return;
94
- }
95
- }
96
-
97
- // Check wallet balance
98
- this.logger.info('Checking wallet balance...');
99
- const { sufficient, balance } = await checkBalance(wallet, network);
100
- if (!sufficient) {
101
- this.logger.fail('Insufficient balance');
102
- this.logger.error(`Wallet balance: ${formatSats(balance)}`);
103
- this.logger.error('Please fund your wallet before accepting transfer.');
104
- process.exit(1);
105
- }
106
- this.logger.success(`Wallet balance: ${formatSats(balance)}`);
107
-
108
- // Execute acceptance
109
- this.logger.info('Accepting transfer...');
110
-
111
- const sender = getWalletAddress(wallet);
112
- const contract = getRegistryContract(network, sender);
113
- const txParams = buildTransactionParams(wallet, network);
114
-
115
- const acceptResult = await contract.acceptScopeTransfer(scopeName);
116
-
117
- if (acceptResult.revert) {
118
- this.logger.fail('Acceptance would fail');
119
- this.logger.error(`Reason: ${acceptResult.revert}`);
120
- process.exit(1);
121
- }
122
-
123
- if (acceptResult.estimatedGas) {
124
- this.logger.info(`Estimated gas: ${acceptResult.estimatedGas} sats`);
125
- }
126
-
127
- const receipt = await acceptResult.sendTransaction(txParams);
128
-
129
- this.logger.log('');
130
- this.logger.success('Scope transfer accepted successfully!');
131
- this.logger.log('');
132
- this.logger.log(`Scope: ${name}`);
133
- this.logger.log(`Transaction ID: ${receipt.transactionId}`);
134
- this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
135
- this.logger.log('');
136
- return;
137
- } else {
138
- const pending = await getPendingTransfer(name, network);
139
-
140
- if (!pending) {
141
- this.logger.warn('No pending transfer');
142
- this.logger.log(`No pending transfer for ${name}.`);
143
- return;
144
- }
145
-
146
- this.logger.success('Found pending transfer');
147
-
148
- // Display summary
149
- this.logger.log('');
150
- this.logger.info('Accept Transfer');
151
- this.logger.log('─'.repeat(50));
152
- this.logger.log(`Type: Package`);
153
- this.logger.log(`Name: ${name}`);
154
- this.logger.log(`Network: ${options?.network}`);
155
- this.logger.log('');
156
-
157
- // Confirmation
158
- if (!options?.yes) {
159
- const confirmed = await confirm({
160
- message: `Accept ownership of ${name}?`,
161
- default: true,
162
- });
163
-
164
- if (!confirmed) {
165
- this.logger.warn('Transfer acceptance cancelled.');
166
- return;
167
- }
168
- }
169
-
170
- // Check wallet balance
171
- this.logger.info('Checking wallet balance...');
172
- const { sufficient: sufficientPkg, balance: balancePkg } = await checkBalance(
173
- wallet,
174
- network,
175
- );
176
- if (!sufficientPkg) {
177
- this.logger.fail('Insufficient balance');
178
- this.logger.error(`Wallet balance: ${formatSats(balancePkg)}`);
179
- this.logger.error('Please fund your wallet before accepting transfer.');
180
- process.exit(1);
181
- }
182
- this.logger.success(`Wallet balance: ${formatSats(balancePkg)}`);
183
-
184
- // Execute acceptance
185
- this.logger.info('Accepting transfer...');
186
-
187
- const sender = getWalletAddress(wallet);
188
- const contract = getRegistryContract(network, sender);
189
- const txParams = buildTransactionParams(wallet, network);
190
-
191
- const acceptResult = await contract.acceptTransfer(name);
192
-
193
- if (acceptResult.revert) {
194
- this.logger.fail('Acceptance would fail');
195
- this.logger.error(`Reason: ${acceptResult.revert}`);
196
- process.exit(1);
197
- }
198
-
199
- if (acceptResult.estimatedGas) {
200
- this.logger.info(`Estimated gas: ${acceptResult.estimatedGas} sats`);
201
- }
202
-
203
- const receipt = await acceptResult.sendTransaction(txParams);
204
-
205
- this.logger.log('');
206
- this.logger.success('Package transfer accepted successfully!');
207
- this.logger.log('');
208
- this.logger.log(`Package: ${name}`);
209
- this.logger.log(`Transaction ID: ${receipt.transactionId}`);
210
- this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
211
- this.logger.log('');
212
- }
213
- } catch (error) {
214
- this.logger.fail('Acceptance failed');
215
- if (this.isUserCancelled(error)) {
216
- this.logger.warn('Acceptance cancelled.');
217
- process.exit(0);
218
- }
219
- this.exitWithError(this.formatError(error));
220
- }
221
- }
222
- }
223
-
224
- export const acceptCommand = new AcceptCommand().getCommand();