// @flow import {Connection} from '../connection'; import {Transaction} from '../transaction'; import {sleep} from './sleep'; import type {Account} from '../account'; import type {TransactionSignature} from '../transaction'; /** * Sign, send and confirm a transaction */ export async function sendAndConfirmTransaction( connection: Connection, from: Account, transaction: Transaction, runtimeErrorOk: boolean = false ): Promise { let sendRetries = 10; let signature; for (;;) { const start = Date.now(); signature = await connection.sendTransaction(from, transaction); // Wait up to a couple seconds for a confirmation let status = 'SignatureNotFound'; let statusRetries = 4; for (;;) { status = await connection.getSignatureStatus(signature); if (status !== 'SignatureNotFound') { break; } await sleep(500); if (--statusRetries <= 0) { const duration = (Date.now() - start) / 1000; throw new Error(`Transaction '${signature}' was not confirmed in ${duration.toFixed(2)} seconds (${status})`); } } if ( (status === 'Confirmed') || (status === 'ProgramRuntimeError' && runtimeErrorOk) ) { break; } if (status !== 'AccountInUse' || --sendRetries <= 0) { throw new Error(`Transaction ${signature} failed (${status})`); } // Retry in 0..100ms to try to avoid another collision await sleep(Math.random() * 100); } return signature; }