UNPKG

@openocean.finance/widget

Version:

Openocean Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.

180 lines (162 loc) 5.16 kB
/** * Solana Transaction Sending Service * * This module handles sending and confirming transactions on Solana blockchain */ import { BlockhashWithExpiryBlockHeight, Connection } from "@solana/web3.js"; /** * Delay execution helper * @param ms Delay time in milliseconds */ const delay = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms)); /** * Transaction sending and confirmation parameters interface */ interface SolanaTransactionParams { /** Solana RPC connection instance */ connection: Connection; /** Serialized transaction data */ serializedTransaction: Buffer; /** Blockhash with expiry block height */ blockhashWithExpiryBlockHeight?: BlockhashWithExpiryBlockHeight; /** Transaction process object */ process?: any; /** Route update callback function */ updateRouteHook?: (route: any) => void; } /** * Send raw transaction to Solana network * * @param connection Solana RPC connection instance * @param serializedTransaction Serialized transaction data * @param process Transaction process object * @param updateRouteHook Route update callback function * @returns Transaction hash */ async function sendSolanaTransaction( connection: Connection, serializedTransaction: Buffer, process: any, updateRouteHook?: (route: any) => void ): Promise<string> { try { // Send transaction to network const txid = await connection.sendRawTransaction( serializedTransaction, { skipPreflight: true, } ); console.log('Transaction sent:', txid); // Update transaction status to pending if (process && updateRouteHook) { process.status = 'PENDING'; process.txHash = txid; process.message = 'Transaction pending'; updateRouteHook(process.route); } return txid; } catch (error) { console.error('Failed to send transaction:', error); if (process && updateRouteHook) { process.status = 'FAILED'; process.message = error instanceof Error ? error.message : 'Failed to send transaction'; updateRouteHook(process.route); } throw error; } } /** * Confirm Solana transaction status * * @param connection Solana RPC connection instance * @param txid Transaction hash * @param process Transaction process object * @param updateRouteHook Route update callback function * @param maxRetries Maximum retry attempts * @returns Whether transaction succeeded */ async function confirmSolanaTransaction( connection: Connection, txid: string, process: any, updateRouteHook?: (route: any) => void, maxRetries: number = 30 ): Promise<boolean> { let retries = 0; while (retries < maxRetries) { try { // Get latest blockhash const latestBlockhash = await connection.getLatestBlockhash(); // Confirm transaction status const confirmation = await connection.confirmTransaction({ signature: txid, blockhash: latestBlockhash.blockhash, lastValidBlockHeight: latestBlockhash.lastValidBlockHeight }); // Check if transaction failed if (confirmation.value.err) { if (process && updateRouteHook) { process.status = 'FAILED'; process.message = 'Transaction failed on chain'; updateRouteHook(process.route); } return false; } // Transaction confirmed successfully if (process && updateRouteHook) { process.status = 'DONE'; process.doneAt = Date.now(); process.message = 'Transaction confirmed'; updateRouteHook(process.route); } return true; } catch (error) { console.warn('Confirmation attempt failed:', error); await delay(2000); // Wait 2 seconds before retrying retries++; } } // Exceeded maximum retry attempts if (process && updateRouteHook) { process.status = 'FAILED'; process.message = 'Transaction confirmation timeout'; updateRouteHook(process.route); } throw new Error('Transaction confirmation timeout'); } /** * Send and wait for Solana transaction confirmation * * @param params Transaction parameters * @returns Transaction response and hash */ export async function sendAndConfirmSolanaTransaction({ connection, serializedTransaction, process, updateRouteHook }: SolanaTransactionParams): Promise<any> { try { // Send transaction and get transaction hash const txid = await sendSolanaTransaction(connection, serializedTransaction, process, updateRouteHook); // Wait for transaction confirmation const success = await confirmSolanaTransaction(connection, txid, process, updateRouteHook); if (!success) { throw new Error('Transaction failed during confirmation'); } // Get transaction details const response = await connection.getTransaction(txid, { commitment: "confirmed", maxSupportedTransactionVersion: 0 }); if (!response) { throw new Error('Failed to fetch transaction details'); } return { response, txid }; } catch (error) { console.error('Transaction failed:', error); throw error; } }