import { Connection, Transaction, SendOptions } from '@solana/web3.js';
async function sendAndConfirmTransaction(
connection: Connection,
transaction: Transaction,
timeout: number = 30000, // 30 seconds default timeout
options?: SendOptions
): Promise<string> {
// Send the transaction
const signature = await connection.sendTransaction(transaction, options?.signers || [], {
...options,
skipPreflight: options?.skipPreflight || false
});
// Create a promise that will reject after the timeout
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`Transaction confirmation timeout after ${timeout}ms`));
}, timeout);
});
// Create the confirmation promise
const confirmationPromise = (async () => {
let done = false;
while (!done) {
// Get the status of the transaction
const response = await connection.getSignatureStatuses([signature]);
const status = response.value[0];
if (status) {
if (status.err) {
throw new Error(`Transaction failed: ${status.err.toString()}`);
}
// Check if we have enough confirmations
if (status.confirmationStatus === 'finalized') {
done = true;
return signature;
}
}
// Wait a bit before checking again
await new Promise(resolve => setTimeout(resolve, 1000));
}
})();
// Race between timeout and confirmation
try {
return await Promise.race([confirmationPromise, timeoutPromise]);
} catch (error) {
// If it's a timeout error, we should still return the signature
if (error.message.includes('timeout')) {
return signature;
}
throw error;
}
}
// Example usage
async function example() {
const connection = new Connection('CHAINSTACK_NODE');
const transaction = new Transaction();
// ... add your transaction instructions here ...
try {
const signature = await sendAndConfirmTransaction(connection, transaction, 60000, {
skipPreflight: false,
// ... other options
});
console.log('Transaction confirmed:', signature);
} catch (error) {
console.error('Transaction failed:', error);
}
}