@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.
- package/build/index.js +3 -4
- package/build/lib/config.js +1 -6
- package/build/lib/ipfs.d.ts +0 -2
- package/build/lib/ipfs.js +29 -32
- package/build/lib/wallet.js +1 -1
- package/package.json +4 -1
- package/.gitattributes +0 -2
- package/.github/dependabot.yml +0 -9
- package/.github/workflows/ci.yml +0 -48
- package/.prettierrc.json +0 -12
- package/CONTRIBUTING.md +0 -56
- package/NOTICE +0 -17
- package/SECURITY.md +0 -35
- package/eslint.config.js +0 -41
- package/gulpfile.js +0 -41
- package/src/commands/AcceptCommand.ts +0 -224
- package/src/commands/BaseCommand.ts +0 -59
- package/src/commands/CompileCommand.ts +0 -195
- package/src/commands/ConfigCommand.ts +0 -117
- package/src/commands/DeprecateCommand.ts +0 -193
- package/src/commands/InfoCommand.ts +0 -293
- package/src/commands/InitCommand.ts +0 -541
- package/src/commands/InstallCommand.ts +0 -179
- package/src/commands/KeygenCommand.ts +0 -157
- package/src/commands/ListCommand.ts +0 -169
- package/src/commands/LoginCommand.ts +0 -197
- package/src/commands/LogoutCommand.ts +0 -76
- package/src/commands/PublishCommand.ts +0 -340
- package/src/commands/ScopeRegisterCommand.ts +0 -164
- package/src/commands/SearchCommand.ts +0 -140
- package/src/commands/SignCommand.ts +0 -110
- package/src/commands/TransferCommand.ts +0 -363
- package/src/commands/UndeprecateCommand.ts +0 -167
- package/src/commands/UpdateCommand.ts +0 -200
- package/src/commands/VerifyCommand.ts +0 -228
- package/src/commands/WhoamiCommand.ts +0 -113
- package/src/index.ts +0 -88
- package/src/lib/PackageRegistry.abi.json +0 -765
- package/src/lib/PackageRegistry.abi.ts +0 -365
- package/src/lib/binary.ts +0 -338
- package/src/lib/config.ts +0 -265
- package/src/lib/credentials.ts +0 -176
- package/src/lib/ipfs.ts +0 -382
- package/src/lib/manifest.ts +0 -195
- package/src/lib/provider.ts +0 -121
- package/src/lib/registry.ts +0 -467
- package/src/lib/transaction.ts +0 -205
- package/src/lib/wallet.ts +0 -262
- package/src/types/PackageRegistry.ts +0 -344
- package/src/types/index.ts +0 -147
- 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
|
-
|
|
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}`);
|
package/build/lib/config.js
CHANGED
|
@@ -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: '',
|
package/build/lib/ipfs.d.ts
CHANGED
|
@@ -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
|
-
|
|
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 (
|
|
40
|
+
if (statusCode >= 200 && statusCode < 300) {
|
|
26
41
|
resolve(body);
|
|
27
42
|
}
|
|
28
43
|
else {
|
|
29
|
-
|
|
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
|
-
}
|
package/build/lib/wallet.js
CHANGED
|
@@ -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
|
|
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.
|
|
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
package/.github/dependabot.yml
DELETED
package/.github/workflows/ci.yml
DELETED
|
@@ -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
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();
|