fix: Appease flow

This commit is contained in:
Tyera Eulberg 2019-04-10 14:40:49 -07:00 committed by Michael Vines
parent 663f9c76d8
commit 507fac06ee
6 changed files with 44 additions and 41 deletions

View File

@ -53,12 +53,12 @@ declare module '@solana/web3.js' {
keyedAccountInfo: KeyedAccountInfo, keyedAccountInfo: KeyedAccountInfo,
) => void; ) => void;
declare export type SignatureStatus = declare export type SignatureSuccess = {|
| 'Confirmed' Ok: null,
| 'AccountInUse' |};
| 'SignatureNotFound' declare export type TransactionError = {|
| 'ProgramRuntimeError' Err: Object,
| 'GenericFailure'; |};
declare export class Connection { declare export class Connection {
constructor(endpoint: string): Connection; constructor(endpoint: string): Connection;
@ -67,7 +67,7 @@ declare module '@solana/web3.js' {
confirmTransaction(signature: TransactionSignature): Promise<boolean>; confirmTransaction(signature: TransactionSignature): Promise<boolean>;
getSignatureStatus( getSignatureStatus(
signature: TransactionSignature, signature: TransactionSignature,
): Promise<SignatureStatus>; ): Promise<SignatureSuccess | TransactionError | null>;
getTransactionCount(): Promise<number>; getTransactionCount(): Promise<number>;
getRecentBlockhash(): Promise<Blockhash>; getRecentBlockhash(): Promise<Blockhash>;
requestAirdrop( requestAirdrop(

View File

@ -126,11 +126,8 @@ const ConfirmTransactionRpcResult = jsonRpcResult('boolean');
const GetSignatureStatusRpcResult = jsonRpcResult( const GetSignatureStatusRpcResult = jsonRpcResult(
struct.union([ struct.union([
'null', 'null',
struct.union([ struct.union([struct({Ok: 'null'}), struct({Err: 'object'})]),
struct({Ok: 'null'}), ]),
struct({Err: 'string'})
])
])
); );
/** /**
@ -212,16 +209,22 @@ type ProgramAccountSubscriptionInfo = {
}; };
/** /**
* Possible signature status values * Signature status: Success
* *
* @typedef {string} SignatureStatus * @typedef {Object} SignatureSuccess
*/ */
export type SignatureStatus = export type SignatureSuccess = {|
| 'Confirmed' Ok: null,
| 'AccountInUse' |};
| 'SignatureNotFound'
| 'ProgramRuntimeError' /**
| 'GenericFailure'; * Signature status: TransactionError
*
* @typedef {Object} TransactionError
*/
export type TransactionError = {|
Err: Object,
|};
/** /**
* A connection to a fullnode JSON RPC endpoint * A connection to a fullnode JSON RPC endpoint
@ -338,7 +341,7 @@ export class Connection {
*/ */
async getSignatureStatus( async getSignatureStatus(
signature: TransactionSignature, signature: TransactionSignature,
): Promise<SignatureStatus> { ): Promise<SignatureSuccess | TransactionError | null> {
const unsafeRes = await this._rpcRequest('getSignatureStatus', [signature]); const unsafeRes = await this._rpcRequest('getSignatureStatus', [signature]);
const res = GetSignatureStatusRpcResult(unsafeRes); const res = GetSignatureStatusRpcResult(unsafeRes);
if (res.error) { if (res.error) {

View File

@ -16,11 +16,11 @@ export async function sendAndConfirmRawTransaction(
let signature = await connection.sendRawTransaction(rawTransaction); let signature = await connection.sendRawTransaction(rawTransaction);
// Wait up to a couple slots for a confirmation // Wait up to a couple slots for a confirmation
let status = ''; let status = null;
let statusRetries = 6; let statusRetries = 6;
for (;;) { for (;;) {
status = await connection.getSignatureStatus(signature); status = await connection.getSignatureStatus(signature);
if (status !== 'SignatureNotFound') { if (status) {
break; break;
} }
@ -32,14 +32,14 @@ export async function sendAndConfirmRawTransaction(
throw new Error( throw new Error(
`Raw Transaction '${signature}' was not confirmed in ${duration.toFixed( `Raw Transaction '${signature}' was not confirmed in ${duration.toFixed(
2, 2,
)} seconds (${status})`, )} seconds (${JSON.stringify(status)})`,
); );
} }
} }
if (status === 'Confirmed') { if (status && 'Ok' in status) {
return signature; return signature;
} }
throw new Error(`Raw transaction ${signature} failed (${status})`); throw new Error(`Raw transaction ${signature} failed (${JSON.stringify(status)})`);
} }

View File

@ -24,7 +24,7 @@ export async function sendAndConfirmTransaction(
signature = await connection.sendTransaction(transaction, ...signers); signature = await connection.sendTransaction(transaction, ...signers);
// Wait up to a couple slots for a confirmation // Wait up to a couple slots for a confirmation
let status = 'SignatureNotFound'; let status = null;
let statusRetries = 6; let statusRetries = 6;
for (;;) { for (;;) {
status = await connection.getSignatureStatus(signature); status = await connection.getSignatureStatus(signature);
@ -39,7 +39,7 @@ export async function sendAndConfirmTransaction(
await sleep((500 * DEFAULT_TICKS_PER_SLOT) / NUM_TICKS_PER_SECOND); await sleep((500 * DEFAULT_TICKS_PER_SLOT) / NUM_TICKS_PER_SECOND);
} }
if ('Ok' in status) { if (status && 'Ok' in status) {
break; break;
} }
if (--sendRetries <= 0) { if (--sendRetries <= 0) {
@ -47,12 +47,12 @@ export async function sendAndConfirmTransaction(
throw new Error( throw new Error(
`Transaction '${signature}' was not confirmed in ${duration.toFixed( `Transaction '${signature}' was not confirmed in ${duration.toFixed(
2, 2,
)} seconds (${status})`, )} seconds (${JSON.stringify(status)})`,
); );
} }
if ('Err' in status && !status.includes('AccountInUse')) { if (status && status.Err && !('AccountInUse' in status.Err)) {
throw new Error(`Transaction ${signature} failed (${status})`); throw new Error(`Transaction ${signature} failed (${JSON.stringify(status)})`);
} }
// Retry in 0..100ms to try to avoid another AccountInUse collision // Retry in 0..100ms to try to avoid another AccountInUse collision

View File

@ -338,12 +338,12 @@ test('transaction', async () => {
}, },
{ {
error: null, error: null,
result: 'Confirmed', result: {Ok: null},
}, },
]); ]);
await expect(connection.getSignatureStatus(signature)).resolves.toEqual( await expect(connection.getSignatureStatus(signature)).resolves.toEqual({
{'Ok': null}, Ok: null,
); });
mockRpc.push([ mockRpc.push([
url, url,
@ -410,9 +410,9 @@ test('multi-instruction transaction', async () => {
expect(++i).toBeLessThan(10); expect(++i).toBeLessThan(10);
await sleep(500); await sleep(500);
} }
await expect(connection.getSignatureStatus(signature)).resolves.toEqual( await expect(connection.getSignatureStatus(signature)).resolves.toEqual({
{'Ok': null}, Ok: null,
); });
expect(await connection.getBalance(accountFrom.publicKey)).toBe(12); expect(await connection.getBalance(accountFrom.publicKey)).toBe(12);
expect(await connection.getBalance(accountTo.publicKey)).toBe(21); expect(await connection.getBalance(accountTo.publicKey)).toBe(21);

View File

@ -11,7 +11,7 @@ import {sleep} from '../src/util/sleep';
// The default of 5 seconds is too slow for live testing sometimes // The default of 5 seconds is too slow for live testing sometimes
jest.setTimeout(60000); jest.setTimeout(60000);
function mockGetSignatureStatus(result: string = 'Confirmed') { function mockGetSignatureStatus(result: Object = {Ok: null}) {
mockRpc.push([ mockRpc.push([
url, url,
{ {
@ -58,7 +58,7 @@ test('create new token', async () => {
// mock Token.newAccount() transaction // mock Token.newAccount() transaction
mockSendTransaction(); mockSendTransaction();
mockGetSignatureStatus('SignatureNotFound'); mockGetSignatureStatus(null);
mockGetSignatureStatus(); mockGetSignatureStatus();
// mock SystemProgram.createAccount transaction for Token.createNewToken() // mock SystemProgram.createAccount transaction for Token.createNewToken()
@ -67,7 +67,7 @@ test('create new token', async () => {
// mock Token.createNewToken() transaction // mock Token.createNewToken() transaction
mockSendTransaction(); mockSendTransaction();
mockGetSignatureStatus('SignatureNotFound'); mockGetSignatureStatus(null);
mockGetSignatureStatus(); mockGetSignatureStatus();
} }