@btc-vision/cli 1.0.13 → 1.1.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.
- package/README.md +1087 -191
- package/build/commands/CompileCommand.js +5 -5
- package/build/commands/DomainCommand.js +3 -2
- package/build/commands/KeygenCommand.js +7 -6
- package/build/commands/LoginCommand.js +10 -0
- package/build/commands/PublishCommand.js +2 -2
- package/build/commands/SignCommand.js +3 -3
- package/build/commands/VerifyCommand.js +2 -2
- package/build/commands/WhoamiCommand.js +2 -1
- package/build/lib/binary.d.ts +10 -9
- package/build/lib/binary.js +50 -34
- package/build/lib/credentials.js +25 -3
- package/build/lib/ipfs.js +93 -22
- package/build/lib/manifest.js +3 -1
- package/build/lib/provider.js +5 -1
- package/build/lib/registry.js +19 -2
- package/build/lib/transaction.js +8 -3
- package/build/lib/wallet.d.ts +10 -10
- package/build/lib/wallet.js +6 -7
- package/package.json +19 -19
package/build/lib/ipfs.js
CHANGED
|
@@ -1,9 +1,59 @@
|
|
|
1
1
|
import * as https from 'https';
|
|
2
2
|
import * as http from 'http';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
|
+
import * as crypto from 'crypto';
|
|
4
5
|
import ora from 'ora';
|
|
5
6
|
import { loadConfig } from './config.js';
|
|
6
7
|
const DEFAULT_MAX_REDIRECTS = 10;
|
|
8
|
+
const MAX_RESPONSE_SIZE = 512 * 1024 * 1024;
|
|
9
|
+
function isPrivateUrl(url) {
|
|
10
|
+
try {
|
|
11
|
+
const parsed = new URL(url);
|
|
12
|
+
const hostname = parsed.hostname;
|
|
13
|
+
if (hostname === 'localhost' ||
|
|
14
|
+
hostname === '127.0.0.1' ||
|
|
15
|
+
hostname === '[::1]' ||
|
|
16
|
+
hostname === '0.0.0.0' ||
|
|
17
|
+
hostname.endsWith('.local') ||
|
|
18
|
+
hostname.endsWith('.internal')) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
const ipv4Match = hostname.match(/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
|
|
22
|
+
if (ipv4Match) {
|
|
23
|
+
const [, a, b] = ipv4Match.map(Number);
|
|
24
|
+
if (a === 10 ||
|
|
25
|
+
a === 127 ||
|
|
26
|
+
(a === 172 && b >= 16 && b <= 31) ||
|
|
27
|
+
(a === 192 && b === 168) ||
|
|
28
|
+
(a === 169 && b === 254) ||
|
|
29
|
+
a === 0) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function getSafeRedirectOptions(options, originalUrl, redirectUrl) {
|
|
40
|
+
const original = new URL(originalUrl);
|
|
41
|
+
const redirect = new URL(redirectUrl);
|
|
42
|
+
const sameOrigin = original.origin === redirect.origin;
|
|
43
|
+
if (sameOrigin) {
|
|
44
|
+
return options;
|
|
45
|
+
}
|
|
46
|
+
const safeHeaders = {};
|
|
47
|
+
if (options.headers) {
|
|
48
|
+
for (const [key, value] of Object.entries(options.headers)) {
|
|
49
|
+
const lower = key.toLowerCase();
|
|
50
|
+
if (lower !== 'authorization' && lower !== 'cookie') {
|
|
51
|
+
safeHeaders[key] = value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return { ...options, headers: safeHeaders };
|
|
56
|
+
}
|
|
7
57
|
async function httpRequest(url, options, redirectCount = 0) {
|
|
8
58
|
const maxRedirects = options.maxRedirects ?? DEFAULT_MAX_REDIRECTS;
|
|
9
59
|
const followRedirect = options.followRedirect ?? false;
|
|
@@ -29,15 +79,29 @@ async function httpRequest(url, options, redirectCount = 0) {
|
|
|
29
79
|
const location = Array.isArray(locationHeader) ? locationHeader[0] : locationHeader;
|
|
30
80
|
if (location) {
|
|
31
81
|
const redirectUrl = new URL(location, url).href;
|
|
82
|
+
if (isPrivateUrl(redirectUrl)) {
|
|
83
|
+
res.resume();
|
|
84
|
+
reject(new Error(`Redirect blocked: target resolves to a private/internal address`));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const safeOptions = getSafeRedirectOptions(options, url, redirectUrl);
|
|
32
88
|
res.resume();
|
|
33
|
-
httpRequest(redirectUrl,
|
|
89
|
+
httpRequest(redirectUrl, safeOptions, redirectCount + 1)
|
|
34
90
|
.then(resolve)
|
|
35
91
|
.catch(reject);
|
|
36
92
|
return;
|
|
37
93
|
}
|
|
38
94
|
}
|
|
39
95
|
const chunks = [];
|
|
96
|
+
let totalSize = 0;
|
|
97
|
+
const maxResponseSize = options.maxResponseSize ?? MAX_RESPONSE_SIZE;
|
|
40
98
|
res.on('data', (chunk) => {
|
|
99
|
+
totalSize += chunk.length;
|
|
100
|
+
if (totalSize > maxResponseSize) {
|
|
101
|
+
req.destroy();
|
|
102
|
+
reject(new Error(`Response size exceeded limit (${maxResponseSize} bytes)`));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
41
105
|
chunks.push(chunk);
|
|
42
106
|
});
|
|
43
107
|
res.on('end', () => {
|
|
@@ -47,7 +111,12 @@ async function httpRequest(url, options, redirectCount = 0) {
|
|
|
47
111
|
const hrefMatch = bodyStr.match(/href="([^"]+)"/);
|
|
48
112
|
if (hrefMatch && hrefMatch[1]) {
|
|
49
113
|
const redirectUrl = new URL(hrefMatch[1], url).href;
|
|
50
|
-
|
|
114
|
+
if (isPrivateUrl(redirectUrl)) {
|
|
115
|
+
reject(new Error(`Redirect blocked: target resolves to a private/internal address`));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const safeOptions = getSafeRedirectOptions(options, url, redirectUrl);
|
|
119
|
+
httpRequest(redirectUrl, safeOptions, redirectCount + 1)
|
|
51
120
|
.then(resolve)
|
|
52
121
|
.catch(reject);
|
|
53
122
|
return;
|
|
@@ -69,7 +138,9 @@ async function httpRequest(url, options, redirectCount = 0) {
|
|
|
69
138
|
reject(new Error('Request timeout'));
|
|
70
139
|
});
|
|
71
140
|
if (options.body) {
|
|
72
|
-
const bodyBuffer = Buffer.isBuffer(options.body)
|
|
141
|
+
const bodyBuffer = Buffer.isBuffer(options.body)
|
|
142
|
+
? options.body
|
|
143
|
+
: Buffer.from(options.body);
|
|
73
144
|
const totalBytes = bodyBuffer.length;
|
|
74
145
|
const chunkSize = 64 * 1024;
|
|
75
146
|
let bytesSent = 0;
|
|
@@ -109,7 +180,7 @@ export async function pinToIPFS(data, name) {
|
|
|
109
180
|
if (!endpoint) {
|
|
110
181
|
throw new Error('IPFS pinning endpoint not configured. Run `opnet config set ipfsPinningEndpoint <url>`');
|
|
111
182
|
}
|
|
112
|
-
const boundary = '----FormBoundary' +
|
|
183
|
+
const boundary = '----FormBoundary' + crypto.randomBytes(16).toString('hex');
|
|
113
184
|
const fileName = name || 'plugin.opnet';
|
|
114
185
|
const formParts = [];
|
|
115
186
|
formParts.push(Buffer.from(`--${boundary}\r\n` +
|
|
@@ -124,11 +195,13 @@ export async function pinToIPFS(data, name) {
|
|
|
124
195
|
'Content-Length': body.length.toString(),
|
|
125
196
|
};
|
|
126
197
|
if (config.ipfsPinningAuthHeader) {
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
.
|
|
130
|
-
|
|
131
|
-
|
|
198
|
+
const colonIndex = config.ipfsPinningAuthHeader.indexOf(':');
|
|
199
|
+
if (colonIndex > 0) {
|
|
200
|
+
const headerName = config.ipfsPinningAuthHeader.substring(0, colonIndex).trim();
|
|
201
|
+
const headerValue = config.ipfsPinningAuthHeader.substring(colonIndex + 1).trim();
|
|
202
|
+
if (headerName && headerValue) {
|
|
203
|
+
headers[headerName] = headerValue;
|
|
204
|
+
}
|
|
132
205
|
}
|
|
133
206
|
}
|
|
134
207
|
else if (config.ipfsPinningApiKey) {
|
|
@@ -136,10 +209,10 @@ export async function pinToIPFS(data, name) {
|
|
|
136
209
|
}
|
|
137
210
|
const url = new URL(endpoint);
|
|
138
211
|
let requestUrl;
|
|
139
|
-
if (url.hostname.
|
|
212
|
+
if (url.hostname === 'ipfs.opnet.org' || url.hostname.endsWith('.ipfs.opnet.org')) {
|
|
140
213
|
requestUrl = endpoint;
|
|
141
214
|
}
|
|
142
|
-
else if (url.hostname.
|
|
215
|
+
else if (url.hostname.endsWith('.pinata.cloud') || url.hostname === 'pinata.cloud') {
|
|
143
216
|
requestUrl = 'https://api.pinata.cloud/pinning/pinFileToIPFS';
|
|
144
217
|
if (config.ipfsPinningApiKey && !config.ipfsPinningApiKey.startsWith('eyJ')) {
|
|
145
218
|
headers['pinata_api_key'] = config.ipfsPinningApiKey;
|
|
@@ -148,10 +221,10 @@ export async function pinToIPFS(data, name) {
|
|
|
148
221
|
}
|
|
149
222
|
}
|
|
150
223
|
}
|
|
151
|
-
else if (url.hostname.
|
|
224
|
+
else if (url.hostname.endsWith('.web3.storage') || url.hostname === 'web3.storage' || url.hostname.endsWith('.w3s.link') || url.hostname === 'w3s.link') {
|
|
152
225
|
requestUrl = endpoint.endsWith('/') ? endpoint + 'upload' : endpoint + '/upload';
|
|
153
226
|
}
|
|
154
|
-
else if (url.hostname.
|
|
227
|
+
else if (url.hostname.endsWith('.nft.storage') || url.hostname === 'nft.storage') {
|
|
155
228
|
requestUrl = 'https://api.nft.storage/upload';
|
|
156
229
|
}
|
|
157
230
|
else if (url.pathname.includes('/api/v0/')) {
|
|
@@ -194,7 +267,9 @@ export async function pinToIPFS(data, name) {
|
|
|
194
267
|
};
|
|
195
268
|
}
|
|
196
269
|
catch (e) {
|
|
197
|
-
throw new Error(`IPFS pinning failed: ${e instanceof Error ? e.message : String(e)}
|
|
270
|
+
throw new Error(`IPFS pinning failed: ${e instanceof Error ? e.message : String(e)}`, {
|
|
271
|
+
cause: e,
|
|
272
|
+
});
|
|
198
273
|
}
|
|
199
274
|
}
|
|
200
275
|
export async function fetchFromIPFS(cid) {
|
|
@@ -372,14 +447,10 @@ function getMimeType(filePath) {
|
|
|
372
447
|
return mimeTypes[ext] || 'application/octet-stream';
|
|
373
448
|
}
|
|
374
449
|
function generateSessionId() {
|
|
375
|
-
return
|
|
376
|
-
const r = (Math.random() * 16) | 0;
|
|
377
|
-
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
378
|
-
return v.toString(16);
|
|
379
|
-
});
|
|
450
|
+
return crypto.randomUUID();
|
|
380
451
|
}
|
|
381
452
|
function sleep(ms) {
|
|
382
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
453
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
383
454
|
}
|
|
384
455
|
async function mfsCall(endpoint, apiPath, params, body, headers, maxRetries = 3) {
|
|
385
456
|
const url = new URL(endpoint);
|
|
@@ -392,7 +463,7 @@ async function mfsCall(endpoint, apiPath, params, body, headers, maxRetries = 3)
|
|
|
392
463
|
};
|
|
393
464
|
let formBody;
|
|
394
465
|
if (body) {
|
|
395
|
-
const boundary = '----FormBoundary' +
|
|
466
|
+
const boundary = '----FormBoundary' + crypto.randomBytes(16).toString('hex');
|
|
396
467
|
const formParts = [];
|
|
397
468
|
formParts.push(Buffer.from(`--${boundary}\r\n` +
|
|
398
469
|
`Content-Disposition: form-data; name="file"\r\n` +
|
|
@@ -541,7 +612,7 @@ export async function uploadDirectory(dirPath, _wrapWithDirectory = true) {
|
|
|
541
612
|
}
|
|
542
613
|
catch {
|
|
543
614
|
}
|
|
544
|
-
throw new Error(`IPFS directory upload failed: ${e instanceof Error ? e.message : String(e)}
|
|
615
|
+
throw new Error(`IPFS directory upload failed: ${e instanceof Error ? e.message : String(e)}`, { cause: e });
|
|
545
616
|
}
|
|
546
617
|
}
|
|
547
618
|
export async function uploadFile(filePath) {
|
package/build/lib/manifest.js
CHANGED
|
@@ -46,7 +46,9 @@ export function loadManifest(manifestPath) {
|
|
|
46
46
|
manifest = JSON.parse(content);
|
|
47
47
|
}
|
|
48
48
|
catch (e) {
|
|
49
|
-
throw new Error(`Failed to parse manifest: ${e instanceof Error ? e.message : String(e)}
|
|
49
|
+
throw new Error(`Failed to parse manifest: ${e instanceof Error ? e.message : String(e)}`, {
|
|
50
|
+
cause: e,
|
|
51
|
+
});
|
|
50
52
|
}
|
|
51
53
|
const errors = [];
|
|
52
54
|
if (!manifest.name || typeof manifest.name !== 'string') {
|
package/build/lib/provider.js
CHANGED
|
@@ -13,7 +13,11 @@ export function getProvider(network) {
|
|
|
13
13
|
return cached;
|
|
14
14
|
}
|
|
15
15
|
const bitcoinNetwork = getNetwork(targetNetwork);
|
|
16
|
-
const provider = new JSONRpcProvider(
|
|
16
|
+
const provider = new JSONRpcProvider({
|
|
17
|
+
url: rpcUrl,
|
|
18
|
+
network: bitcoinNetwork,
|
|
19
|
+
timeout: DEFAULT_TIMEOUT,
|
|
20
|
+
});
|
|
17
21
|
providerCache.set(cacheKey, provider);
|
|
18
22
|
return provider;
|
|
19
23
|
}
|
package/build/lib/registry.js
CHANGED
|
@@ -161,8 +161,21 @@ export function parsePackageName(fullName) {
|
|
|
161
161
|
}
|
|
162
162
|
return { scope: null, name: fullName };
|
|
163
163
|
}
|
|
164
|
+
function canonicalSort(value) {
|
|
165
|
+
if (value === null || value === undefined || typeof value !== 'object') {
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
if (Array.isArray(value)) {
|
|
169
|
+
return value.map(canonicalSort);
|
|
170
|
+
}
|
|
171
|
+
const sorted = {};
|
|
172
|
+
for (const key of Object.keys(value).sort()) {
|
|
173
|
+
sorted[key] = canonicalSort(value[key]);
|
|
174
|
+
}
|
|
175
|
+
return sorted;
|
|
176
|
+
}
|
|
164
177
|
export function computePermissionsHash(permissions) {
|
|
165
|
-
const json = JSON.stringify(permissions);
|
|
178
|
+
const json = JSON.stringify(canonicalSort(permissions));
|
|
166
179
|
const hash = crypto.createHash('sha256').update(json).digest();
|
|
167
180
|
return new Uint8Array(hash);
|
|
168
181
|
}
|
|
@@ -179,7 +192,11 @@ export function registryToMldsaLevel(registryLevel) {
|
|
|
179
192
|
2: 65,
|
|
180
193
|
3: 87,
|
|
181
194
|
};
|
|
182
|
-
|
|
195
|
+
const level = levels[registryLevel];
|
|
196
|
+
if (level === undefined) {
|
|
197
|
+
throw new Error(`Unknown MLDSA registry level: ${registryLevel}. Expected 1, 2, or 3.`);
|
|
198
|
+
}
|
|
199
|
+
return level;
|
|
183
200
|
}
|
|
184
201
|
export function mldsaLevelToRegistry(mldsaLevel) {
|
|
185
202
|
const levels = {
|
package/build/lib/transaction.js
CHANGED
|
@@ -19,9 +19,14 @@ export function getWalletAddress(wallet) {
|
|
|
19
19
|
return wallet.address;
|
|
20
20
|
}
|
|
21
21
|
export function formatSats(sats) {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const btcWhole = sats / 100000000n;
|
|
23
|
+
const btcFrac = sats % 100000000n;
|
|
24
|
+
const absWhole = btcWhole < 0n ? -btcWhole : btcWhole;
|
|
25
|
+
const absFrac = btcFrac < 0n ? -btcFrac : btcFrac;
|
|
26
|
+
const sign = sats < 0n ? '-' : '';
|
|
27
|
+
const btcStr = `${sign}${absWhole}.${absFrac.toString().padStart(8, '0')}`;
|
|
28
|
+
if (absWhole > 0n || absFrac >= 100000n) {
|
|
29
|
+
return `${sats} sats (${btcStr} BTC)`;
|
|
25
30
|
}
|
|
26
31
|
return `${sats} sats`;
|
|
27
32
|
}
|
package/build/lib/wallet.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Network
|
|
1
|
+
import { Network } from '@btc-vision/bitcoin';
|
|
2
2
|
import { MLDSASecurityLevel, QuantumBIP32Interface } from '@btc-vision/bip32';
|
|
3
3
|
import { Address } from '@btc-vision/transaction';
|
|
4
4
|
import { CLICredentials, CLIMldsaLevel, NetworkName } from '../types/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { UniversalSigner } from '@btc-vision/ecpair';
|
|
6
6
|
export declare function getNetwork(networkName: NetworkName): Network;
|
|
7
7
|
export declare function getMLDSASecurityLevel(level: CLIMldsaLevel): MLDSASecurityLevel;
|
|
8
8
|
export declare class CLIWallet {
|
|
@@ -12,21 +12,21 @@ export declare class CLIWallet {
|
|
|
12
12
|
private constructor();
|
|
13
13
|
get address(): Address;
|
|
14
14
|
get p2trAddress(): string;
|
|
15
|
-
get keypair():
|
|
15
|
+
get keypair(): UniversalSigner | null;
|
|
16
16
|
get mldsaKeypair(): QuantumBIP32Interface;
|
|
17
|
-
get mldsaPublicKey():
|
|
17
|
+
get mldsaPublicKey(): Uint8Array;
|
|
18
18
|
get mldsaPublicKeyHash(): string;
|
|
19
19
|
get securityLevel(): CLIMldsaLevel;
|
|
20
20
|
static fromCredentials(credentials: CLICredentials): CLIWallet;
|
|
21
21
|
static load(): CLIWallet;
|
|
22
|
-
static verifyMLDSA(data:
|
|
23
|
-
signMLDSA(data:
|
|
24
|
-
verifyMLDSA(data:
|
|
22
|
+
static verifyMLDSA(data: Uint8Array, signature: Uint8Array, publicKey: Uint8Array, level: CLIMldsaLevel): boolean;
|
|
23
|
+
signMLDSA(data: Uint8Array): Uint8Array;
|
|
24
|
+
verifyMLDSA(data: Uint8Array, signature: Uint8Array): boolean;
|
|
25
25
|
}
|
|
26
26
|
export declare function generateMLDSAKeypair(level: CLIMldsaLevel): {
|
|
27
|
-
privateKey:
|
|
28
|
-
publicKey:
|
|
27
|
+
privateKey: Uint8Array;
|
|
28
|
+
publicKey: Uint8Array;
|
|
29
29
|
};
|
|
30
|
-
export declare function computePublicKeyHash(publicKey:
|
|
30
|
+
export declare function computePublicKeyHash(publicKey: Uint8Array): string;
|
|
31
31
|
export declare function validateMnemonic(phrase: string): boolean;
|
|
32
32
|
export declare function generateMnemonic(): string;
|
package/build/lib/wallet.js
CHANGED
|
@@ -45,11 +45,10 @@ export class CLIWallet {
|
|
|
45
45
|
return this.wallet.mldsaKeypair;
|
|
46
46
|
}
|
|
47
47
|
get mldsaPublicKey() {
|
|
48
|
-
return
|
|
48
|
+
return this.wallet.mldsaKeypair.publicKey;
|
|
49
49
|
}
|
|
50
50
|
get mldsaPublicKeyHash() {
|
|
51
|
-
|
|
52
|
-
return hash.toString('hex');
|
|
51
|
+
return crypto.createHash('sha256').update(this.mldsaPublicKey).digest('hex');
|
|
53
52
|
}
|
|
54
53
|
get securityLevel() {
|
|
55
54
|
return this.mldsaLevel;
|
|
@@ -59,7 +58,7 @@ export class CLIWallet {
|
|
|
59
58
|
const securityLevel = getMLDSASecurityLevel(credentials.mldsaLevel);
|
|
60
59
|
if (credentials.mnemonic) {
|
|
61
60
|
const mnemonic = new Mnemonic(credentials.mnemonic, '', network, securityLevel);
|
|
62
|
-
const wallet = mnemonic.
|
|
61
|
+
const wallet = mnemonic.deriveOPWallet();
|
|
63
62
|
return new CLIWallet(wallet, network, credentials.mldsaLevel);
|
|
64
63
|
}
|
|
65
64
|
if (credentials.wif && credentials.mldsaPrivateKey) {
|
|
@@ -86,7 +85,7 @@ export class CLIWallet {
|
|
|
86
85
|
}
|
|
87
86
|
signMLDSA(data) {
|
|
88
87
|
const result = MessageSigner.signMLDSAMessage(this.wallet.mldsaKeypair, data);
|
|
89
|
-
return
|
|
88
|
+
return result.signature;
|
|
90
89
|
}
|
|
91
90
|
verifyMLDSA(data, signature) {
|
|
92
91
|
return MessageSigner.verifyMLDSASignature(this.wallet.mldsaKeypair, data, signature);
|
|
@@ -96,8 +95,8 @@ export function generateMLDSAKeypair(level) {
|
|
|
96
95
|
const securityLevel = getMLDSASecurityLevel(level);
|
|
97
96
|
const keypair = EcKeyPair.generateQuantumKeyPair(securityLevel);
|
|
98
97
|
return {
|
|
99
|
-
privateKey:
|
|
100
|
-
publicKey:
|
|
98
|
+
privateKey: keypair.privateKey,
|
|
99
|
+
publicKey: keypair.publicKey,
|
|
101
100
|
};
|
|
102
101
|
}
|
|
103
102
|
export function computePublicKeyHash(publicKey) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btc-vision/cli",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for the OPNet plugin ecosystem - scaffolding, compilation, signing, and registry interaction",
|
|
6
6
|
"author": "OP_NET",
|
|
@@ -49,32 +49,32 @@
|
|
|
49
49
|
"prepublishOnly": "npm run build"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@btc-vision/bip32": "^
|
|
53
|
-
"@btc-vision/bitcoin": "^
|
|
54
|
-
"@btc-vision/
|
|
55
|
-
"@btc-vision/
|
|
56
|
-
"@btc-vision/
|
|
57
|
-
"@
|
|
52
|
+
"@btc-vision/bip32": "^7.1.2",
|
|
53
|
+
"@btc-vision/bitcoin": "^7.0.0-rc.4",
|
|
54
|
+
"@btc-vision/ecpair": "^4.0.5",
|
|
55
|
+
"@btc-vision/logger": "^1.0.8",
|
|
56
|
+
"@btc-vision/plugin-sdk": "^1.0.1",
|
|
57
|
+
"@btc-vision/transaction": "^1.8.0-rc.4",
|
|
58
|
+
"@inquirer/prompts": "^8.2.1",
|
|
58
59
|
"bytenode": "^1.5.7",
|
|
59
|
-
"commander": "^14.0.
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"ora": "^9.0.0"
|
|
60
|
+
"commander": "^14.0.3",
|
|
61
|
+
"esbuild": "^0.27.3",
|
|
62
|
+
"opnet": "^1.8.1-rc.3",
|
|
63
|
+
"ora": "^9.3.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@eslint/js": "^
|
|
67
|
-
"@types/node": "^25.
|
|
68
|
-
"eslint": "^
|
|
66
|
+
"@eslint/js": "^10.0.1",
|
|
67
|
+
"@types/node": "^25.2.3",
|
|
68
|
+
"eslint": "^10.0.0",
|
|
69
69
|
"gulp": "^5.0.1",
|
|
70
70
|
"gulp-cached": "^1.1.1",
|
|
71
71
|
"gulp-clean": "^0.4.0",
|
|
72
|
-
"gulp-eslint-new": "^2.
|
|
72
|
+
"gulp-eslint-new": "^2.6.0",
|
|
73
73
|
"gulp-logger-new": "^1.0.1",
|
|
74
74
|
"gulp-typescript": "^6.0.0-alpha.1",
|
|
75
|
-
"prettier": "^3.
|
|
76
|
-
"typescript": "^5.9.
|
|
77
|
-
"typescript-eslint": "^8.
|
|
75
|
+
"prettier": "^3.8.1",
|
|
76
|
+
"typescript": "^5.9.3",
|
|
77
|
+
"typescript-eslint": "^8.56.0"
|
|
78
78
|
},
|
|
79
79
|
"keywords": [
|
|
80
80
|
"opnet",
|