import type { Wallet } from "@saberhq/solana-contrib"; import type { ConfirmOptions, Connection, Signer, Transaction, } from "@solana/web3.js"; import { logError } from "./logError"; export async function executeMultiTransactions( connection: Connection, wallet: Wallet, txs: { tx: Transaction; signers?: Signer[] }[], config?: { batchSize?: number; errorHandler?: (e: unknown, ix: { sequence: number; total: number }) => T; successHandler?: (ix: { sequence: number; total: number; txid: string; }) => T; confirmOptions?: ConfirmOptions; } ): Promise { if (txs.length === 0) return []; const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash( config?.confirmOptions?.commitment || "processed" ); const signedTxs = await wallet.signAllTransactions( txs.map(({ tx, signers }) => { tx.recentBlockhash = blockhash; tx.feePayer = wallet.publicKey; if (signers?.length) { tx.partialSign(...signers); } return tx; }) ); const txIds = await Promise.all( signedTxs.map((signed) => connection.sendRawTransaction(signed.serialize(), config?.confirmOptions) ) ); const successfulTxIds: string[] = []; for (let i = 0; i < txIds.length; i++) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const signature = txIds[i]!; try { await connection.confirmTransaction( { blockhash, signature, lastValidBlockHeight, }, config?.confirmOptions?.commitment || "processed" ); if (config?.successHandler) { config?.successHandler({ sequence: i + 1, total: txIds.length, txid: signature, }); } successfulTxIds.push(signature); } catch (e) { if (config?.errorHandler) { config?.errorHandler(e, { sequence: i + 1, total: txIds.length, }); } logError(e); } } console.info("Successful txs", successfulTxIds); return successfulTxIds; }