@btc-vision/cli 1.0.2 → 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.
- package/README.md +55 -23
- package/build/commands/AcceptCommand.js +62 -15
- package/build/commands/ConfigCommand.js +2 -27
- package/build/commands/DeprecateCommand.js +32 -11
- package/build/commands/InitCommand.js +0 -6
- package/build/commands/PublishCommand.js +82 -27
- package/build/commands/ScopeRegisterCommand.d.ts +7 -0
- package/build/commands/ScopeRegisterCommand.js +115 -0
- package/build/commands/TransferCommand.js +118 -30
- package/build/commands/UndeprecateCommand.js +31 -10
- package/build/index.js +2 -0
- package/build/lib/config.d.ts +1 -0
- package/build/lib/config.js +3 -2
- package/build/lib/ipfs.js +85 -76
- package/build/lib/registry.d.ts +1 -1
- package/build/lib/registry.js +3 -3
- package/build/lib/transaction.d.ts +27 -0
- package/build/lib/transaction.js +91 -0
- package/build/lib/wallet.d.ts +7 -7
- package/build/lib/wallet.js +3 -6
- package/build/types/index.d.ts +1 -0
- package/package.json +2 -1
- package/src/commands/AcceptCommand.ts +89 -16
- package/src/commands/ConfigCommand.ts +2 -29
- package/src/commands/DeprecateCommand.ts +48 -11
- package/src/commands/InitCommand.ts +0 -6
- package/src/commands/PublishCommand.ts +138 -28
- package/src/commands/ScopeRegisterCommand.ts +164 -0
- package/src/commands/TransferCommand.ts +159 -31
- package/src/commands/UndeprecateCommand.ts +43 -10
- package/src/index.ts +2 -0
- package/src/lib/config.ts +3 -2
- package/src/lib/ipfs.ts +113 -99
- package/src/lib/registry.ts +5 -2
- package/src/lib/transaction.ts +205 -0
- package/src/lib/wallet.ts +10 -19
- package/src/types/index.ts +3 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Address } from '@btc-vision/transaction';
|
|
2
|
+
import { TransactionParameters } from 'opnet';
|
|
3
|
+
import { CLIWallet } from './wallet.js';
|
|
4
|
+
import { NetworkName } from '../types/index.js';
|
|
5
|
+
import { PsbtOutputExtended } from '@btc-vision/bitcoin';
|
|
6
|
+
export declare const DEFAULT_MAX_SAT_TO_SPEND = 100000n;
|
|
7
|
+
export declare const DEFAULT_FEE_RATE = 6;
|
|
8
|
+
export declare function buildTransactionParams(wallet: CLIWallet, network: NetworkName, maxSatToSpend?: bigint, feeRate?: number, extra?: PsbtOutputExtended): TransactionParameters;
|
|
9
|
+
export declare function getWalletAddress(wallet: CLIWallet): Address;
|
|
10
|
+
export declare function formatSats(sats: bigint): string;
|
|
11
|
+
export declare function checkBalance(wallet: CLIWallet, network: NetworkName, minBalance?: bigint): Promise<{
|
|
12
|
+
sufficient: boolean;
|
|
13
|
+
balance: bigint;
|
|
14
|
+
}>;
|
|
15
|
+
export declare const DEFAULT_POLL_INTERVAL = 10000;
|
|
16
|
+
export declare const DEFAULT_MAX_WAIT_TIME = 600000;
|
|
17
|
+
export interface TransactionConfirmationResult {
|
|
18
|
+
confirmed: boolean;
|
|
19
|
+
blockNumber?: bigint;
|
|
20
|
+
revert?: string;
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function waitForTransactionConfirmation(txHash: string, network: NetworkName, options?: {
|
|
24
|
+
pollInterval?: number;
|
|
25
|
+
maxWaitTime?: number;
|
|
26
|
+
message?: string;
|
|
27
|
+
}): Promise<TransactionConfirmationResult>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import ora from 'ora';
|
|
2
|
+
import { getNetwork } from './wallet.js';
|
|
3
|
+
import { getProvider } from './provider.js';
|
|
4
|
+
export const DEFAULT_MAX_SAT_TO_SPEND = 100000n;
|
|
5
|
+
export const DEFAULT_FEE_RATE = 6;
|
|
6
|
+
export function buildTransactionParams(wallet, network, maxSatToSpend = DEFAULT_MAX_SAT_TO_SPEND, feeRate = DEFAULT_FEE_RATE, extra) {
|
|
7
|
+
const bitcoinNetwork = getNetwork(network);
|
|
8
|
+
return {
|
|
9
|
+
signer: wallet.keypair,
|
|
10
|
+
mldsaSigner: wallet.mldsaKeypair,
|
|
11
|
+
refundTo: wallet.p2trAddress,
|
|
12
|
+
maximumAllowedSatToSpend: maxSatToSpend,
|
|
13
|
+
network: bitcoinNetwork,
|
|
14
|
+
feeRate,
|
|
15
|
+
extraOutputs: extra ? [extra] : undefined,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export function getWalletAddress(wallet) {
|
|
19
|
+
return wallet.address;
|
|
20
|
+
}
|
|
21
|
+
export function formatSats(sats) {
|
|
22
|
+
const btc = Number(sats) / 100_000_000;
|
|
23
|
+
if (btc >= 0.001) {
|
|
24
|
+
return `${sats} sats (${btc.toFixed(8)} BTC)`;
|
|
25
|
+
}
|
|
26
|
+
return `${sats} sats`;
|
|
27
|
+
}
|
|
28
|
+
export async function checkBalance(wallet, network, minBalance = 10000n) {
|
|
29
|
+
const provider = getProvider(network);
|
|
30
|
+
const balance = await provider.getBalance(wallet.p2trAddress);
|
|
31
|
+
return {
|
|
32
|
+
sufficient: balance >= minBalance,
|
|
33
|
+
balance,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export const DEFAULT_POLL_INTERVAL = 10_000;
|
|
37
|
+
export const DEFAULT_MAX_WAIT_TIME = 600_000;
|
|
38
|
+
export async function waitForTransactionConfirmation(txHash, network, options) {
|
|
39
|
+
const pollInterval = options?.pollInterval ?? DEFAULT_POLL_INTERVAL;
|
|
40
|
+
const maxWaitTime = options?.maxWaitTime ?? DEFAULT_MAX_WAIT_TIME;
|
|
41
|
+
const message = options?.message ?? 'Waiting for transaction confirmation';
|
|
42
|
+
const provider = getProvider(network);
|
|
43
|
+
const startTime = Date.now();
|
|
44
|
+
const spinner = ora({
|
|
45
|
+
text: `${message} (0s elapsed)`,
|
|
46
|
+
spinner: 'dots',
|
|
47
|
+
}).start();
|
|
48
|
+
const updateSpinnerText = () => {
|
|
49
|
+
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
50
|
+
spinner.text = `${message} (${elapsed}s elapsed)`;
|
|
51
|
+
};
|
|
52
|
+
const textUpdateInterval = setInterval(updateSpinnerText, 1000);
|
|
53
|
+
try {
|
|
54
|
+
while (Date.now() - startTime < maxWaitTime) {
|
|
55
|
+
try {
|
|
56
|
+
const tx = await provider.getTransaction(txHash);
|
|
57
|
+
if (tx.blockNumber !== undefined && tx.blockNumber !== null) {
|
|
58
|
+
const blockNum = typeof tx.blockNumber === 'bigint'
|
|
59
|
+
? tx.blockNumber
|
|
60
|
+
: BigInt(tx.blockNumber);
|
|
61
|
+
spinner.succeed(`Transaction confirmed in block ${blockNum}`);
|
|
62
|
+
return {
|
|
63
|
+
confirmed: true,
|
|
64
|
+
blockNumber: blockNum,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (tx.revert) {
|
|
68
|
+
spinner.fail(`Transaction reverted: ${tx.revert}`);
|
|
69
|
+
return {
|
|
70
|
+
confirmed: false,
|
|
71
|
+
revert: tx.revert,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
}
|
|
77
|
+
await sleep(pollInterval);
|
|
78
|
+
}
|
|
79
|
+
spinner.fail(`Timeout waiting for transaction confirmation`);
|
|
80
|
+
return {
|
|
81
|
+
confirmed: false,
|
|
82
|
+
error: `Transaction not confirmed within ${maxWaitTime / 1000} seconds`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
clearInterval(textUpdateInterval);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function sleep(ms) {
|
|
90
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
91
|
+
}
|
package/build/lib/wallet.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Network } from '@btc-vision/bitcoin';
|
|
2
|
-
import { MLDSASecurityLevel } from '@btc-vision/bip32';
|
|
3
|
-
import {
|
|
1
|
+
import { Network, Signer } from '@btc-vision/bitcoin';
|
|
2
|
+
import { MLDSASecurityLevel, QuantumBIP32Interface } from '@btc-vision/bip32';
|
|
3
|
+
import { Address } from '@btc-vision/transaction';
|
|
4
4
|
import { CLICredentials, CLIMldsaLevel, NetworkName } from '../types/index.js';
|
|
5
|
+
import { ECPairInterface } from 'ecpair';
|
|
5
6
|
export declare function getNetwork(networkName: NetworkName): Network;
|
|
6
7
|
export declare function getMLDSASecurityLevel(level: CLIMldsaLevel): MLDSASecurityLevel;
|
|
7
8
|
export declare class CLIWallet {
|
|
@@ -9,14 +10,13 @@ export declare class CLIWallet {
|
|
|
9
10
|
private readonly network;
|
|
10
11
|
private readonly mldsaLevel;
|
|
11
12
|
private constructor();
|
|
13
|
+
get address(): Address;
|
|
12
14
|
get p2trAddress(): string;
|
|
13
|
-
get
|
|
14
|
-
get
|
|
15
|
-
get mldsaKeypair(): EcKeyPair;
|
|
15
|
+
get keypair(): Signer | ECPairInterface | null;
|
|
16
|
+
get mldsaKeypair(): QuantumBIP32Interface;
|
|
16
17
|
get mldsaPublicKey(): Buffer;
|
|
17
18
|
get mldsaPublicKeyHash(): string;
|
|
18
19
|
get securityLevel(): CLIMldsaLevel;
|
|
19
|
-
get walletNetwork(): Network;
|
|
20
20
|
static fromCredentials(credentials: CLICredentials): CLIWallet;
|
|
21
21
|
static load(): CLIWallet;
|
|
22
22
|
static verifyMLDSA(data: Buffer, signature: Buffer, publicKey: Buffer, level: CLIMldsaLevel): boolean;
|
package/build/lib/wallet.js
CHANGED
|
@@ -32,12 +32,12 @@ export class CLIWallet {
|
|
|
32
32
|
this.network = network;
|
|
33
33
|
this.mldsaLevel = mldsaLevel;
|
|
34
34
|
}
|
|
35
|
+
get address() {
|
|
36
|
+
return this.wallet.address;
|
|
37
|
+
}
|
|
35
38
|
get p2trAddress() {
|
|
36
39
|
return this.wallet.p2tr;
|
|
37
40
|
}
|
|
38
|
-
get underlyingWallet() {
|
|
39
|
-
return this.wallet;
|
|
40
|
-
}
|
|
41
41
|
get keypair() {
|
|
42
42
|
return this.wallet.keypair;
|
|
43
43
|
}
|
|
@@ -54,9 +54,6 @@ export class CLIWallet {
|
|
|
54
54
|
get securityLevel() {
|
|
55
55
|
return this.mldsaLevel;
|
|
56
56
|
}
|
|
57
|
-
get walletNetwork() {
|
|
58
|
-
return this.network;
|
|
59
|
-
}
|
|
60
57
|
static fromCredentials(credentials) {
|
|
61
58
|
const network = getNetwork(credentials.network);
|
|
62
59
|
const securityLevel = getMLDSASecurityLevel(credentials.mldsaLevel);
|
package/build/types/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface CLIConfig {
|
|
|
8
8
|
ipfsGateways: string[];
|
|
9
9
|
ipfsPinningEndpoint: string;
|
|
10
10
|
ipfsPinningApiKey: string;
|
|
11
|
+
ipfsPinningSecret: string;
|
|
11
12
|
ipfsPinningAuthHeader: string;
|
|
12
13
|
registryAddresses: Record<NetworkName, string>;
|
|
13
14
|
defaultMldsaLevel: CLIMldsaLevel;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btc-vision/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "CLI for the OPNet plugin ecosystem - scaffolding, compilation, signing, and registry interaction",
|
|
6
6
|
"author": "OP_NET",
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"@inquirer/prompts": "^7.5.3",
|
|
53
53
|
"bytenode": "^1.5.7",
|
|
54
54
|
"commander": "^14.0.0",
|
|
55
|
+
"ecpair": "^2.1.0",
|
|
55
56
|
"esbuild": "^0.25.5",
|
|
56
57
|
"opnet": "^1.7.18",
|
|
57
58
|
"ora": "^8.2.0"
|
|
@@ -6,9 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
import { confirm } from '@inquirer/prompts';
|
|
8
8
|
import { BaseCommand } from './BaseCommand.js';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
getPendingScopeTransfer,
|
|
11
|
+
getPendingTransfer,
|
|
12
|
+
getRegistryContract,
|
|
13
|
+
} from '../lib/registry.js';
|
|
10
14
|
import { canSign, loadCredentials } from '../lib/credentials.js';
|
|
11
15
|
import { CLIWallet } from '../lib/wallet.js';
|
|
16
|
+
import {
|
|
17
|
+
buildTransactionParams,
|
|
18
|
+
checkBalance,
|
|
19
|
+
formatSats,
|
|
20
|
+
getWalletAddress,
|
|
21
|
+
} from '../lib/transaction.js';
|
|
12
22
|
import { NetworkName } from '../types/index.js';
|
|
13
23
|
|
|
14
24
|
interface AcceptOptions {
|
|
@@ -41,7 +51,7 @@ export class AcceptCommand extends BaseCommand {
|
|
|
41
51
|
this.logger.warn('Run `opnet login` to configure your wallet.');
|
|
42
52
|
process.exit(1);
|
|
43
53
|
}
|
|
44
|
-
CLIWallet.fromCredentials(credentials);
|
|
54
|
+
const wallet = CLIWallet.fromCredentials(credentials);
|
|
45
55
|
this.logger.success('Wallet loaded');
|
|
46
56
|
|
|
47
57
|
const network = (options?.network || 'mainnet') as NetworkName;
|
|
@@ -84,12 +94,46 @@ export class AcceptCommand extends BaseCommand {
|
|
|
84
94
|
}
|
|
85
95
|
}
|
|
86
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
|
+
|
|
87
108
|
// Execute acceptance
|
|
88
109
|
this.logger.info('Accepting transfer...');
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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;
|
|
93
137
|
} else {
|
|
94
138
|
const pending = await getPendingTransfer(name, network);
|
|
95
139
|
|
|
@@ -123,20 +167,49 @@ export class AcceptCommand extends BaseCommand {
|
|
|
123
167
|
}
|
|
124
168
|
}
|
|
125
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
|
+
|
|
126
184
|
// Execute acceptance
|
|
127
185
|
this.logger.info('Accepting transfer...');
|
|
128
|
-
this.logger.warn('Acceptance transaction required.');
|
|
129
|
-
this.logger.log('Transaction would call: acceptTransfer(');
|
|
130
|
-
this.logger.log(` packageName: "${name}"`);
|
|
131
|
-
this.logger.log(')');
|
|
132
|
-
}
|
|
133
186
|
|
|
134
|
-
|
|
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);
|
|
135
192
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
+
}
|
|
140
213
|
} catch (error) {
|
|
141
214
|
this.logger.fail('Acceptance failed');
|
|
142
215
|
if (this.isUserCancelled(error)) {
|
|
@@ -8,8 +8,7 @@ import { Command } from 'commander';
|
|
|
8
8
|
import * as os from 'os';
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import { BaseCommand } from './BaseCommand.js';
|
|
11
|
-
import { displayConfig, getConfigValue, saveConfig, setConfigValue } from '../lib/config.js';
|
|
12
|
-
import { CLIConfig } from '../types/index.js';
|
|
11
|
+
import { DEFAULT_CONFIG, displayConfig, getConfigValue, saveConfig, setConfigValue, } from '../lib/config.js';
|
|
13
12
|
|
|
14
13
|
export class ConfigCommand extends BaseCommand {
|
|
15
14
|
constructor() {
|
|
@@ -106,33 +105,7 @@ export class ConfigCommand extends BaseCommand {
|
|
|
106
105
|
return;
|
|
107
106
|
}
|
|
108
107
|
|
|
109
|
-
|
|
110
|
-
defaultNetwork: 'mainnet',
|
|
111
|
-
rpcUrls: {
|
|
112
|
-
mainnet: 'https://api.opnet.org',
|
|
113
|
-
testnet: 'https://testnet.opnet.org',
|
|
114
|
-
regtest: 'http://localhost:9001',
|
|
115
|
-
},
|
|
116
|
-
ipfsGateway: 'https://ipfs.opnet.org/ipfs/',
|
|
117
|
-
ipfsGateways: [
|
|
118
|
-
'https://ipfs.opnet.org/ipfs/',
|
|
119
|
-
'https://ipfs.io/ipfs/',
|
|
120
|
-
'https://cloudflare-ipfs.com/ipfs/',
|
|
121
|
-
'https://dweb.link/ipfs/',
|
|
122
|
-
],
|
|
123
|
-
ipfsPinningEndpoint: 'https://ipfs.opnet.org/api/v0/add',
|
|
124
|
-
ipfsPinningApiKey: '',
|
|
125
|
-
ipfsPinningAuthHeader: 'Authorization',
|
|
126
|
-
registryAddresses: {
|
|
127
|
-
mainnet: '',
|
|
128
|
-
testnet: '',
|
|
129
|
-
regtest: '',
|
|
130
|
-
},
|
|
131
|
-
defaultMldsaLevel: 44,
|
|
132
|
-
indexerUrl: 'https://indexer.opnet.org',
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
saveConfig(defaultConfig);
|
|
108
|
+
saveConfig(DEFAULT_CONFIG);
|
|
136
109
|
this.logger.success('Configuration reset to defaults.');
|
|
137
110
|
}
|
|
138
111
|
|
|
@@ -6,9 +6,15 @@
|
|
|
6
6
|
|
|
7
7
|
import { confirm, input } from '@inquirer/prompts';
|
|
8
8
|
import { BaseCommand } from './BaseCommand.js';
|
|
9
|
-
import { getPackage, getVersion, isVersionImmutable } from '../lib/registry.js';
|
|
9
|
+
import { getPackage, getRegistryContract, getVersion, isVersionImmutable } from '../lib/registry.js';
|
|
10
10
|
import { canSign, loadCredentials } from '../lib/credentials.js';
|
|
11
11
|
import { CLIWallet } from '../lib/wallet.js';
|
|
12
|
+
import {
|
|
13
|
+
buildTransactionParams,
|
|
14
|
+
checkBalance,
|
|
15
|
+
formatSats,
|
|
16
|
+
getWalletAddress,
|
|
17
|
+
} from '../lib/transaction.js';
|
|
12
18
|
import { NetworkName } from '../types/index.js';
|
|
13
19
|
|
|
14
20
|
interface DeprecateOptions {
|
|
@@ -48,7 +54,7 @@ export class DeprecateCommand extends BaseCommand {
|
|
|
48
54
|
this.logger.warn('Run `opnet login` to configure your wallet.');
|
|
49
55
|
process.exit(1);
|
|
50
56
|
}
|
|
51
|
-
CLIWallet.fromCredentials(credentials);
|
|
57
|
+
const wallet = CLIWallet.fromCredentials(credentials);
|
|
52
58
|
this.logger.success('Wallet loaded');
|
|
53
59
|
|
|
54
60
|
// Get package info
|
|
@@ -128,19 +134,50 @@ export class DeprecateCommand extends BaseCommand {
|
|
|
128
134
|
}
|
|
129
135
|
}
|
|
130
136
|
|
|
137
|
+
// Check wallet balance
|
|
138
|
+
this.logger.info('Checking wallet balance...');
|
|
139
|
+
const { sufficient, balance } = await checkBalance(wallet, network);
|
|
140
|
+
if (!sufficient) {
|
|
141
|
+
this.logger.fail('Insufficient balance');
|
|
142
|
+
this.logger.error(`Wallet balance: ${formatSats(balance)}`);
|
|
143
|
+
this.logger.error('Please fund your wallet before deprecating.');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
this.logger.success(`Wallet balance: ${formatSats(balance)}`);
|
|
147
|
+
|
|
131
148
|
// Execute deprecation
|
|
132
149
|
this.logger.info('Deprecating version...');
|
|
133
|
-
this.logger.warn('Deprecation transaction required.');
|
|
134
|
-
this.logger.log('Transaction would call: deprecateVersion(');
|
|
135
|
-
this.logger.log(` packageName: "${packageName}",`);
|
|
136
|
-
this.logger.log(` version: "${targetVersion}",`);
|
|
137
|
-
this.logger.log(` reason: "${message}"`);
|
|
138
|
-
this.logger.log(')');
|
|
139
|
-
this.logger.info('Deprecation (transaction pending)');
|
|
140
150
|
|
|
151
|
+
const sender = getWalletAddress(wallet);
|
|
152
|
+
const contract = getRegistryContract(network, sender);
|
|
153
|
+
const txParams = buildTransactionParams(wallet, network);
|
|
154
|
+
|
|
155
|
+
const deprecateResult = await contract.deprecateVersion(
|
|
156
|
+
packageName,
|
|
157
|
+
targetVersion,
|
|
158
|
+
message,
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
if (deprecateResult.revert) {
|
|
162
|
+
this.logger.fail('Deprecation would fail');
|
|
163
|
+
this.logger.error(`Reason: ${deprecateResult.revert}`);
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (deprecateResult.estimatedGas) {
|
|
168
|
+
this.logger.info(`Estimated gas: ${deprecateResult.estimatedGas} sats`);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const receipt = await deprecateResult.sendTransaction(txParams);
|
|
172
|
+
|
|
173
|
+
this.logger.log('');
|
|
174
|
+
this.logger.success('Version deprecated successfully!');
|
|
141
175
|
this.logger.log('');
|
|
142
|
-
this.logger.
|
|
143
|
-
this.logger.
|
|
176
|
+
this.logger.log(`Package: ${packageName}`);
|
|
177
|
+
this.logger.log(`Version: ${targetVersion}`);
|
|
178
|
+
this.logger.log(`Reason: ${message}`);
|
|
179
|
+
this.logger.log(`Transaction ID: ${receipt.transactionId}`);
|
|
180
|
+
this.logger.log(`Fees paid: ${formatSats(receipt.estimatedFees)}`);
|
|
144
181
|
this.logger.log('');
|
|
145
182
|
} catch (error) {
|
|
146
183
|
this.logger.fail('Deprecation failed');
|