UNPKG

@bagsfm/bags-sdk

Version:

TypeScript SDK for Bags

123 lines 5.04 kB
"use strict"; 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