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