@jpool/bond-cli 1.6.3 → 1.7.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/dist/cli.js +185 -107
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -6075,7 +6075,7 @@ function initContext({ cluster, env: env2, keypair }) {
|
|
|
6075
6075
|
const connection = new import_web3.Connection(rpcUrl, opts.commitment);
|
|
6076
6076
|
const wallet = new import_anchor.Wallet(resolveKeypair(keypair));
|
|
6077
6077
|
const provider = new import_anchor.AnchorProvider(connection, wallet, opts);
|
|
6078
|
-
const client = new import_bond_sdk.JBondClient(provider).env(env2);
|
|
6078
|
+
const client = new import_bond_sdk.JBondClient(provider, { debug: true }).env(env2);
|
|
6079
6079
|
context = {
|
|
6080
6080
|
cluster: cluster || "mainnet-beta",
|
|
6081
6081
|
keypair: wallet.payer,
|
|
@@ -6146,20 +6146,9 @@ function parseCollateralType(input) {
|
|
|
6146
6146
|
}
|
|
6147
6147
|
throw new Error("Invalid collateral type. Use: native | token:<mint> | stakeAccount");
|
|
6148
6148
|
}
|
|
6149
|
-
function parseBondType(type) {
|
|
6150
|
-
const normalized = (type || "").toLowerCase();
|
|
6151
|
-
if (normalized === "crowdfunding") {
|
|
6152
|
-
return { crowdfunding: {} };
|
|
6153
|
-
}
|
|
6154
|
-
if (normalized === "standard") {
|
|
6155
|
-
return { standard: {} };
|
|
6156
|
-
}
|
|
6157
|
-
console.error(source_default.red(`Invalid bond type: ${type}`));
|
|
6158
|
-
process.exit(1);
|
|
6159
|
-
}
|
|
6160
6149
|
|
|
6161
6150
|
// package.json
|
|
6162
|
-
var version = "1.
|
|
6151
|
+
var version = "1.7.0-next.2";
|
|
6163
6152
|
|
|
6164
6153
|
// src/cli.ts
|
|
6165
6154
|
var log = {
|
|
@@ -6171,7 +6160,7 @@ var log = {
|
|
|
6171
6160
|
`)),
|
|
6172
6161
|
json: (data, color) => console.log(source_default[color ?? "magenta"](JSON.stringify(data, null, 2)))
|
|
6173
6162
|
};
|
|
6174
|
-
import_commander.program.name("jbond").description("CLI to interact with the JPool Bond program").version(process.env.VERSION ?? version).option("-c, --cluster <cluster>", "Solana cluster (mainnet-beta, devnet, testnet) or RPC URL", process.env.CLUSTER ?? "mainnet-beta").option("-k, --keypair <path>", "Path to Solana keypair file").option("-b, --bond <name>", "Bond name
|
|
6163
|
+
import_commander.program.name("jbond").description("CLI to interact with the JPool Bond program").version(process.env.VERSION ?? version).option("-c, --cluster <cluster>", "Solana cluster (mainnet-beta, devnet, testnet) or RPC URL [env:CLUSTER]", process.env.CLUSTER ?? "mainnet-beta").option("-e, --env <env>", "JBond program environment: dev | prod [env:JBOND_ENV]", process.env.JBOND_ENV || "prod").option("-k, --keypair <path>", "Path to Solana keypair file [env:CLI_SOLANA_KEYPAIR] (default: ~/.config/solana/id.json)").option("-b, --bond <name>", "Bond name [env:JBOND_BOND]", process.env.JBOND_BOND).option("-t, --bond-type <type>", "Bond type: standard|crowdfunding", "standard").hook("preAction", async (command) => {
|
|
6175
6164
|
const opts = command.opts();
|
|
6176
6165
|
const { provider, client } = initContext(opts);
|
|
6177
6166
|
log.json({
|
|
@@ -6195,8 +6184,7 @@ import_commander.program.command("init").description("Initialize global bond pro
|
|
|
6195
6184
|
});
|
|
6196
6185
|
} catch (error2) {
|
|
6197
6186
|
spinner.fail("Failed to initialize global state");
|
|
6198
|
-
|
|
6199
|
-
process.exit(1);
|
|
6187
|
+
throw error2;
|
|
6200
6188
|
}
|
|
6201
6189
|
});
|
|
6202
6190
|
var bond = import_commander.program.command("bond").description("Manage bond projects");
|
|
@@ -6206,7 +6194,7 @@ bond.command("init <name>").description("Initialize a new bond project").option(
|
|
|
6206
6194
|
try {
|
|
6207
6195
|
const reserve = opts.reserve ? new import_web33.PublicKey(opts.reserve) : keypair.publicKey;
|
|
6208
6196
|
const authority = opts.authority ? new import_web33.PublicKey(opts.authority) : void 0;
|
|
6209
|
-
const bondType =
|
|
6197
|
+
const bondType = getBondType();
|
|
6210
6198
|
const collateralType = parseCollateralType(opts.collateral);
|
|
6211
6199
|
await client.bondInitialize({ bondType, name, authority, collateralType, reserve });
|
|
6212
6200
|
spinner.succeed("Bond initialized");
|
|
@@ -6217,14 +6205,13 @@ bond.command("init <name>").description("Initialize a new bond project").option(
|
|
|
6217
6205
|
});
|
|
6218
6206
|
} catch (error2) {
|
|
6219
6207
|
spinner.fail("Failed to initialize bond");
|
|
6220
|
-
|
|
6221
|
-
process.exit(1);
|
|
6208
|
+
throw error2;
|
|
6222
6209
|
}
|
|
6223
6210
|
});
|
|
6224
|
-
bond.command("
|
|
6211
|
+
bond.command("configure").description("Update bond configuration").option("-a, --authority <pubkey>", "New authority address").option("-r, --reserve <pubkey>", "New reserve address").action(async (opts) => {
|
|
6225
6212
|
const spinner = ora("Updating bond configuration").start();
|
|
6226
6213
|
const { client } = useContext();
|
|
6227
|
-
const bondType =
|
|
6214
|
+
const bondType = getBondType();
|
|
6228
6215
|
const bondName = getBondName();
|
|
6229
6216
|
try {
|
|
6230
6217
|
if (!opts.authority && !opts.reserve) {
|
|
@@ -6241,75 +6228,111 @@ bond.command("config").description("Update bond configuration").option("-a, --au
|
|
|
6241
6228
|
spinner.succeed("Bond configuration updated");
|
|
6242
6229
|
const details = {};
|
|
6243
6230
|
if (newAuthority) {
|
|
6244
|
-
details.
|
|
6231
|
+
details.newAuthority = newAuthority.toString();
|
|
6245
6232
|
}
|
|
6246
6233
|
if (newReserve) {
|
|
6247
|
-
details.
|
|
6234
|
+
details.newReserve = newReserve.toString();
|
|
6248
6235
|
}
|
|
6249
6236
|
details.transaction = tx;
|
|
6250
6237
|
log.json(details);
|
|
6251
6238
|
} catch (error2) {
|
|
6252
6239
|
spinner.fail("Failed to update bond configuration");
|
|
6253
|
-
|
|
6254
|
-
process.exit(1);
|
|
6240
|
+
throw error2;
|
|
6255
6241
|
}
|
|
6256
6242
|
});
|
|
6257
6243
|
bond.command("info").description("Show bond state information").action(async () => {
|
|
6258
6244
|
const { client } = useContext();
|
|
6259
|
-
const bondType =
|
|
6245
|
+
const bondType = getBondType();
|
|
6246
|
+
const bondName = getBondName();
|
|
6247
|
+
const state = await client.getBondState(bondType, bondName);
|
|
6248
|
+
if (!state) {
|
|
6249
|
+
log.warn("Bond state not found");
|
|
6250
|
+
return;
|
|
6251
|
+
}
|
|
6252
|
+
log.header("Bond State Information");
|
|
6253
|
+
log.json(state);
|
|
6254
|
+
});
|
|
6255
|
+
bond.command("list").description("List all bond states").action(async () => {
|
|
6256
|
+
const { client } = useContext();
|
|
6257
|
+
const bondType = getBondType();
|
|
6258
|
+
const states = await client.getAllBondStates(bondType);
|
|
6259
|
+
if (states.length === 0) {
|
|
6260
|
+
log.warn("No bond states found");
|
|
6261
|
+
return;
|
|
6262
|
+
}
|
|
6263
|
+
log.header(`Found ${states.length} bond state(s)
|
|
6264
|
+
`);
|
|
6265
|
+
states.forEach((state, index) => {
|
|
6266
|
+
log.info(`Bond ${index + 1}:`);
|
|
6267
|
+
log.json(state);
|
|
6268
|
+
console.log("");
|
|
6269
|
+
});
|
|
6270
|
+
});
|
|
6271
|
+
bond.command("claim-all").description("Claim compensations from all validator bonds to reserve").action(async () => {
|
|
6272
|
+
const spinner = ora("Claiming all compensations").start();
|
|
6273
|
+
const { client, keypair, provider } = useContext();
|
|
6274
|
+
const bondType = getBondType();
|
|
6260
6275
|
const bondName = getBondName();
|
|
6276
|
+
const BATCH_SIZE = 10;
|
|
6261
6277
|
try {
|
|
6262
|
-
const
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6278
|
+
const ix = await client.getClaimAllCompensationsIxs({
|
|
6279
|
+
bondType,
|
|
6280
|
+
name: bondName,
|
|
6281
|
+
authority: keypair.publicKey
|
|
6282
|
+
});
|
|
6283
|
+
console.log(`Total claims to process: ${ix.length}`);
|
|
6284
|
+
for (let i = 0; i < ix.length; i += BATCH_SIZE) {
|
|
6285
|
+
const chunk = ix.slice(i, i + BATCH_SIZE);
|
|
6286
|
+
const tx = await provider.connection.sendTransaction(new import_web33.Transaction().add(...chunk), [keypair]);
|
|
6287
|
+
log.info(`Processed batch ${i / BATCH_SIZE + 1}: ${chunk.length} claims (tx: ${tx})`);
|
|
6266
6288
|
}
|
|
6267
|
-
|
|
6268
|
-
log.json(state);
|
|
6289
|
+
spinner.succeed("All compensations claimed");
|
|
6269
6290
|
} catch (error2) {
|
|
6270
|
-
|
|
6271
|
-
|
|
6291
|
+
spinner.fail("Failed to claim all compensations");
|
|
6292
|
+
throw error2;
|
|
6272
6293
|
}
|
|
6273
6294
|
});
|
|
6274
|
-
bond.command("
|
|
6295
|
+
bond.command("balances").description("Show total collateral balances for bond").action(async () => {
|
|
6275
6296
|
const { client } = useContext();
|
|
6276
|
-
const bondType =
|
|
6297
|
+
const bondType = getBondType();
|
|
6298
|
+
const bondName = getBondName();
|
|
6277
6299
|
try {
|
|
6278
|
-
const
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
log.json(state);
|
|
6288
|
-
console.log("");
|
|
6300
|
+
const validatorBalances = await client.getBondStateValidatorBondBalances(bondType, bondName);
|
|
6301
|
+
log.header("Bond Total Validator Collateral Balance");
|
|
6302
|
+
log.json({
|
|
6303
|
+
bond: bondName,
|
|
6304
|
+
bondType,
|
|
6305
|
+
validatorBalances: validatorBalances.map((vb) => ({
|
|
6306
|
+
voteAccount: vb.voteAccount.toString(),
|
|
6307
|
+
balance: `${lamportsToSol(vb.balance)}`
|
|
6308
|
+
}))
|
|
6289
6309
|
});
|
|
6290
6310
|
} catch (error2) {
|
|
6291
|
-
|
|
6292
|
-
process.exit(1);
|
|
6311
|
+
throw new Error(`Failed to get bond balances: ${error2}`);
|
|
6293
6312
|
}
|
|
6294
6313
|
});
|
|
6295
|
-
bond.command("
|
|
6296
|
-
const
|
|
6297
|
-
const
|
|
6314
|
+
bond.command("remove").description("Remove bond state").action(async () => {
|
|
6315
|
+
const spinner = ora("Removing bond state").start();
|
|
6316
|
+
const { client, keypair } = useContext();
|
|
6317
|
+
const bondType = getBondType();
|
|
6298
6318
|
const bondName = getBondName();
|
|
6299
6319
|
try {
|
|
6300
|
-
const
|
|
6301
|
-
|
|
6302
|
-
log.json(
|
|
6320
|
+
const tx = await client.bondRemove({ bondType, name: bondName, authority: keypair.publicKey });
|
|
6321
|
+
spinner.succeed("Bond state removed");
|
|
6322
|
+
log.json({
|
|
6323
|
+
name: bondName,
|
|
6324
|
+
transaction: tx
|
|
6325
|
+
});
|
|
6303
6326
|
} catch (error2) {
|
|
6304
|
-
|
|
6305
|
-
|
|
6327
|
+
spinner.fail("Failed to remove bond state");
|
|
6328
|
+
throw error2;
|
|
6306
6329
|
}
|
|
6307
6330
|
});
|
|
6308
6331
|
var validator = import_commander.program.command("validator").description("Manage validator bonds");
|
|
6309
6332
|
validator.command("register <vote>").description("Register validator and create bond account").action(async (vote) => {
|
|
6310
6333
|
const spinner = ora("Registering validator").start();
|
|
6311
6334
|
const { keypair, client } = useContext();
|
|
6312
|
-
const bondType =
|
|
6335
|
+
const bondType = getBondType();
|
|
6313
6336
|
const bondName = getBondName();
|
|
6314
6337
|
try {
|
|
6315
6338
|
const voteAccount = new import_web33.PublicKey(vote);
|
|
@@ -6326,19 +6349,18 @@ validator.command("register <vote>").description("Register validator and create
|
|
|
6326
6349
|
});
|
|
6327
6350
|
} catch (error2) {
|
|
6328
6351
|
spinner.fail("Failed to register validator");
|
|
6329
|
-
|
|
6330
|
-
process.exit(1);
|
|
6352
|
+
throw error2;
|
|
6331
6353
|
}
|
|
6332
6354
|
});
|
|
6333
|
-
validator.command("topup <vote> <amount>").description("Add collateral to validator bond account").action(async (vote,
|
|
6355
|
+
validator.command("topup <vote> <amount>").description("Add collateral to validator bond account").action(async (vote, amountStr) => {
|
|
6334
6356
|
const spinner = ora("Adding collateral").start();
|
|
6335
6357
|
const { client, keypair } = useContext();
|
|
6336
|
-
const bondType =
|
|
6358
|
+
const bondType = getBondType();
|
|
6337
6359
|
const bondName = getBondName();
|
|
6338
6360
|
try {
|
|
6339
6361
|
const voteAccount = new import_web33.PublicKey(vote);
|
|
6340
|
-
const
|
|
6341
|
-
if (Number.isNaN(
|
|
6362
|
+
const amount = Number.parseFloat(amountStr);
|
|
6363
|
+
if (Number.isNaN(amount) || amount <= 0) {
|
|
6342
6364
|
throw new Error("Invalid amount: must be positive number");
|
|
6343
6365
|
}
|
|
6344
6366
|
const signature = await client.topUpCollateral({
|
|
@@ -6346,29 +6368,28 @@ validator.command("topup <vote> <amount>").description("Add collateral to valida
|
|
|
6346
6368
|
name: bondName,
|
|
6347
6369
|
identity: keypair.publicKey,
|
|
6348
6370
|
voteAccount,
|
|
6349
|
-
|
|
6371
|
+
amount
|
|
6350
6372
|
});
|
|
6351
6373
|
spinner.succeed("Collateral added");
|
|
6352
6374
|
log.json({
|
|
6353
|
-
amount: `${
|
|
6375
|
+
amount: `${amount} SOL`,
|
|
6354
6376
|
transaction: signature
|
|
6355
6377
|
});
|
|
6356
6378
|
} catch (error2) {
|
|
6357
6379
|
spinner.fail("Failed to add collateral");
|
|
6358
|
-
|
|
6359
|
-
process.exit(1);
|
|
6380
|
+
throw error2;
|
|
6360
6381
|
}
|
|
6361
6382
|
});
|
|
6362
|
-
validator.command("withdraw <vote
|
|
6383
|
+
validator.command("withdraw <vote> <amount> <destination>").description("Withdraw collateral from validator bond account").action(async (voteAccountStr, amountStr, destinationStr) => {
|
|
6363
6384
|
const spinner = ora("Withdrawing collateral").start();
|
|
6364
6385
|
const { client } = useContext();
|
|
6365
|
-
const bondType =
|
|
6386
|
+
const bondType = getBondType();
|
|
6366
6387
|
const bondName = getBondName();
|
|
6367
6388
|
try {
|
|
6368
6389
|
const voteAccount = new import_web33.PublicKey(voteAccountStr);
|
|
6369
6390
|
const destination = new import_web33.PublicKey(destinationStr);
|
|
6370
|
-
const
|
|
6371
|
-
if (Number.isNaN(
|
|
6391
|
+
const amount = Number.parseFloat(amountStr);
|
|
6392
|
+
if (Number.isNaN(amount) || amount <= 0) {
|
|
6372
6393
|
throw new Error("Invalid amount: must be positive number");
|
|
6373
6394
|
}
|
|
6374
6395
|
const bond2 = await client.getValidatorBond(bondType, bondName, voteAccount);
|
|
@@ -6380,51 +6401,49 @@ validator.command("withdraw <vote-account> <amount> <destination>").description(
|
|
|
6380
6401
|
name: bondName,
|
|
6381
6402
|
voteAccount,
|
|
6382
6403
|
destination,
|
|
6383
|
-
|
|
6404
|
+
amount
|
|
6384
6405
|
});
|
|
6385
6406
|
spinner.succeed("Collateral withdrawn");
|
|
6386
6407
|
log.json({
|
|
6387
|
-
amount: `${
|
|
6408
|
+
amount: `${amount} SOL`,
|
|
6388
6409
|
destination: destinationStr,
|
|
6389
6410
|
transaction: tx
|
|
6390
6411
|
});
|
|
6391
6412
|
} catch (error2) {
|
|
6392
6413
|
spinner.fail("Failed to withdraw collateral");
|
|
6393
|
-
|
|
6394
|
-
process.exit(1);
|
|
6414
|
+
throw error2;
|
|
6395
6415
|
}
|
|
6396
6416
|
});
|
|
6397
|
-
validator.command("claim <vote> <amount>").description("Claim collateral from validator to reserve").action(async (vote,
|
|
6417
|
+
validator.command("claim <vote> <amount>").description("Claim collateral from validator to reserve").action(async (vote, amountStr) => {
|
|
6398
6418
|
const spinner = ora("Claiming collateral").start();
|
|
6399
6419
|
const { client } = useContext();
|
|
6400
|
-
const bondType =
|
|
6420
|
+
const bondType = getBondType();
|
|
6401
6421
|
const bondName = getBondName();
|
|
6402
6422
|
try {
|
|
6403
6423
|
const voteAccount = new import_web33.PublicKey(vote);
|
|
6404
|
-
const
|
|
6405
|
-
if (Number.isNaN(
|
|
6424
|
+
const amount = Number.parseFloat(amountStr);
|
|
6425
|
+
if (Number.isNaN(amount) || amount <= 0) {
|
|
6406
6426
|
throw new Error("Invalid amount: must be positive number");
|
|
6407
6427
|
}
|
|
6408
6428
|
const tx = await client.claimCompensation({
|
|
6409
6429
|
bondType,
|
|
6410
6430
|
name: bondName,
|
|
6411
6431
|
voteAccount,
|
|
6412
|
-
|
|
6432
|
+
amount
|
|
6413
6433
|
});
|
|
6414
6434
|
spinner.succeed("Collateral claimed");
|
|
6415
6435
|
log.json({
|
|
6416
|
-
amount: `${
|
|
6436
|
+
amount: `${amount} SOL`,
|
|
6417
6437
|
transaction: tx
|
|
6418
6438
|
});
|
|
6419
6439
|
} catch (error2) {
|
|
6420
6440
|
spinner.fail("Failed to claim collateral");
|
|
6421
|
-
|
|
6422
|
-
process.exit(1);
|
|
6441
|
+
throw error2;
|
|
6423
6442
|
}
|
|
6424
6443
|
});
|
|
6425
6444
|
validator.command("info <vote>").description("Show validator bond account information").action(async (vote) => {
|
|
6426
6445
|
const { client } = useContext();
|
|
6427
|
-
const bondType =
|
|
6446
|
+
const bondType = getBondType();
|
|
6428
6447
|
const bondName = getBondName();
|
|
6429
6448
|
try {
|
|
6430
6449
|
const voteAccount = new import_web33.PublicKey(vote);
|
|
@@ -6441,19 +6460,22 @@ validator.command("info <vote>").description("Show validator bond account inform
|
|
|
6441
6460
|
validator: bond2.identity,
|
|
6442
6461
|
voteAccount: bond2.voteAccount,
|
|
6443
6462
|
balance: `${lamportsToSol(balance)} SOL`,
|
|
6463
|
+
// TODO: handle non-native collateral
|
|
6444
6464
|
authority: bond2.withdrawalAuthority || "identity only",
|
|
6445
6465
|
createdAt: bond2.createdAt,
|
|
6446
|
-
creator: bond2.creator
|
|
6466
|
+
creator: bond2.creator,
|
|
6467
|
+
currentEpochLocked: bond2.locked,
|
|
6468
|
+
pendingUnlock: bond2.pendingUnlock,
|
|
6469
|
+
pendingUnlockEpoch: bond2.pendingUnlockEpoch
|
|
6447
6470
|
});
|
|
6448
6471
|
} catch (error2) {
|
|
6449
|
-
|
|
6450
|
-
process.exit(1);
|
|
6472
|
+
throw new Error(`Failed to get validator info: ${error2}`);
|
|
6451
6473
|
}
|
|
6452
6474
|
});
|
|
6453
6475
|
validator.command("set-authority <vote>").description("Set withdrawal authority for validator bond").option("-a, --authority <pubkey>", "New withdrawal authority (omit to remove)").action(async (vote, opts) => {
|
|
6454
6476
|
const spinner = ora("Setting withdrawal authority").start();
|
|
6455
6477
|
const { client, keypair } = useContext();
|
|
6456
|
-
const bondType =
|
|
6478
|
+
const bondType = getBondType();
|
|
6457
6479
|
const bondName = getBondName();
|
|
6458
6480
|
try {
|
|
6459
6481
|
const voteAccount = new import_web33.PublicKey(vote);
|
|
@@ -6478,37 +6500,95 @@ validator.command("set-authority <vote>").description("Set withdrawal authority
|
|
|
6478
6500
|
});
|
|
6479
6501
|
} catch (error2) {
|
|
6480
6502
|
spinner.fail("Failed to set withdrawal authority");
|
|
6481
|
-
|
|
6482
|
-
process.exit(1);
|
|
6503
|
+
throw error2;
|
|
6483
6504
|
}
|
|
6484
6505
|
});
|
|
6485
6506
|
validator.command("history <vote>").description("Show transaction history for validator").option("-l, --limit <number>", "Number of records", "10").action(async (vote, opts) => {
|
|
6486
6507
|
const { client } = useContext();
|
|
6487
|
-
const bondType =
|
|
6508
|
+
const bondType = getBondType();
|
|
6488
6509
|
const bondName = getBondName();
|
|
6489
6510
|
const limit = Number.parseInt(opts.limit, 10);
|
|
6490
6511
|
const voteAccount = new import_web33.PublicKey(vote);
|
|
6491
6512
|
const cluster = import_commander.program.opts().cluster || "mainnet-beta";
|
|
6513
|
+
const history = await client.history.getHistory(bondType, bondName, voteAccount, { limit, cluster });
|
|
6514
|
+
log.header(`Transaction History (limit: ${limit})`);
|
|
6515
|
+
log.json(history);
|
|
6516
|
+
});
|
|
6517
|
+
validator.command("lock-funds <vote> <amount>").description("Lock funds in validator bond account (standard bonds only)").action(async (vote, amountStr) => {
|
|
6518
|
+
const spinner = ora("Locking funds").start();
|
|
6519
|
+
const { client, keypair } = useContext();
|
|
6520
|
+
const bondType = getBondType();
|
|
6521
|
+
const bondName = getBondName();
|
|
6522
|
+
try {
|
|
6523
|
+
if (bondType !== "standard") {
|
|
6524
|
+
throw new Error("Locking funds is only supported for standard bonds");
|
|
6525
|
+
}
|
|
6526
|
+
const voteAccount = new import_web33.PublicKey(vote);
|
|
6527
|
+
const amount = Number.parseFloat(amountStr);
|
|
6528
|
+
if (Number.isNaN(amount) || amount <= 0) {
|
|
6529
|
+
throw new Error("Invalid amount: must be positive number");
|
|
6530
|
+
}
|
|
6531
|
+
const tx = await client.lockFunds({
|
|
6532
|
+
bondType,
|
|
6533
|
+
name: bondName,
|
|
6534
|
+
voteAccount,
|
|
6535
|
+
amount,
|
|
6536
|
+
withdrawAuthority: keypair.publicKey
|
|
6537
|
+
});
|
|
6538
|
+
spinner.succeed("Funds locked");
|
|
6539
|
+
log.json({
|
|
6540
|
+
amount: `${amount} SOL`,
|
|
6541
|
+
transaction: tx
|
|
6542
|
+
});
|
|
6543
|
+
} catch (error2) {
|
|
6544
|
+
spinner.fail("Failed to lock funds");
|
|
6545
|
+
throw error2;
|
|
6546
|
+
}
|
|
6547
|
+
});
|
|
6548
|
+
validator.command("close <vote>").description("Close validator bond account and reclaim funds").option("-r, --receiver <pubkey>", "Rent receiver address (defaults to signer)").action(async (vote, opts) => {
|
|
6549
|
+
const spinner = ora("Closing validator bond").start();
|
|
6550
|
+
const { client, keypair } = useContext();
|
|
6551
|
+
const bondType = getBondType();
|
|
6552
|
+
const bondName = getBondName();
|
|
6492
6553
|
try {
|
|
6493
|
-
const
|
|
6494
|
-
|
|
6495
|
-
|
|
6554
|
+
const voteAccount = new import_web33.PublicKey(vote);
|
|
6555
|
+
const rentReceiver = opts.receiver ? new import_web33.PublicKey(opts.receiver) : keypair.publicKey;
|
|
6556
|
+
const bond2 = await client.getValidatorBond(bondType, bondName, voteAccount);
|
|
6557
|
+
if (!bond2) {
|
|
6558
|
+
throw new Error("Validator bond account not found");
|
|
6559
|
+
}
|
|
6560
|
+
if (bond2.locked.toNumber() > 0 || bond2.pendingUnlock.toNumber() > 0) {
|
|
6561
|
+
throw new Error("Cannot close: funds are still locked or pending unlock");
|
|
6562
|
+
}
|
|
6563
|
+
const tx = await client.closeValidatorBond({
|
|
6564
|
+
bondType,
|
|
6565
|
+
name: bondName,
|
|
6566
|
+
voteAccount,
|
|
6567
|
+
rentReceiver,
|
|
6568
|
+
authority: keypair.publicKey
|
|
6569
|
+
});
|
|
6570
|
+
spinner.succeed("Validator bond closed");
|
|
6571
|
+
log.json({
|
|
6572
|
+
voteAccount: vote,
|
|
6573
|
+
rentReceiver: rentReceiver.toString(),
|
|
6574
|
+
transaction: tx
|
|
6575
|
+
});
|
|
6496
6576
|
} catch (error2) {
|
|
6497
|
-
|
|
6498
|
-
|
|
6577
|
+
spinner.fail("Failed to close validator bond");
|
|
6578
|
+
throw error2;
|
|
6499
6579
|
}
|
|
6500
6580
|
});
|
|
6501
6581
|
var session = import_commander.program.command("session").description("Manage bond sessions");
|
|
6502
6582
|
session.command("start <duration>").description("Start a bond session").action(async (duration) => {
|
|
6503
6583
|
const spinner = ora("Starting bond session").start();
|
|
6504
6584
|
const { client } = useContext();
|
|
6505
|
-
const bondType =
|
|
6585
|
+
const bondType = getBondType();
|
|
6506
6586
|
const bondName = getBondName();
|
|
6507
6587
|
try {
|
|
6508
6588
|
if (Number.isNaN(duration) || duration <= 0) {
|
|
6509
6589
|
throw new Error("Invalid duration: must be positive number");
|
|
6510
6590
|
}
|
|
6511
|
-
const tx = await client.bondStart({ bondType, name: bondName,
|
|
6591
|
+
const tx = await client.bondStart({ bondType, name: bondName, duration });
|
|
6512
6592
|
spinner.succeed("Bond session started");
|
|
6513
6593
|
log.json({
|
|
6514
6594
|
duration: `${duration} seconds`,
|
|
@@ -6516,14 +6596,13 @@ session.command("start <duration>").description("Start a bond session").action(a
|
|
|
6516
6596
|
});
|
|
6517
6597
|
} catch (error2) {
|
|
6518
6598
|
spinner.fail("Failed to start bond session");
|
|
6519
|
-
|
|
6520
|
-
process.exit(1);
|
|
6599
|
+
throw error2;
|
|
6521
6600
|
}
|
|
6522
6601
|
});
|
|
6523
6602
|
session.command("finish").description("Finish current bond session").action(async () => {
|
|
6524
6603
|
const spinner = ora("Finishing bond session").start();
|
|
6525
6604
|
const { client } = useContext();
|
|
6526
|
-
const bondType =
|
|
6605
|
+
const bondType = getBondType();
|
|
6527
6606
|
const bondName = getBondName();
|
|
6528
6607
|
try {
|
|
6529
6608
|
const transaction = await client.bondFinish({ bondType, name: bondName });
|
|
@@ -6531,17 +6610,13 @@ session.command("finish").description("Finish current bond session").action(asyn
|
|
|
6531
6610
|
log.json({ transaction });
|
|
6532
6611
|
} catch (error2) {
|
|
6533
6612
|
spinner.fail("Failed to finish bond session");
|
|
6534
|
-
|
|
6535
|
-
process.exit(1);
|
|
6613
|
+
throw error2;
|
|
6536
6614
|
}
|
|
6537
6615
|
});
|
|
6538
6616
|
import_commander.program.command("*", { isDefault: true, hidden: true }).allowExcessArguments(true).action(() => import_commander.program.help());
|
|
6539
6617
|
import_commander.program.parseAsync().catch((e) => {
|
|
6540
6618
|
log.error(`
|
|
6541
6619
|
${e.message}`);
|
|
6542
|
-
if (e.logs) {
|
|
6543
|
-
log.json(e.logs, "red");
|
|
6544
|
-
}
|
|
6545
6620
|
process.exit(1);
|
|
6546
6621
|
});
|
|
6547
6622
|
function getBondName() {
|
|
@@ -6551,3 +6626,6 @@ function getBondName() {
|
|
|
6551
6626
|
}
|
|
6552
6627
|
return bond2;
|
|
6553
6628
|
}
|
|
6629
|
+
function getBondType() {
|
|
6630
|
+
return import_commander.program.opts().bondType;
|
|
6631
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jpool/bond-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0-next.2",
|
|
4
4
|
"description": "JBond CLI for interacting with the Solana program",
|
|
5
5
|
"main": "./dist/cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"commander": "^14.0.1",
|
|
17
17
|
"dotenv": "^17.2.3",
|
|
18
18
|
"ora": "^9.0.0",
|
|
19
|
-
"@jpool/bond-sdk": "0.
|
|
19
|
+
"@jpool/bond-sdk": "0.11.0-next.22"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"tsup": "^8.5.0",
|