@bagsfm/bags-sdk
Version:
TypeScript SDK for Bags
123 lines • 5.04 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.sleep = sleep;
exports.chunkArray = chunkArray;
exports.waitForSlotsToPass = waitForSlotsToPass;
exports.signAndSendTransaction = signAndSendTransaction;
exports.serializeVersionedTransaction = serializeVersionedTransaction;
exports.createTipTransaction = createTipTransaction;
exports.sendBundleAndConfirm = sendBundleAndConfirm;
const web3_js_1 = require("@solana/web3.js");
const bs58_1 = __importDefault(require("bs58"));
const constants_1 = require("../constants");
function sleep(ms) {
return new Promise((resolve) => globalThis.setTimeout(resolve, ms));
}
function chunkArray(array, size) {
const result = [];
for (let i = 0; i < array.length; i += size) {
result.push(array.slice(i, i + size));
}
return result;
}
async function waitForSlotsToPass(connection, commitment, slotsToPass = 1, pollIntervalMs = 400) {
try {
const initialSlot = await connection.getSlot(commitment);
const targetSlot = initialSlot + slotsToPass;
while (true) {
const currentSlot = await connection.getSlot(commitment);
if (currentSlot >= targetSlot) {
break;
}
await sleep(pollIntervalMs);
}
}
catch (error) {
console.error('Error waiting for slots to pass:', error);
await sleep(slotsToPass * 400);
}
}
async function signAndSendTransaction(connection, commitment, transaction, keypair, blockhash) {
transaction.sign([keypair]);
let finalBlockhash = blockhash;
if (!blockhash) {
finalBlockhash = await connection.getLatestBlockhash(commitment);
}
else {
finalBlockhash = blockhash;
}
const signature = await connection.sendTransaction(transaction, {
skipPreflight: true,
maxRetries: 0,
});
const confirmed = await connection.confirmTransaction({
blockhash: finalBlockhash.blockhash,
lastValidBlockHeight: finalBlockhash.lastValidBlockHeight,
signature: signature,
}, commitment);
if (confirmed.value.err) {
throw new Error(`Transaction failed: ${confirmed.value.err}`);
}
console.log('✅ Transaction confirmed:', signature);
return signature;
}
function serializeVersionedTransaction(transaction) {
if (typeof transaction === 'string') {
if (!bs58_1.default.decodeUnsafe(transaction)) {
throw new Error('Invalid base58 string');
}
return transaction;
}
const serialized = transaction.serialize();
return bs58_1.default.encode(serialized);
}
async function createTipTransaction(connection, commitment, payer, tipLamports, options = {}) {
if (tipLamports <= 0) {
throw new Error('Tip lamports must be greater than zero.');
}
const availableTipAccounts = constants_1.JITO_TIP_ACCOUNTS;
const tipAccount = options.tipAccount ?? availableTipAccounts[Math.floor(Math.random() * availableTipAccounts.length)];
if (!tipAccount) {
throw new Error('No tip account provided and no default tip accounts available.');
}
const recentBlockhash = options.blockhash ?? (await connection.getLatestBlockhash(commitment)).blockhash;
const tipInstruction = web3_js_1.SystemProgram.transfer({
fromPubkey: payer,
toPubkey: tipAccount,
lamports: tipLamports,
});
const transactionMessage = new web3_js_1.TransactionMessage({
payerKey: payer,
recentBlockhash,
instructions: [tipInstruction],
}).compileToV0Message();
return new web3_js_1.VersionedTransaction(transactionMessage);
}
async function sendBundleAndConfirm(signedTransactions, sdk, region = 'mainnet') {
const bundleId = await sdk.solana.sendBundle(signedTransactions, region);
const maxRetries = 10;
const retryDelayMs = 500;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const statusResponse = await sdk.solana.getBundleStatuses([bundleId], region);
if (statusResponse?.value?.length && statusResponse.value[0] != null) {
const bundleStatus = statusResponse.value[0];
const { confirmation_status, err, transactions } = bundleStatus;
if (confirmation_status === 'confirmed' || confirmation_status === 'finalized') {
const isSuccess = err == null || err.Ok == null;
if (!isSuccess) {
throw new Error('Bundle transactions failed with error');
}
if (!transactions?.length) {
throw new Error('Bundle confirmed but no transactions found');
}
return bundleId;
}
}
await sleep(retryDelayMs);
}
throw new Error(`Bundle confirmation timed out after ${maxRetries} attempts`);
}
//# sourceMappingURL=helpers.js.map