@jpool/bond-sdk 0.9.0-next.0 → 0.9.0-next.1

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.d.mts CHANGED
@@ -1200,13 +1200,6 @@ declare class JBondClient {
1200
1200
  * @return Balance in SOL
1201
1201
  */
1202
1202
  getValidatorBondBalance(vote: PublicKeyInitData): Promise<number>;
1203
- /**
1204
- * Get transaction history grouped by epochs
1205
- * @param vote - The vote account to get history for
1206
- * @param epochsCount - Number of recent epochs to return (default: 10)
1207
- * @returns Array of epoch history items sorted by epoch (descending)
1208
- */
1209
- getHistoryGroupedByEpochs(vote: PublicKeyInitData, epochsCount?: number): Promise<EpochHistoryItem[]>;
1210
1203
  /**
1211
1204
  * Get transaction history for a specific validator bond account
1212
1205
  */
@@ -1216,18 +1209,15 @@ declare class JBondClient {
1216
1209
  before?: string;
1217
1210
  until?: string;
1218
1211
  }): Promise<TransactionHistoryItem[]>;
1219
- /**
1220
- * Get full transaction history by paginating through results
1221
- * @param voteAccount
1222
- * @param pageSize
1223
- */
1224
- getFullHistory(voteAccount: PublicKey, pageSize?: number): Promise<TransactionHistoryItem[]>;
1225
1212
  /**
1226
1213
  * Get instruction discriminator from IDL
1227
1214
  * @param instructionName
1228
1215
  * @private
1229
1216
  */
1230
1217
  private getInstructionDiscriminator;
1218
+ private fetchSignaturesForValidator;
1219
+ private fetchParsedTransactions;
1220
+ private decodeInstructionData;
1231
1221
  }
1232
1222
 
1233
1223
  /**
package/dist/index.d.ts CHANGED
@@ -1200,13 +1200,6 @@ declare class JBondClient {
1200
1200
  * @return Balance in SOL
1201
1201
  */
1202
1202
  getValidatorBondBalance(vote: PublicKeyInitData): Promise<number>;
1203
- /**
1204
- * Get transaction history grouped by epochs
1205
- * @param vote - The vote account to get history for
1206
- * @param epochsCount - Number of recent epochs to return (default: 10)
1207
- * @returns Array of epoch history items sorted by epoch (descending)
1208
- */
1209
- getHistoryGroupedByEpochs(vote: PublicKeyInitData, epochsCount?: number): Promise<EpochHistoryItem[]>;
1210
1203
  /**
1211
1204
  * Get transaction history for a specific validator bond account
1212
1205
  */
@@ -1216,18 +1209,15 @@ declare class JBondClient {
1216
1209
  before?: string;
1217
1210
  until?: string;
1218
1211
  }): Promise<TransactionHistoryItem[]>;
1219
- /**
1220
- * Get full transaction history by paginating through results
1221
- * @param voteAccount
1222
- * @param pageSize
1223
- */
1224
- getFullHistory(voteAccount: PublicKey, pageSize?: number): Promise<TransactionHistoryItem[]>;
1225
1212
  /**
1226
1213
  * Get instruction discriminator from IDL
1227
1214
  * @param instructionName
1228
1215
  * @private
1229
1216
  */
1230
1217
  private getInstructionDiscriminator;
1218
+ private fetchSignaturesForValidator;
1219
+ private fetchParsedTransactions;
1220
+ private decodeInstructionData;
1231
1221
  }
1232
1222
 
1233
1223
  /**
package/dist/index.js CHANGED
@@ -1297,167 +1297,82 @@ var JBondClient = class _JBondClient {
1297
1297
  const availableBalance = Math.max(0, lamports - rentExempt);
1298
1298
  return availableBalance / web3_js.LAMPORTS_PER_SOL;
1299
1299
  }
1300
- /**
1301
- * Get transaction history grouped by epochs
1302
- * @param vote - The vote account to get history for
1303
- * @param epochsCount - Number of recent epochs to return (default: 10)
1304
- * @returns Array of epoch history items sorted by epoch (descending)
1305
- */
1306
- async getHistoryGroupedByEpochs(vote, epochsCount = 10) {
1307
- const epochInfo = await this.connection.getEpochInfo();
1308
- const fullHistory = await this.getFullHistory(new web3_js.PublicKey(vote));
1309
- const epochMap = /* @__PURE__ */ new Map();
1310
- for (const item of fullHistory) {
1311
- if (item.epoch < epochInfo.epoch - epochsCount + 1) {
1312
- continue;
1313
- }
1314
- if (!epochMap.has(item.epoch)) {
1315
- epochMap.set(item.epoch, {
1316
- epoch: item.epoch,
1317
- deposits: 0,
1318
- withdrawals: 0,
1319
- balanceChange: 0,
1320
- signatures: []
1321
- });
1322
- }
1323
- const epochData = epochMap.get(item.epoch);
1324
- if (item.type === "deposit") {
1325
- epochData.deposits += item.amount;
1326
- } else if (item.type === "withdrawal") {
1327
- epochData.withdrawals += item.amount;
1328
- }
1329
- if (!epochData.signatures.includes(item.signature)) {
1330
- epochData.signatures.push(item.signature);
1331
- }
1332
- }
1333
- for (const epochData of epochMap.values()) {
1334
- epochData.balanceChange = epochData.deposits - epochData.withdrawals;
1335
- }
1336
- return [...epochMap.values()].toSorted((a, b) => b.epoch - a.epoch);
1337
- }
1338
1300
  /**
1339
1301
  * Get transaction history for a specific validator bond account
1340
1302
  */
1341
1303
  async getHistory(vote, options) {
1342
- const [ValidatorBondAccount] = this.pda.validatorBond(new web3_js.PublicKey(vote));
1343
- const signatures = (await this.connection.getSignaturesForAddress(
1344
- ValidatorBondAccount,
1345
- {
1346
- limit: options?.limit || 1e3,
1347
- before: options?.before,
1348
- until: options?.until
1349
- }
1350
- )).filter((sig) => !sig.err);
1351
- const signatureStrings = signatures.map((sig) => sig.signature);
1352
- const BATCH_SIZE = 100;
1353
- const allTransactions = [];
1354
- for (let i = 0; i < signatureStrings.length; i += BATCH_SIZE) {
1355
- const batch = signatureStrings.slice(i, i + BATCH_SIZE);
1356
- const transactions = await this.connection.getParsedTransactions(
1357
- batch,
1358
- {
1359
- maxSupportedTransactionVersion: 0
1304
+ const cluster = options?.cluster || "mainnet-beta";
1305
+ const [validatorBondAccount] = this.pda.validatorBond(vote);
1306
+ const signatures = await this.fetchSignaturesForValidator(validatorBondAccount, {
1307
+ limit: options?.limit,
1308
+ before: options?.before,
1309
+ until: options?.until
1310
+ });
1311
+ if (signatures.length === 0) {
1312
+ return [];
1313
+ }
1314
+ const signatureStrings = signatures.map((s) => s.signature);
1315
+ const parsedTxs = await this.fetchParsedTransactions(signatureStrings);
1316
+ const txBySig = /* @__PURE__ */ new Map();
1317
+ for (let i = 0; i < signatureStrings.length; i++) {
1318
+ const requestedSig = signatureStrings[i];
1319
+ const tx = parsedTxs[i] ?? null;
1320
+ if (tx && tx.transaction && Array.isArray(tx.transaction.signatures) && tx.transaction.signatures[0]) {
1321
+ const txSig = tx.transaction.signatures[0];
1322
+ if (txSig !== requestedSig) {
1323
+ const found = parsedTxs.find((t) => t && t.transaction && t.transaction.signatures && t.transaction.signatures[0] === requestedSig) ?? null;
1324
+ txBySig.set(requestedSig, found);
1325
+ continue;
1360
1326
  }
1361
- );
1362
- allTransactions.push(...transactions);
1327
+ }
1328
+ txBySig.set(requestedSig, tx);
1363
1329
  }
1364
- const cluster = options?.cluster || "mainnet-beta";
1365
1330
  const history = [];
1366
- for (const [idx, tx] of allTransactions.entries()) {
1367
- const sigInfo = signatures[idx];
1331
+ for (const sigInfo of signatures) {
1332
+ const sig = sigInfo.signature;
1333
+ const tx = txBySig.get(sig) ?? null;
1368
1334
  if (!tx || !tx.meta || tx.meta.err !== null) {
1369
1335
  continue;
1370
1336
  }
1371
1337
  try {
1372
- const slot = tx.slot || 0;
1338
+ const slot = tx.slot ?? 0;
1373
1339
  const instructions = tx.transaction.message.instructions;
1374
1340
  for (const instruction of instructions) {
1375
- if ("programId" in instruction && instruction.programId.equals(this.options.programId ?? this.program.programId)) {
1376
- const ixData = instruction;
1377
- if ("parsed" in ixData && ixData.parsed) {
1378
- continue;
1379
- }
1380
- const data = ixData.data;
1381
- if (!data) {
1382
- continue;
1383
- }
1384
- let type = null;
1385
- let amount = 0;
1386
- try {
1387
- const dataBuffer = bs58__default.default.decode(data);
1388
- if (dataBuffer.length >= 16) {
1389
- const discriminator = dataBuffer.slice(0, 8);
1390
- const bondInitDiscriminator = this.getInstructionDiscriminator("register");
1391
- const bondTopUpDiscriminator = this.getInstructionDiscriminator("topUp");
1392
- const withdrawCompensationDiscriminator = this.getInstructionDiscriminator("claim");
1393
- const bondWithdrawDiscriminator = this.getInstructionDiscriminator("withdraw");
1394
- const amountBytes = dataBuffer.slice(8, 16);
1395
- const amountBN = new anchor.BN(amountBytes, "le");
1396
- amount = amountBN.toNumber() / web3_js.LAMPORTS_PER_SOL;
1397
- if (Buffer.from(discriminator).equals(Buffer.from(bondInitDiscriminator))) {
1398
- type = "deposit" /* Deposit */;
1399
- } else if (Buffer.from(discriminator).equals(Buffer.from(bondTopUpDiscriminator))) {
1400
- type = "deposit" /* Deposit */;
1401
- } else if (Buffer.from(discriminator).equals(Buffer.from(withdrawCompensationDiscriminator))) {
1402
- type = "compensation" /* Compensation */;
1403
- } else if (Buffer.from(discriminator).equals(Buffer.from(bondWithdrawDiscriminator))) {
1404
- type = "withdrawal" /* Withdrawal */;
1405
- }
1406
- }
1407
- } catch {
1408
- console.warn("Failed to decode instruction data");
1409
- }
1410
- if (type && amount > 0) {
1411
- let beforeBalance;
1412
- let afterBalance;
1413
- const accountIndex = tx.transaction.message.accountKeys.findIndex(
1414
- (key) => key.pubkey.equals(ValidatorBondAccount)
1415
- );
1416
- if (accountIndex !== -1 && tx.meta.preBalances && tx.meta.postBalances) {
1417
- beforeBalance = Number(tx.meta.preBalances[accountIndex] || 0) / web3_js.LAMPORTS_PER_SOL;
1418
- afterBalance = Number(tx.meta.postBalances[accountIndex] || 0) / web3_js.LAMPORTS_PER_SOL;
1419
- }
1420
- history.push({
1421
- signature: sigInfo.signature,
1422
- slot,
1423
- epoch: slotToEpoch(slot, cluster),
1424
- type,
1425
- amount,
1426
- beforeBalance,
1427
- afterBalance
1428
- });
1429
- }
1341
+ if (!("programId" in instruction)) {
1342
+ continue;
1343
+ }
1344
+ if (!instruction.programId.equals(this.options.programId ?? this.program.programId)) {
1345
+ continue;
1430
1346
  }
1347
+ if (instruction.parsed) {
1348
+ continue;
1349
+ }
1350
+ const { type, amount } = this.decodeInstructionData(instruction.data);
1351
+ if (!type || amount <= 0) {
1352
+ continue;
1353
+ }
1354
+ let beforeBalance;
1355
+ let afterBalance;
1356
+ const accountIndex = tx.transaction.message.accountKeys.findIndex((k) => k.pubkey.equals(validatorBondAccount));
1357
+ if (accountIndex !== -1 && tx.meta.preBalances && tx.meta.postBalances) {
1358
+ beforeBalance = Number(tx.meta.preBalances[accountIndex] || 0) / web3_js.LAMPORTS_PER_SOL;
1359
+ afterBalance = Number(tx.meta.postBalances[accountIndex] || 0) / web3_js.LAMPORTS_PER_SOL;
1360
+ }
1361
+ history.push({
1362
+ signature: sigInfo.signature,
1363
+ slot,
1364
+ epoch: slotToEpoch(slot, cluster),
1365
+ type,
1366
+ amount,
1367
+ beforeBalance,
1368
+ afterBalance
1369
+ });
1431
1370
  }
1432
1371
  } catch (error) {
1433
1372
  console.error(`Error processing transaction ${sigInfo.signature}:`, error);
1434
1373
  }
1435
1374
  }
1436
- return history.toSorted((a, b) => b.slot - a.slot);
1437
- }
1438
- /**
1439
- * Get full transaction history by paginating through results
1440
- * @param voteAccount
1441
- * @param pageSize
1442
- */
1443
- async getFullHistory(voteAccount, pageSize = 100) {
1444
- const allHistory = [];
1445
- let before;
1446
- while (true) {
1447
- const batch = await this.getHistory(voteAccount, {
1448
- limit: pageSize,
1449
- before
1450
- });
1451
- if (batch.length === 0) {
1452
- break;
1453
- }
1454
- allHistory.push(...batch);
1455
- before = batch.at(-1)?.signature;
1456
- if (batch.length < pageSize) {
1457
- break;
1458
- }
1459
- }
1460
- return allHistory;
1375
+ return history.sort((a, b) => b.slot - a.slot);
1461
1376
  }
1462
1377
  /**
1463
1378
  * Get instruction discriminator from IDL
@@ -1474,6 +1389,65 @@ var JBondClient = class _JBondClient {
1474
1389
  }
1475
1390
  return new Uint8Array(instruction.discriminator);
1476
1391
  }
1392
+ async fetchSignaturesForValidator(validatorBondAccount, options) {
1393
+ const sigs = await this.connection.getSignaturesForAddress(
1394
+ validatorBondAccount,
1395
+ {
1396
+ limit: options?.limit || 1e3,
1397
+ before: options?.before,
1398
+ until: options?.until
1399
+ }
1400
+ );
1401
+ return sigs.filter((s) => !s.err);
1402
+ }
1403
+ // Fetch parsed transactions in batches to avoid rate limits
1404
+ async fetchParsedTransactions(signatureStrings, batchSize = 100) {
1405
+ const allTxs = [];
1406
+ for (let i = 0; i < signatureStrings.length; i += batchSize) {
1407
+ const batch = signatureStrings.slice(i, i + batchSize);
1408
+ const txs = await this.connection.getParsedTransactions(batch, {
1409
+ maxSupportedTransactionVersion: 0
1410
+ });
1411
+ allTxs.push(...txs);
1412
+ }
1413
+ return allTxs;
1414
+ }
1415
+ // Decode instruction data to determine transaction type and amount
1416
+ decodeInstructionData(data) {
1417
+ if (!data) {
1418
+ return { type: null, amount: 0 };
1419
+ }
1420
+ try {
1421
+ const dataBuffer = bs58__default.default.decode(data);
1422
+ if (dataBuffer.length < 16) {
1423
+ return { type: null, amount: 0 };
1424
+ }
1425
+ const discriminator = dataBuffer.slice(0, 8);
1426
+ const amountBytes = dataBuffer.slice(8, 16);
1427
+ const amountBN = new anchor.BN(amountBytes, "le");
1428
+ const amount = amountBN.toNumber() / web3_js.LAMPORTS_PER_SOL;
1429
+ const bondInitDiscriminator = this.getInstructionDiscriminator("register");
1430
+ const bondTopUpDiscriminator = this.getInstructionDiscriminator("topUp");
1431
+ const withdrawCompensationDiscriminator = this.getInstructionDiscriminator("claim");
1432
+ const bondWithdrawDiscriminator = this.getInstructionDiscriminator("withdraw");
1433
+ if (Buffer.from(discriminator).equals(Buffer.from(bondInitDiscriminator))) {
1434
+ return { type: "deposit" /* Deposit */, amount };
1435
+ }
1436
+ if (Buffer.from(discriminator).equals(Buffer.from(bondTopUpDiscriminator))) {
1437
+ return { type: "deposit" /* Deposit */, amount };
1438
+ }
1439
+ if (Buffer.from(discriminator).equals(Buffer.from(withdrawCompensationDiscriminator))) {
1440
+ return { type: "compensation" /* Compensation */, amount };
1441
+ }
1442
+ if (Buffer.from(discriminator).equals(Buffer.from(bondWithdrawDiscriminator))) {
1443
+ return { type: "withdrawal" /* Withdrawal */, amount };
1444
+ }
1445
+ return { type: null, amount: 0 };
1446
+ } catch (err) {
1447
+ console.warn("Failed to decode instruction data", err);
1448
+ return { type: null, amount: 0 };
1449
+ }
1450
+ }
1477
1451
  };
1478
1452
 
1479
1453
  exports.BondClientEnv = BondClientEnv;