@jpool/bond-sdk 0.10.5 → 0.11.0-next.11

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/index.mjs CHANGED
@@ -4735,7 +4735,7 @@ function slotToEpoch(slot, cluster) {
4735
4735
 
4736
4736
  // src/idl/jbond.json
4737
4737
  var jbond_default = {
4738
- address: "BondQ7KqZreTcW2UbeTNDcLCJQ3aXAtLn2Fm6ftaJDU",
4738
+ address: "Fo17edWRJewZNTRibgx9iTfjywCW6dzS81VwBLmPFVq1",
4739
4739
  metadata: {
4740
4740
  name: "jbond",
4741
4741
  version: "0.2.1",
@@ -4984,6 +4984,50 @@ var jbond_default = {
4984
4984
  }
4985
4985
  ]
4986
4986
  },
4987
+ {
4988
+ name: "bond_lock_funds",
4989
+ docs: [
4990
+ "Locks funds for both the current and upcoming epoch.",
4991
+ "Moves collateral from available to locked state, making it unavailable for withdrawal for the current and next epoch.",
4992
+ "# Errors",
4993
+ "Fails if the validator is not active, or if there are insufficient available funds."
4994
+ ],
4995
+ discriminator: [
4996
+ 117,
4997
+ 166,
4998
+ 195,
4999
+ 99,
5000
+ 103,
5001
+ 45,
5002
+ 195,
5003
+ 2
5004
+ ],
5005
+ accounts: [
5006
+ {
5007
+ name: "bond_state",
5008
+ writable: true
5009
+ },
5010
+ {
5011
+ name: "validator_bond",
5012
+ writable: true
5013
+ },
5014
+ {
5015
+ name: "bond_token_account",
5016
+ optional: true
5017
+ },
5018
+ {
5019
+ name: "payer",
5020
+ writable: true,
5021
+ signer: true
5022
+ }
5023
+ ],
5024
+ args: [
5025
+ {
5026
+ name: "amount",
5027
+ type: "u64"
5028
+ }
5029
+ ]
5030
+ },
4987
5031
  {
4988
5032
  name: "bond_register",
4989
5033
  docs: [
@@ -5096,6 +5140,42 @@ var jbond_default = {
5096
5140
  }
5097
5141
  ]
5098
5142
  },
5143
+ {
5144
+ name: "bond_release_funds",
5145
+ docs: [
5146
+ "Releases locked funds after an epoch ends.",
5147
+ "Moves collateral from locked back to available state, allowing withdrawals.",
5148
+ "# Errors",
5149
+ "Fails if the validator is not active, or if there are insufficient locked funds."
5150
+ ],
5151
+ discriminator: [
5152
+ 184,
5153
+ 224,
5154
+ 14,
5155
+ 24,
5156
+ 76,
5157
+ 14,
5158
+ 226,
5159
+ 190
5160
+ ],
5161
+ accounts: [
5162
+ {
5163
+ name: "validator_bond",
5164
+ writable: true
5165
+ },
5166
+ {
5167
+ name: "payer",
5168
+ writable: true,
5169
+ signer: true
5170
+ }
5171
+ ],
5172
+ args: [
5173
+ {
5174
+ name: "amount",
5175
+ type: "u64"
5176
+ }
5177
+ ]
5178
+ },
5099
5179
  {
5100
5180
  name: "bond_set_withdraw_authority",
5101
5181
  docs: [
@@ -5275,6 +5355,42 @@ var jbond_default = {
5275
5355
  }
5276
5356
  ]
5277
5357
  },
5358
+ {
5359
+ name: "bond_update",
5360
+ docs: [
5361
+ "Transitions locked funds between epochs for a validator bond.",
5362
+ "",
5363
+ "This function should be called at epoch boundaries to update the bond's",
5364
+ "`last_update_epoch` and move the `next_epoch_locked` amount into",
5365
+ "`current_epoch_locked`. It ensures that the update only occurs once per epoch.",
5366
+ "",
5367
+ "# Errors",
5368
+ "Returns [`BondError::InvalidEpoch`] if called more than once in the same epoch,",
5369
+ "or if the system clock cannot be accessed."
5370
+ ],
5371
+ discriminator: [
5372
+ 237,
5373
+ 102,
5374
+ 183,
5375
+ 192,
5376
+ 94,
5377
+ 83,
5378
+ 52,
5379
+ 82
5380
+ ],
5381
+ accounts: [
5382
+ {
5383
+ name: "validator_bond",
5384
+ writable: true
5385
+ },
5386
+ {
5387
+ name: "payer",
5388
+ writable: true,
5389
+ signer: true
5390
+ }
5391
+ ],
5392
+ args: []
5393
+ },
5278
5394
  {
5279
5395
  name: "bond_withdraw",
5280
5396
  docs: [
@@ -5875,6 +5991,11 @@ var jbond_default = {
5875
5991
  code: 6023,
5876
5992
  name: "BondNotEnabled",
5877
5993
  msg: "Bond is not enabled"
5994
+ },
5995
+ {
5996
+ code: 6024,
5997
+ name: "InvalidEpoch",
5998
+ msg: "Invalid epoch for this operation"
5878
5999
  }
5879
6000
  ],
5880
6001
  types: [
@@ -6257,33 +6378,76 @@ var jbond_default = {
6257
6378
  fields: [
6258
6379
  {
6259
6380
  name: "state",
6381
+ docs: [
6382
+ "The bond state address"
6383
+ ],
6260
6384
  type: "pubkey"
6261
6385
  },
6262
6386
  {
6263
6387
  name: "identity",
6388
+ docs: [
6389
+ "Validator identity pubkey"
6390
+ ],
6264
6391
  type: "pubkey"
6265
6392
  },
6266
6393
  {
6267
6394
  name: "vote_account",
6395
+ docs: [
6396
+ "Validator vote account pubkey"
6397
+ ],
6268
6398
  type: "pubkey"
6269
6399
  },
6270
6400
  {
6271
6401
  name: "creator",
6402
+ docs: [
6403
+ "The bond creator pubkey"
6404
+ ],
6272
6405
  type: "pubkey"
6273
6406
  },
6274
6407
  {
6275
6408
  name: "withdrawal_authority",
6409
+ docs: [
6410
+ "Optional withdrawal authority pubkey (if set, can withdraw on behalf of the validator,",
6411
+ "otherwise only identity can withdraw)"
6412
+ ],
6276
6413
  type: {
6277
6414
  option: "pubkey"
6278
6415
  }
6279
6416
  },
6280
6417
  {
6281
6418
  name: "created_at",
6419
+ docs: [
6420
+ "Bond creation timestamp"
6421
+ ],
6282
6422
  type: "i64"
6283
6423
  },
6284
6424
  {
6285
6425
  name: "bump",
6426
+ docs: [
6427
+ "Bump for the PDA"
6428
+ ],
6286
6429
  type: "u8"
6430
+ },
6431
+ {
6432
+ name: "next_epoch_locked",
6433
+ docs: [
6434
+ "Amount of collateral locked for the next epoch"
6435
+ ],
6436
+ type: "u64"
6437
+ },
6438
+ {
6439
+ name: "current_epoch_locked",
6440
+ docs: [
6441
+ "Amount of collateral locked for the current epoch"
6442
+ ],
6443
+ type: "u64"
6444
+ },
6445
+ {
6446
+ name: "last_update_epoch",
6447
+ docs: [
6448
+ "The last epoch when the bond was updated"
6449
+ ],
6450
+ type: "u64"
6287
6451
  }
6288
6452
  ]
6289
6453
  }
@@ -6397,6 +6561,20 @@ var NodeWallet = class {
6397
6561
  }
6398
6562
  };
6399
6563
  var SOL_DECIMALS = Math.log10(LAMPORTS_PER_SOL);
6564
+ function lamportsToSol(lamports) {
6565
+ if (typeof lamports === "number") {
6566
+ return Math.abs(lamports) / LAMPORTS_PER_SOL;
6567
+ }
6568
+ let signMultiplier = 1;
6569
+ if (lamports.isNeg()) {
6570
+ signMultiplier = -1;
6571
+ }
6572
+ const absLamports = lamports.abs();
6573
+ const lamportsString = absLamports.toString(10).padStart(10, "0");
6574
+ const splitIndex = lamportsString.length - SOL_DECIMALS;
6575
+ const solString = `${lamportsString.slice(0, splitIndex)}.${lamportsString.slice(splitIndex)}`;
6576
+ return signMultiplier * Number.parseFloat(solString);
6577
+ }
6400
6578
  function solToLamports(amount) {
6401
6579
  if (Number.isNaN(amount)) {
6402
6580
  return new BN(0);
@@ -6417,12 +6595,12 @@ function getBondTypeSeed(type) {
6417
6595
  }
6418
6596
 
6419
6597
  // src/client.ts
6420
- var BondClientEnv = /* @__PURE__ */ ((BondClientEnv2) => {
6421
- BondClientEnv2["DEV"] = "dev";
6422
- BondClientEnv2["STAGE"] = "stage";
6423
- BondClientEnv2["PROD"] = "prod";
6424
- return BondClientEnv2;
6425
- })(BondClientEnv || {});
6598
+ var JBondClientEnv = /* @__PURE__ */ ((JBondClientEnv2) => {
6599
+ JBondClientEnv2["DEV"] = "dev";
6600
+ JBondClientEnv2["STAGE"] = "stage";
6601
+ JBondClientEnv2["PROD"] = "prod";
6602
+ return JBondClientEnv2;
6603
+ })(JBondClientEnv || {});
6426
6604
  var JBondClient = class _JBondClient {
6427
6605
  constructor(provider, options) {
6428
6606
  this.provider = provider;
@@ -6434,6 +6612,12 @@ var JBondClient = class _JBondClient {
6434
6612
  get history() {
6435
6613
  return new HistoryManager(this);
6436
6614
  }
6615
+ /**
6616
+ * Creates a local instance of `JBondClient` for development and testing.
6617
+ */
6618
+ static local(options) {
6619
+ return new _JBondClient(AnchorProvider.local(), options);
6620
+ }
6437
6621
  /**
6438
6622
  * Creates an instance of `JBondClient` using a provided connection and wallet.
6439
6623
  */
@@ -6545,7 +6729,7 @@ var JBondClient = class _JBondClient {
6545
6729
  return this.provider.sendAndConfirm?.(new Transaction().add(ix));
6546
6730
  }
6547
6731
  /**
6548
- * Claim compensation
6732
+ * Claim compensation for a validator
6549
6733
  */
6550
6734
  async claimCompensation(props) {
6551
6735
  const ix = await this.getClaimIx(props);
@@ -6806,6 +6990,35 @@ var JBondClient = class _JBondClient {
6806
6990
  });
6807
6991
  return this.program.methods.bondClaim(solToLamports(amount)).accountsPartial(accounts).instruction();
6808
6992
  }
6993
+ /**
6994
+ * Build claim all compensations instructions
6995
+ */
6996
+ async getClaimAllCompensationsIxs(props) {
6997
+ const ixs = [];
6998
+ const validatorBondBalances = await this.getBondStateValidatorBondBalances(
6999
+ props.bondType,
7000
+ props.name
7001
+ );
7002
+ for (const bond_balance of validatorBondBalances) {
7003
+ const amountToClaim = lamportsToSol(bond_balance.balance);
7004
+ if (amountToClaim <= 0) {
7005
+ this.debug("No balance to claim for validator:", bond_balance.voteAccount.toBase58());
7006
+ continue;
7007
+ }
7008
+ this.debug("Amount to claim:", amountToClaim);
7009
+ const ix = await this.getClaimIx({
7010
+ bondType: props.bondType,
7011
+ name: props.name,
7012
+ amount: amountToClaim,
7013
+ collateralType: props.collateralType,
7014
+ reserve: props.reserve,
7015
+ authority: props.authority,
7016
+ voteAccount: bond_balance.voteAccount
7017
+ });
7018
+ ixs.push(ix);
7019
+ }
7020
+ return ixs;
7021
+ }
6809
7022
  /**
6810
7023
  * Build set withdraw authority instruction
6811
7024
  */
@@ -6834,6 +7047,77 @@ var JBondClient = class _JBondClient {
6834
7047
  const authority = this.provider.wallet?.publicKey;
6835
7048
  return this.program.methods.sessionStart(new import_bn.BN(props.duration)).accountsPartial({ bondState, authority }).instruction();
6836
7049
  }
7050
+ async lockFunds(props) {
7051
+ const ix = await this.getLockFundsIx(props);
7052
+ return this.provider.sendAndConfirm?.(new Transaction().add(ix));
7053
+ }
7054
+ async releaseFunds(props) {
7055
+ const ix = await this.getReleaseFundsIx(props);
7056
+ return this.provider.sendAndConfirm?.(new Transaction().add(ix));
7057
+ }
7058
+ /**
7059
+ * Update epoch locks
7060
+ */
7061
+ async updateEpochLocks(props) {
7062
+ const { bondType, bondName, voteAccount } = props;
7063
+ const ix = await this.getUpdateEpochLocksIx({ bondType, bondName, voteAccount });
7064
+ return this.provider.sendAndConfirm?.(new Transaction().add(ix));
7065
+ }
7066
+ /**
7067
+ * Build update epoch locks instruction
7068
+ */
7069
+ async getUpdateEpochLocksIx(props) {
7070
+ const { bondType, bondName, voteAccount } = props;
7071
+ const [validatorBond, _] = this.pda.validatorBond(bondType, bondName, voteAccount);
7072
+ return this.program.methods.bondUpdate().accountsPartial({ validatorBond }).instruction();
7073
+ }
7074
+ /**
7075
+ * Build lock funds instruction
7076
+ */
7077
+ async getLockFundsIx(props) {
7078
+ const { bondType, name, voteAccount, amount, withdrawAuthority } = props;
7079
+ const [bondState] = this.pda.bondState(bondType, name);
7080
+ let collateralType = props.collateralType;
7081
+ if (!collateralType) {
7082
+ const bondState2 = await this.getBondState(bondType, name);
7083
+ collateralType = bondState2.collateralType;
7084
+ }
7085
+ const [validatorBond] = this.pda.validatorBond(bondType, name, voteAccount);
7086
+ const accounts = {
7087
+ bondState,
7088
+ validatorBond,
7089
+ payer: withdrawAuthority,
7090
+ bondTokenAccount: null
7091
+ };
7092
+ matchVariant(collateralType, {
7093
+ native: () => {
7094
+ },
7095
+ token: (mint) => {
7096
+ const bondTokenAccount = getAssociatedTokenAddressSync(mint, validatorBond, true);
7097
+ accounts.bondTokenAccount = bondTokenAccount;
7098
+ }
7099
+ });
7100
+ return this.program.methods.bondLockFunds(solToLamports(amount)).accountsPartial(accounts).instruction();
7101
+ }
7102
+ /**
7103
+ * Build release funds instruction
7104
+ */
7105
+ async getReleaseFundsIx(props) {
7106
+ const { bondType, name, voteAccount, amount, withdrawAuthority } = props;
7107
+ const [validatorBond] = this.pda.validatorBond(bondType, name, voteAccount);
7108
+ const accounts = {
7109
+ validatorBond,
7110
+ payer: withdrawAuthority
7111
+ };
7112
+ return this.program.methods.bondReleaseFunds(solToLamports(amount)).accountsPartial(accounts).instruction();
7113
+ }
7114
+ /**
7115
+ * Get available collateral for withdrawal (taking into account locked funds)
7116
+ */
7117
+ async getAvailableCollateral(bondType, bondName, voteAccount) {
7118
+ const validatorBond = await this.getValidatorBond(bondType, bondName, voteAccount);
7119
+ return await this.getValidatorBondBalance(bondType, bondName, voteAccount) - validatorBond.currentEpochLocked.toNumber();
7120
+ }
6837
7121
  /**
6838
7122
  * Get all bond states with total collected collateral
6839
7123
  */
@@ -6891,8 +7175,8 @@ var JBondClient = class _JBondClient {
6891
7175
  if (!accountInfo) {
6892
7176
  return 0;
6893
7177
  }
6894
- const { data, lamports } = accountInfo;
6895
- const rentExempt = await this.connection.getMinimumBalanceForRentExemption(data.length);
7178
+ const { lamports } = accountInfo;
7179
+ const rentExempt = await this.validatorBondRentExempt();
6896
7180
  return Math.max(0, lamports - rentExempt);
6897
7181
  },
6898
7182
  token: async (mint) => {
@@ -6906,12 +7190,13 @@ var JBondClient = class _JBondClient {
6906
7190
  }
6907
7191
  });
6908
7192
  }
6909
- /**
6910
- * Get total collected collateral for a bond state
6911
- */
6912
- async getBondStateTotalCollected(bondType, bondName, votes) {
7193
+ async getBondStateValidatorBondBalances(bondType, bondName) {
6913
7194
  const bondState = await this.getBondState(bondType, bondName);
6914
7195
  const collateralType = bondState.collateralType;
7196
+ const validatorBonds = await this.getValidatorBondsForState(bondType, bondName);
7197
+ if (!validatorBonds.length) {
7198
+ return [];
7199
+ }
6915
7200
  const chunk = (arr, n = 100) => {
6916
7201
  const res = [];
6917
7202
  for (let i = 0; i < arr.length; i += n) {
@@ -6921,54 +7206,53 @@ var JBondClient = class _JBondClient {
6921
7206
  };
6922
7207
  return await matchVariant(collateralType, {
6923
7208
  native: async () => {
6924
- const addresses = votes.map((vote) => {
6925
- const [address] = this.pda.validatorBond(bondType, bondName, new PublicKey(vote));
6926
- return address;
6927
- });
7209
+ const addresses = validatorBonds.map((vb) => vb.publicKey);
6928
7210
  const accountInfos = await this.connection.getMultipleAccountsInfo(addresses);
6929
- const balances = await Promise.all(
6930
- accountInfos.map(async (accountInfo) => {
6931
- if (!accountInfo) {
6932
- return 0;
6933
- }
6934
- const { lamports } = accountInfo;
6935
- return lamports;
6936
- })
6937
- );
6938
- return balances.reduce((sum, v) => sum + v, 0);
7211
+ const rentExempt = await this.validatorBondRentExempt();
7212
+ return validatorBonds.map((vb, idx) => ({
7213
+ voteAccount: vb.voteAccount,
7214
+ balance: Math.max(0, (accountInfos[idx]?.lamports ?? 0) - rentExempt)
7215
+ }));
6939
7216
  },
6940
7217
  token: async (mint) => {
6941
- const tokenAccounts = votes.map((vote) => {
6942
- const [validatorBondAddress] = this.pda.validatorBond(bondType, bondName, new PublicKey(vote));
6943
- return getAssociatedTokenAddressSync(mint, validatorBondAddress, true);
6944
- });
6945
- if (tokenAccounts.length === 0) {
6946
- return 0;
6947
- }
6948
- let total = 0n;
6949
- for (const part of chunk(tokenAccounts, 100)) {
6950
- const infos = await this.connection.getMultipleAccountsInfo(part).catch(() => []);
6951
- for (let i = 0; i < infos.length; i++) {
7218
+ const items = validatorBonds.map((vb) => ({
7219
+ voteAccount: vb.voteAccount,
7220
+ tokenAccount: getAssociatedTokenAddressSync(mint, vb.publicKey, true)
7221
+ }));
7222
+ const balances = [];
7223
+ for (const part of chunk(items, 100)) {
7224
+ const infos = await this.connection.getMultipleAccountsInfo(part.map((i) => i.tokenAccount)).catch(() => []);
7225
+ for (let i = 0; i < part.length; i++) {
6952
7226
  const info = infos[i];
6953
- if (!info) {
6954
- continue;
6955
- }
6956
- if (info.data.length !== ACCOUNT_SIZE) {
7227
+ const voteAccount = part[i].voteAccount;
7228
+ if (!info || info.data.length !== ACCOUNT_SIZE) {
7229
+ balances.push({ voteAccount, balance: 0 });
6957
7230
  continue;
6958
7231
  }
6959
7232
  try {
6960
7233
  const acc = AccountLayout.decode(info.data);
6961
7234
  const raw = BigInt(acc.amount.toString());
6962
- total += raw;
7235
+ const asNumber = Number(raw);
7236
+ balances.push({
7237
+ voteAccount,
7238
+ balance: Number.isFinite(asNumber) ? asNumber : Number.MAX_SAFE_INTEGER
7239
+ });
6963
7240
  } catch {
7241
+ balances.push({ voteAccount, balance: 0 });
6964
7242
  }
6965
7243
  }
6966
7244
  }
6967
- const asNumber = Number(total);
6968
- return Number.isFinite(asNumber) ? asNumber : Number.MAX_SAFE_INTEGER;
7245
+ return balances;
6969
7246
  }
6970
7247
  });
6971
7248
  }
7249
+ /**
7250
+ * Get total collected collateral for a bond state
7251
+ */
7252
+ async getBondStateTotalCollected(bondType, bondName) {
7253
+ const allBalances = await this.getBondStateValidatorBondBalances(bondType, bondName);
7254
+ return allBalances.reduce((sum, vb) => sum + vb.balance, 0);
7255
+ }
6972
7256
  /**
6973
7257
  * Get bond state stats
6974
7258
  * @param state
@@ -6976,21 +7260,25 @@ var JBondClient = class _JBondClient {
6976
7260
  */
6977
7261
  async getBondStateStats(state) {
6978
7262
  const bondType = anchorToBondType(state.bondType);
6979
- const validatorBonds = await this.getBondValidatorStates(bondType, state.name);
6980
7263
  const totalCollected = await this.getBondStateTotalCollected(
6981
7264
  bondType,
6982
- state.name,
6983
- validatorBonds.map((vb) => vb.voteAccount)
7265
+ state.name
6984
7266
  );
6985
7267
  return {
6986
7268
  totalCollected,
6987
7269
  status: this.getBondStateSessionStatus(state)
6988
7270
  };
6989
7271
  }
7272
+ /**
7273
+ * Get validator bond rent exempt amount
7274
+ */
7275
+ validatorBondRentExempt = async () => {
7276
+ return this.connection.getMinimumBalanceForRentExemption(this.program.account.validatorBond.size);
7277
+ };
6990
7278
  /**
6991
7279
  * Get all validator bonds for a given bond state
6992
7280
  */
6993
- async getBondValidatorStates(bondType, bondName) {
7281
+ async getValidatorBondsForState(bondType, bondName) {
6994
7282
  const [bondState] = this.pda.bondState(bondType, bondName);
6995
7283
  const accounts = await this.program.account.validatorBond.all([
6996
7284
  {
@@ -7033,6 +7321,6 @@ buffer/index.js:
7033
7321
  *)
7034
7322
  */
7035
7323
 
7036
- export { BOND_STATE_SEED, BondClientEnv, BondTransactionType, BondType, CROWDFUNDING_BOND_SEED, ENV_PROGRAM_ID, GLOBAL_STATE_SEED, JBondClient, NodeWallet, STANDARD_BOND_SEED, SessionStatus, VALIDATOR_BOND_SEED };
7324
+ export { BOND_STATE_SEED, BondTransactionType, BondType, CROWDFUNDING_BOND_SEED, ENV_PROGRAM_ID, GLOBAL_STATE_SEED, JBondClient, JBondClientEnv, NodeWallet, STANDARD_BOND_SEED, SessionStatus, VALIDATOR_BOND_SEED };
7037
7325
  //# sourceMappingURL=index.mjs.map
7038
7326
  //# sourceMappingURL=index.mjs.map