@jpool/bond-cli 1.2.0-next.0 → 1.2.0-next.2
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 +36 -7
- package/dist/cli.js +174 -87
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Example:
|
|
|
52
52
|
Add additional collateral to an existing validator bond.
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
pnpm jbond topup
|
|
55
|
+
pnpm jbond topup <vote-account> <amount> -k <path>
|
|
56
56
|
|
|
57
57
|
Arguments:
|
|
58
58
|
vote-account Vote account public key
|
|
@@ -63,15 +63,15 @@ Options:
|
|
|
63
63
|
-c, --cluster <CLUSTER_NAME> Solana cluster(devnet or mainnet-beta)
|
|
64
64
|
|
|
65
65
|
Example:
|
|
66
|
-
pnpm jbond topup
|
|
66
|
+
pnpm jbond topup 686JcEJ98r8fMtUiVuKiz4WRoBpJ2Sm9zMhdc2b6H4bu 50 -c mainnet-beta
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
### Withdraw Collateral
|
|
70
70
|
|
|
71
|
-
Withdraw collateral from validator bond account.
|
|
71
|
+
Withdraw collateral from a validator bond account to a specified destination address.
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
pnpm jbond withdraw
|
|
74
|
+
pnpm jbond withdraw <vote-account> <destination> <amount> [options]
|
|
75
75
|
|
|
76
76
|
Arguments:
|
|
77
77
|
vote-account Vote account public key
|
|
@@ -83,13 +83,42 @@ Options:
|
|
|
83
83
|
-c, --cluster <CLUSTER_NAME> Solana cluster(devnet or mainnet-beta)
|
|
84
84
|
|
|
85
85
|
Example:
|
|
86
|
-
pnpm jbond withdraw
|
|
86
|
+
pnpm jbond withdraw 686JcEJ98r8fMtUiVuKiz4WRoBpJ2Sm9zMhdc2b6H4bu 3K2coMGaZhrSkyF52wUBUXBeRBRpGLnmB3znzLRKjgiP 25 -c mainnet-beta
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
**Requirements**:
|
|
90
90
|
|
|
91
91
|
Only the validator identity or withdrawal authority can execute withdrawals. The validator bond account must have sufficient collateral
|
|
92
92
|
|
|
93
|
+
### Set Withdrawal Authority
|
|
94
|
+
|
|
95
|
+
Set or update the withdrawal authority for a validator bond account. This allows delegating withdrawal permissions to another address.
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pnpm jbond set-withdraw-authority <vote-account> [options]
|
|
99
|
+
|
|
100
|
+
Arguments:
|
|
101
|
+
vote-account Vote account public key
|
|
102
|
+
|
|
103
|
+
Options:
|
|
104
|
+
-k, --keypair <path> Path to keypair file (default: ~/.config/solana/id.json)
|
|
105
|
+
-w, --new-authority <pubkey> New withdrawal authority (omit to remove authority)
|
|
106
|
+
-c, --cluster <CLUSTER_NAME> Solana cluster(devnet or mainnet-beta)
|
|
107
|
+
|
|
108
|
+
Examples:
|
|
109
|
+
# Set a withdrawal authority
|
|
110
|
+
pnpm jbond set-withdraw-authority 686JcEJ98r8fMtUiVuKiz4WRoBpJ2Sm9zMhdc2b6H4bu -w 9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin -c mainnet-beta
|
|
111
|
+
|
|
112
|
+
# Remove withdrawal authority (revert to identity-only)
|
|
113
|
+
pnpm jbond set-withdraw-authority 686JcEJ98r8fMtUiVuKiz4WRoBpJ2Sm9zMhdc2b6H4bu -c mainnet-beta
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Requirements**:
|
|
117
|
+
|
|
118
|
+
- Only the validator identity can set or update the withdrawal authority
|
|
119
|
+
- When a withdrawal authority is set, only that authority (or validator identity) can withdraw collateral
|
|
120
|
+
- Omitting the `--new-authority` option removes the withdrawal authority, reverting to identity-only withdrawals
|
|
121
|
+
|
|
93
122
|
### Claim Compensation
|
|
94
123
|
|
|
95
124
|
Claim compensation from a validator's collateral to the reserve (authority only).
|
|
@@ -195,7 +224,7 @@ pnpm jbond register-validator GHRvDXj9BfACkJ9CoLWbpi2UkMVti9DwXJGsaFT9XDcD 100
|
|
|
195
224
|
pnpm jbond validator-info GHRvDXj9BfACkJ9CoLWbpi2UkMVti9DwXJGsaFT9XDcD -c mainnet-beta
|
|
196
225
|
|
|
197
226
|
# 4. Top up with additional 50 SOL
|
|
198
|
-
pnpm jbond topup
|
|
227
|
+
pnpm jbond topup GHRvDXj9BfACkJ9CoLWbpi2UkMVti9DwXJGsaFT9XDcD 50 -c mainnet-beta
|
|
199
228
|
```
|
|
200
229
|
|
|
201
230
|
### Authority Operations
|
|
@@ -231,4 +260,4 @@ Common errors and solutions:
|
|
|
231
260
|
### `Account already in use`
|
|
232
261
|
|
|
233
262
|
- The validator is already registered
|
|
234
|
-
- Use `topup
|
|
263
|
+
- Use `topup` to add more funds instead
|
package/dist/cli.js
CHANGED
|
@@ -5,6 +5,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
8
12
|
var __copyProps = (to, from, except, desc) => {
|
|
9
13
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
14
|
for (let key of __getOwnPropNames(from))
|
|
@@ -21,8 +25,14 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
25
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
26
|
mod
|
|
23
27
|
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
24
29
|
|
|
25
30
|
// src/cli.ts
|
|
31
|
+
var cli_exports = {};
|
|
32
|
+
__export(cli_exports, {
|
|
33
|
+
parseCollateralType: () => parseCollateralType
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(cli_exports);
|
|
26
36
|
var import_web32 = require("@solana/web3.js");
|
|
27
37
|
var import_chalk = __toESM(require("chalk"));
|
|
28
38
|
var import_commander = require("commander");
|
|
@@ -81,10 +91,10 @@ function resolveKeypair(path) {
|
|
|
81
91
|
}
|
|
82
92
|
|
|
83
93
|
// package.json
|
|
84
|
-
var version = "1.
|
|
94
|
+
var version = "1.2.0-next.1";
|
|
85
95
|
|
|
86
96
|
// src/cli.ts
|
|
87
|
-
import_commander.program.name("jbond").description("CLI to interact with the JPool Bond program").version(process.env.VERSION ?? version).allowExcessArguments(false).option("-c, --cluster <CLUSTER>", "Solana cluster or RPC URL").option("-k, --keypair <KEYPAIR>", "Filepath to Solana keypair").hook("preAction", async (command) => {
|
|
97
|
+
import_commander.program.name("jbond").description("CLI to interact with the JPool Bond program").version(process.env.VERSION ?? version).allowExcessArguments(false).option("-c, --cluster <CLUSTER>", "Solana cluster or RPC URL").option("-k, --keypair <KEYPAIR>", "Filepath to Solana keypair").option("-b, --bond-type <TYPE>", "Bond type: performance | crowdfunding", "performance").option("-n , --bond-name <name>", "Bond name").hook("preAction", async (command) => {
|
|
88
98
|
const opts = command.opts();
|
|
89
99
|
const { provider, client } = initContext(opts);
|
|
90
100
|
console.log(import_chalk.default.dim(`# Version: ${command.version()}`));
|
|
@@ -95,50 +105,32 @@ import_commander.program.name("jbond").description("CLI to interact with the JPo
|
|
|
95
105
|
}).hook("postAction", (_c) => {
|
|
96
106
|
process.exit();
|
|
97
107
|
});
|
|
98
|
-
import_commander.program.command("
|
|
108
|
+
import_commander.program.command("global-initialize").description("Initialize global state").option("-w, --authority <pubkey>", "Authority (defaults to signer)").action(async (opts) => {
|
|
109
|
+
const spinner = (0, import_ora.default)("Initializing global state...").start();
|
|
99
110
|
const { client, provider } = useContext();
|
|
100
111
|
try {
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
console.log(import_chalk.default.cyan("====== Global State: ======\n"));
|
|
107
|
-
console.log(import_chalk.default.white(` Authority: ${state.authority}`));
|
|
108
|
-
console.log(import_chalk.default.white(` Reserve: ${state.reserve}`));
|
|
109
|
-
console.log(import_chalk.default.white(` Total Validators: ${state.totalValidators}`));
|
|
110
|
-
console.log(import_chalk.default.white(` Total Compensation Amount: ${state.totalCompensationAmount.toString()}`));
|
|
111
|
-
const epochInfo = await provider.connection.getEpochInfo();
|
|
112
|
-
console.log(import_chalk.default.white(` Current Epoch: ${epochInfo.epoch}`));
|
|
113
|
-
console.log(import_chalk.default.cyan("\n====== Validators: ======\n"));
|
|
114
|
-
const bonds = await client.program.account.validatorBond.all();
|
|
115
|
-
const publicKeys = bonds.map((b) => b.publicKey);
|
|
116
|
-
const bondAccounts = await provider.connection.getMultipleAccountsInfo(publicKeys);
|
|
117
|
-
const bondBalances = bondAccounts.map((acc) => acc?.lamports ?? 0);
|
|
118
|
-
if (bonds.length === 0) {
|
|
119
|
-
console.log(import_chalk.default.dim("No validators found"));
|
|
120
|
-
} else {
|
|
121
|
-
bonds.forEach((b, i) => {
|
|
122
|
-
console.log(import_chalk.default.magenta(prettyJson({
|
|
123
|
-
balance: `${bondBalances[i] / import_web32.LAMPORTS_PER_SOL} SOL`,
|
|
124
|
-
...b
|
|
125
|
-
})));
|
|
126
|
-
});
|
|
127
|
-
}
|
|
112
|
+
const authority = opts.authority ? new import_web32.PublicKey(opts.authority) : provider.wallet.publicKey;
|
|
113
|
+
const tx = await client.globalInitialize({ authority });
|
|
114
|
+
spinner.succeed(import_chalk.default.green("Global state initialized successfully!"));
|
|
115
|
+
console.log(import_chalk.default.gray(`Transaction: ${tx}`));
|
|
116
|
+
console.log(import_chalk.default.gray(`Authority: ${authority.toString()}`));
|
|
128
117
|
} catch (error) {
|
|
129
|
-
|
|
118
|
+
spinner.fail(import_chalk.default.red(`Failed to initialize global state: ${error}`));
|
|
130
119
|
process.exit(1);
|
|
131
120
|
}
|
|
132
121
|
});
|
|
133
|
-
import_commander.program.command("initialize").description("Initialize
|
|
134
|
-
const spinner = (0, import_ora.default)("Initializing
|
|
122
|
+
import_commander.program.command("initialize").description("Initialize specific bond project").requiredOption("-r, --reserve <address>", "Reserve vault address").requiredOption("-t, --collateral <type>", "Collateral type (sol | tokenMint:<address> | stakeAccount)").option("-w, --claim-authority <pubkey>", "Claim authority (defaults to signer)").action(async (opts) => {
|
|
123
|
+
const spinner = (0, import_ora.default)("Initializing bond project...").start();
|
|
135
124
|
const { client } = useContext();
|
|
136
125
|
const reserve = new import_web32.PublicKey(opts.reserve);
|
|
137
126
|
const authority = opts.claimAuthority ? new import_web32.PublicKey(opts.claimAuthority) : void 0;
|
|
127
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
128
|
+
const collateralType = parseCollateralType(opts.collateral);
|
|
129
|
+
const bondName = import_commander.program.opts().bondName;
|
|
130
|
+
console.log(import_chalk.default.gray(`Collateral Type: ${JSON.stringify(collateralType)}`));
|
|
138
131
|
try {
|
|
139
|
-
|
|
132
|
+
await client.bondInitialize({ bondType, name: bondName, authority, collateralType, reserve });
|
|
140
133
|
spinner.succeed(import_chalk.default.green(`Bond program initialized successfully!`));
|
|
141
|
-
console.log(import_chalk.default.gray(`Transaction: ${tx}`));
|
|
142
134
|
console.log(import_chalk.default.gray(`Reserve address: ${reserve.toString()}`));
|
|
143
135
|
} catch (error) {
|
|
144
136
|
spinner.fail(import_chalk.default.red(`Failed to initialize bond program: ${error}`));
|
|
@@ -147,37 +139,46 @@ import_commander.program.command("initialize").description("Initialize the globa
|
|
|
147
139
|
import_commander.program.command("register-validator").description("Register validator and fund initial collateral").argument("<vote-account>", "Vote account public key").argument("<amount>", "Initial collateral amount in SOL").action(async (voteAccountStr, amount) => {
|
|
148
140
|
const spinner = (0, import_ora.default)("Registering validator...").start();
|
|
149
141
|
const { keypair, client } = useContext();
|
|
142
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
143
|
+
const bondName = import_commander.program.opts().bondName;
|
|
150
144
|
try {
|
|
151
145
|
const voteAccount = new import_web32.PublicKey(voteAccountStr);
|
|
152
146
|
const initialCollateral = Number.parseFloat(amount);
|
|
153
|
-
if (Number.isNaN(initialCollateral) || initialCollateral
|
|
147
|
+
if (Number.isNaN(initialCollateral) || initialCollateral < 0) {
|
|
154
148
|
throw new Error("Invalid collateral amount");
|
|
155
149
|
}
|
|
156
|
-
|
|
150
|
+
await client.registerValidator({
|
|
151
|
+
bondType,
|
|
152
|
+
name: bondName,
|
|
157
153
|
voteAccount,
|
|
158
|
-
initialCollateral,
|
|
159
154
|
identity: keypair.publicKey
|
|
160
155
|
});
|
|
161
156
|
spinner.succeed(import_chalk.default.green(`Validator registered successfully!`));
|
|
162
|
-
console.log(import_chalk.default.gray(`
|
|
163
|
-
console.log(import_chalk.default.gray(`Initial collateral: ${initialCollateral} SOL`));
|
|
157
|
+
console.log(import_chalk.default.gray(`Initial collateral (ignored by register): ${initialCollateral} SOL`));
|
|
164
158
|
console.log(import_chalk.default.gray(`Validator: ${keypair.publicKey.toString()}`));
|
|
165
159
|
console.log(import_chalk.default.gray(`Vote Account: ${voteAccountStr}`));
|
|
166
160
|
} catch (error) {
|
|
167
161
|
spinner.fail(import_chalk.default.red(`Failed to register validator: ${error}`));
|
|
168
162
|
}
|
|
169
163
|
});
|
|
170
|
-
import_commander.program.command("topup
|
|
164
|
+
import_commander.program.command("topup").description("Top up collateral for validator bond account").argument("<vote-account>", "Vote account public key").argument("<amount>", "Amount to top up in SOL").action(async (voteAccountStr, amount) => {
|
|
171
165
|
const spinner = (0, import_ora.default)("Topping up collateral...").start();
|
|
172
166
|
const { client } = useContext();
|
|
167
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
168
|
+
const bondName = import_commander.program.opts().bondName;
|
|
173
169
|
try {
|
|
174
170
|
const voteAccount = new import_web32.PublicKey(voteAccountStr);
|
|
175
171
|
const topUpAmount = Number.parseFloat(amount);
|
|
176
172
|
if (Number.isNaN(topUpAmount) || topUpAmount <= 0) {
|
|
177
173
|
throw new Error("Invalid top-up amount");
|
|
178
174
|
}
|
|
179
|
-
const signature = await client.topUpCollateral({
|
|
180
|
-
|
|
175
|
+
const signature = await client.topUpCollateral({
|
|
176
|
+
bondType,
|
|
177
|
+
name: bondName,
|
|
178
|
+
voteAccount,
|
|
179
|
+
collateral: { amount: topUpAmount }
|
|
180
|
+
});
|
|
181
|
+
spinner.succeed(import_chalk.default.green(`Collateral topped up successfully for bond type ${import_commander.program.opts().bondType}!`));
|
|
181
182
|
console.log(import_chalk.default.gray(`Signature: ${signature}`));
|
|
182
183
|
console.log(import_chalk.default.gray(`Top-up amount: ${topUpAmount} SOL`));
|
|
183
184
|
} catch (error) {
|
|
@@ -185,9 +186,11 @@ import_commander.program.command("topup-collateral").description("Top up collate
|
|
|
185
186
|
process.exit(1);
|
|
186
187
|
}
|
|
187
188
|
});
|
|
188
|
-
import_commander.program.command("withdraw
|
|
189
|
+
import_commander.program.command("withdraw").description("Withdraw collateral from validator bond account").argument("<vote-account>", "Vote account public key").argument("<destination>", "Destination address for withdrawn funds").argument("<amount>", "Amount to withdraw in SOL").action(async (voteAccountStr, destinationStr, amount) => {
|
|
189
190
|
const spinner = (0, import_ora.default)("Withdrawing collateral...").start();
|
|
190
191
|
const { client } = useContext();
|
|
192
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
193
|
+
const bondName = import_commander.program.opts().bondName;
|
|
191
194
|
try {
|
|
192
195
|
const voteAccount = new import_web32.PublicKey(voteAccountStr);
|
|
193
196
|
const destination = new import_web32.PublicKey(destinationStr);
|
|
@@ -195,11 +198,17 @@ import_commander.program.command("withdraw-collateral").description("Withdraw co
|
|
|
195
198
|
if (Number.isNaN(withdrawAmount) || withdrawAmount <= 0) {
|
|
196
199
|
throw new Error("Invalid withdrawal amount");
|
|
197
200
|
}
|
|
198
|
-
const
|
|
199
|
-
if (!
|
|
201
|
+
const bond = await client.getValidatorBond(bondType, bondName, voteAccount);
|
|
202
|
+
if (!bond) {
|
|
200
203
|
throw new Error("Validator bond account not found");
|
|
201
204
|
}
|
|
202
|
-
const tx = await client.withdrawCollateral({
|
|
205
|
+
const tx = await client.withdrawCollateral({
|
|
206
|
+
bondType,
|
|
207
|
+
name: bondName,
|
|
208
|
+
voteAccount,
|
|
209
|
+
destination,
|
|
210
|
+
withdraw: { amount: withdrawAmount }
|
|
211
|
+
});
|
|
203
212
|
spinner.succeed(import_chalk.default.green(`Collateral withdrawn successfully!`));
|
|
204
213
|
console.log(import_chalk.default.gray(`Transaction: ${tx}`));
|
|
205
214
|
console.log(import_chalk.default.gray(`Amount withdrawn: ${withdrawAmount} SOL`));
|
|
@@ -212,6 +221,8 @@ import_commander.program.command("withdraw-collateral").description("Withdraw co
|
|
|
212
221
|
import_commander.program.command("claim-compensation").description("Claim compensation from validator to reserve").argument("<vote-account>", "Vote account public key").argument("<amount>", "Amount to withdraw in SOL").action(async (voteAccountStr, amount) => {
|
|
213
222
|
const spinner = (0, import_ora.default)("Claiming compensation...").start();
|
|
214
223
|
const { client } = useContext();
|
|
224
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
225
|
+
const bondName = import_commander.program.opts().bondName;
|
|
215
226
|
try {
|
|
216
227
|
const voteAccount = new import_web32.PublicKey(voteAccountStr);
|
|
217
228
|
const withdrawAmount = Number.parseFloat(amount);
|
|
@@ -219,8 +230,12 @@ import_commander.program.command("claim-compensation").description("Claim compen
|
|
|
219
230
|
throw new Error("Invalid withdrawal amount");
|
|
220
231
|
}
|
|
221
232
|
const tx = await client.claimCompensation({
|
|
233
|
+
bondType,
|
|
234
|
+
name: bondName,
|
|
222
235
|
voteAccount,
|
|
223
|
-
|
|
236
|
+
claim: {
|
|
237
|
+
amount: withdrawAmount
|
|
238
|
+
}
|
|
224
239
|
});
|
|
225
240
|
spinner.succeed(import_chalk.default.green(`Compensation withdrawn successfully!`));
|
|
226
241
|
console.log(import_chalk.default.gray(`Transaction: ${tx}`));
|
|
@@ -232,31 +247,31 @@ import_commander.program.command("claim-compensation").description("Claim compen
|
|
|
232
247
|
});
|
|
233
248
|
import_commander.program.command("validator-info").description("Get validator bond account information").argument("<vote-account>", "Vote account public key").option("-v, --validator <pubkey>", "Validator public key (optional, defaults to current keypair)").action(async (voteAccountStr) => {
|
|
234
249
|
const { client } = useContext();
|
|
250
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
251
|
+
const bondName = import_commander.program.opts().bondName;
|
|
235
252
|
try {
|
|
236
253
|
const voteAccount = new import_web32.PublicKey(voteAccountStr);
|
|
237
|
-
const [validatorBondAddress] = client.pda.validatorBond(voteAccount);
|
|
254
|
+
const [validatorBondAddress] = client.pda.validatorBond(bondType, bondName, voteAccount);
|
|
238
255
|
console.log(import_chalk.default.gray(`Validator Bond Address: ${validatorBondAddress.toString()}`));
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
);
|
|
242
|
-
if (!state) {
|
|
256
|
+
const bond = await client.getValidatorBond(bondType, bondName, voteAccount);
|
|
257
|
+
if (!bond) {
|
|
243
258
|
console.log(import_chalk.default.yellow("Validator bond account not found"));
|
|
244
259
|
return;
|
|
245
260
|
}
|
|
246
261
|
console.log(import_chalk.default.cyan("\nValidator Bond Account Information:"));
|
|
247
|
-
console.log(import_chalk.default.white(` Validator: ${
|
|
248
|
-
console.log(import_chalk.default.white(` Vote Account: ${
|
|
249
|
-
if (
|
|
250
|
-
console.log(import_chalk.default.white(` Withdrawal Authority: ${
|
|
262
|
+
console.log(import_chalk.default.white(` Validator: ${bond.identity}`));
|
|
263
|
+
console.log(import_chalk.default.white(` Vote Account: ${bond.voteAccount}`));
|
|
264
|
+
if (bond.withdrawalAuthority) {
|
|
265
|
+
console.log(import_chalk.default.white(` Withdrawal Authority: ${bond.withdrawalAuthority}`));
|
|
251
266
|
} else {
|
|
252
267
|
console.log(import_chalk.default.white(` Withdrawal Authority: Not set (identity only)`));
|
|
253
268
|
}
|
|
254
269
|
console.log(
|
|
255
270
|
import_chalk.default.white(
|
|
256
|
-
` Active: ${
|
|
271
|
+
` Active: ${bond.isActive ? import_chalk.default.green("Yes") : import_chalk.default.red("No")}`
|
|
257
272
|
)
|
|
258
273
|
);
|
|
259
|
-
console.log(import_chalk.default.white(` Created At: ${
|
|
274
|
+
console.log(import_chalk.default.white(` Created At: ${bond.createdAt}`));
|
|
260
275
|
} catch (error) {
|
|
261
276
|
console.error(import_chalk.default.red(`Failed to get validator info: ${error}`));
|
|
262
277
|
process.exit(1);
|
|
@@ -265,9 +280,11 @@ import_commander.program.command("validator-info").description("Get validator bo
|
|
|
265
280
|
import_commander.program.command("set-withdraw-authority").description("Set or update withdrawal authority for validator bond").argument("<vote-account>", "Vote account public key").option("-w, --new-authority <pubkey>", "New withdrawal authority (omit to remove authority)").action(async (voteAccountStr, options) => {
|
|
266
281
|
const spinner = (0, import_ora.default)("Setting withdrawal authority...").start();
|
|
267
282
|
const { client, keypair } = useContext();
|
|
283
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
284
|
+
const bondName = import_commander.program.opts().bondName;
|
|
268
285
|
try {
|
|
269
286
|
const voteAccount = new import_web32.PublicKey(voteAccountStr);
|
|
270
|
-
const bondAccount = await client.getValidatorBond(voteAccount);
|
|
287
|
+
const bondAccount = await client.getValidatorBond(bondType, bondName, voteAccount);
|
|
271
288
|
if (!bondAccount) {
|
|
272
289
|
throw new Error("Validator bond account not found");
|
|
273
290
|
}
|
|
@@ -276,6 +293,8 @@ import_commander.program.command("set-withdraw-authority").description("Set or u
|
|
|
276
293
|
}
|
|
277
294
|
const newWithdrawAuthority = options.newAuthority ? new import_web32.PublicKey(options.newAuthority) : null;
|
|
278
295
|
const tx = await client.setWithdrawAuthority({
|
|
296
|
+
bondType,
|
|
297
|
+
name: bondName,
|
|
279
298
|
voteAccount,
|
|
280
299
|
newWithdrawAuthority
|
|
281
300
|
});
|
|
@@ -294,13 +313,17 @@ import_commander.program.command("set-withdraw-authority").description("Set or u
|
|
|
294
313
|
import_commander.program.command("configure").description("Update program configuration (authority and/or reserve)").option("-a, --new-authority <pubkey>", "New authority address").option("-r, --new-reserve <pubkey>", "New reserve address").action(async (opts) => {
|
|
295
314
|
const spinner = (0, import_ora.default)("Updating program configuration...").start();
|
|
296
315
|
const { client } = useContext();
|
|
316
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
317
|
+
const bondName = import_commander.program.opts().bondName;
|
|
297
318
|
try {
|
|
298
319
|
if (!opts.newAuthority && !opts.newReserve) {
|
|
299
320
|
throw new Error("At least one of --new-authority or --new-reserve must be provided");
|
|
300
321
|
}
|
|
301
322
|
const newAuthority = opts.newAuthority ? new import_web32.PublicKey(opts.newAuthority) : void 0;
|
|
302
323
|
const newReserve = opts.newReserve ? new import_web32.PublicKey(opts.newReserve) : void 0;
|
|
303
|
-
const tx = await client.
|
|
324
|
+
const tx = await client.bondConfigure({
|
|
325
|
+
bondType,
|
|
326
|
+
name: bondName,
|
|
304
327
|
newAuthority,
|
|
305
328
|
newReserve
|
|
306
329
|
});
|
|
@@ -317,6 +340,65 @@ import_commander.program.command("configure").description("Update program config
|
|
|
317
340
|
process.exit(1);
|
|
318
341
|
}
|
|
319
342
|
});
|
|
343
|
+
import_commander.program.command("get-bond-state").description("Get bond state information").action(async () => {
|
|
344
|
+
const { client } = useContext();
|
|
345
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
346
|
+
const bondName = import_commander.program.opts().bondName;
|
|
347
|
+
try {
|
|
348
|
+
const state = await client.getBondState(bondType, bondName);
|
|
349
|
+
if (!state) {
|
|
350
|
+
console.log(import_chalk.default.yellow("Bond state not found"));
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
console.log(import_chalk.default.cyan("====== Bond State: ======\n"));
|
|
354
|
+
console.log(import_chalk.default.white(JSON.stringify(state, null, 2)));
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.error(import_chalk.default.red(`Failed to get bond state info: ${error}`));
|
|
357
|
+
process.exit(1);
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
import_commander.program.command("start-bond").description("Start bond command").requiredOption("-d, --duration <seconds>", "Bond session duration in seconds").action(async (opts) => {
|
|
361
|
+
const spinner = (0, import_ora.default)("Starting bond...").start();
|
|
362
|
+
const { client } = useContext();
|
|
363
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
364
|
+
const bondName = import_commander.program.opts().bondName;
|
|
365
|
+
const duration = Number.parseInt(opts.duration, 10);
|
|
366
|
+
try {
|
|
367
|
+
const tx = await client.bondStart({ bondType, name: bondName, duration_secs: duration });
|
|
368
|
+
spinner.succeed(import_chalk.default.green(`Bond started successfully!`));
|
|
369
|
+
console.log(import_chalk.default.gray(`Transaction: ${tx}`));
|
|
370
|
+
} catch (error) {
|
|
371
|
+
spinner.fail(import_chalk.default.red(`Failed to start bond: ${error}`));
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
import_commander.program.command("finish-bond").description("Finish bond command").action(async () => {
|
|
376
|
+
const spinner = (0, import_ora.default)("Finishing bond...").start();
|
|
377
|
+
const { client } = useContext();
|
|
378
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
379
|
+
const bondName = import_commander.program.opts().bondName;
|
|
380
|
+
try {
|
|
381
|
+
const tx = await client.bondFinish({ bondType, name: bondName });
|
|
382
|
+
spinner.succeed(import_chalk.default.green(`Bond finished successfully!`));
|
|
383
|
+
console.log(import_chalk.default.gray(`Transaction: ${tx}`));
|
|
384
|
+
} catch (error) {
|
|
385
|
+
spinner.fail(import_chalk.default.red(`Failed to finish bond: ${error}`));
|
|
386
|
+
process.exit(1);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
import_commander.program.command("get-collateral-type").description("Get bond collateral type").action(async () => {
|
|
390
|
+
const { client } = useContext();
|
|
391
|
+
const bondType = parseBondType(import_commander.program.opts().bondType);
|
|
392
|
+
const bondName = import_commander.program.opts().bondName;
|
|
393
|
+
try {
|
|
394
|
+
const collateralType = await client.getBondCollateralType(bondType, bondName);
|
|
395
|
+
console.log(import_chalk.default.cyan("Collateral Type:"));
|
|
396
|
+
console.log(import_chalk.default.white(JSON.stringify(collateralType, null, 2)));
|
|
397
|
+
} catch (error) {
|
|
398
|
+
console.error(import_chalk.default.red(`Failed to get collateral type: ${error}`));
|
|
399
|
+
process.exit(1);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
320
402
|
import_commander.program.command("*", { isDefault: true, hidden: true }).allowExcessArguments(true).action(() => {
|
|
321
403
|
import_commander.program.help();
|
|
322
404
|
});
|
|
@@ -329,32 +411,37 @@ import_commander.program.parseAsync().catch((e) => {
|
|
|
329
411
|
}
|
|
330
412
|
process.exit();
|
|
331
413
|
});
|
|
332
|
-
function
|
|
333
|
-
const
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
414
|
+
function parseBondType(t) {
|
|
415
|
+
const x = (t || "").toLowerCase();
|
|
416
|
+
if (x === "crowdfunding") {
|
|
417
|
+
return { crowdfunding: {} };
|
|
418
|
+
}
|
|
419
|
+
if (x === "performance") {
|
|
420
|
+
return { performance: {} };
|
|
421
|
+
}
|
|
422
|
+
console.error(import_chalk.default.red(`Invalid bond type: ${t}`));
|
|
423
|
+
process.exit(1);
|
|
424
|
+
}
|
|
425
|
+
function parseCollateralType(input) {
|
|
426
|
+
if (input === "sol") {
|
|
427
|
+
return { native: {} };
|
|
428
|
+
} else if (input.startsWith("tokenMint:")) {
|
|
429
|
+
const parts = input.split(":");
|
|
430
|
+
if (parts.length !== 2) {
|
|
431
|
+
throw new Error("Invalid tokenMint format. Use tokenMint:<address>");
|
|
339
432
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
return value.map((item) => convertValue(item));
|
|
346
|
-
}
|
|
347
|
-
const converted2 = {};
|
|
348
|
-
for (const [k, v] of Object.entries(value)) {
|
|
349
|
-
if (omitKeys.includes(k)) {
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
converted2[k] = convertValue(v);
|
|
353
|
-
}
|
|
354
|
-
return converted2;
|
|
433
|
+
return { token: [new import_web32.PublicKey(parts[1])] };
|
|
434
|
+
} else if (input.startsWith("stakeAccount:")) {
|
|
435
|
+
const parts = input.split(":");
|
|
436
|
+
if (parts.length !== 2) {
|
|
437
|
+
throw new Error("Invalid stakeAccount format. Use stakeAccount:<address>");
|
|
355
438
|
}
|
|
356
|
-
return
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
|
|
439
|
+
return { stakeAccount: {} };
|
|
440
|
+
} else {
|
|
441
|
+
throw new Error("Unsupported collateral type. Use sol, tokenMint:<address>, or stakeAccount:<address>");
|
|
442
|
+
}
|
|
360
443
|
}
|
|
444
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
445
|
+
0 && (module.exports = {
|
|
446
|
+
parseCollateralType
|
|
447
|
+
});
|