2018-10-06 10:36:59 -07:00
|
|
|
// @flow
|
|
|
|
|
|
|
|
import {Connection, Transaction} from '..';
|
|
|
|
|
|
|
|
import {sleep} from './sleep';
|
|
|
|
|
|
|
|
import type {Account} from '..';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sign, send and confirm a transaction
|
|
|
|
*/
|
|
|
|
export async function sendAndConfirmTransaction(
|
|
|
|
connection: Connection,
|
|
|
|
from: Account,
|
|
|
|
transaction: Transaction,
|
|
|
|
runtimeErrorOk: boolean = false
|
|
|
|
): Promise<void> {
|
|
|
|
|
2018-10-23 13:10:08 -07:00
|
|
|
let sendRetries = 3;
|
2018-10-06 10:36:59 -07:00
|
|
|
for (;;) {
|
2018-10-23 13:10:08 -07:00
|
|
|
const start = Date.now();
|
|
|
|
const 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) ) {
|
2018-10-23 08:35:20 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-23 13:10:08 -07:00
|
|
|
if (status !== 'AccountInUse' || --sendRetries <= 0) {
|
|
|
|
throw new Error(`Transaction ${signature} failed (${status})`);
|
2018-10-06 10:36:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|