feat: update transaction confirming apis
This commit is contained in:
		
				
					committed by
					
						 Michael Vines
						Michael Vines
					
				
			
			
				
	
			
			
			
						parent
						
							3b71ec1ff6
						
					
				
				
					commit
					839e93480c
				
			
							
								
								
									
										21
									
								
								web3.js/module.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								web3.js/module.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -210,14 +210,10 @@ declare module '@solana/web3.js' { | |||||||
|       endSlot: number, |       endSlot: number, | ||||||
|     ): Promise<Array<TransactionSignature>>; |     ): Promise<Array<TransactionSignature>>; | ||||||
|     getVoteAccounts(commitment?: Commitment): Promise<VoteAccountStatus>; |     getVoteAccounts(commitment?: Commitment): Promise<VoteAccountStatus>; | ||||||
|     confirmTransactionAndContext( |  | ||||||
|       signature: TransactionSignature, |  | ||||||
|       commitment?: Commitment, |  | ||||||
|     ): Promise<RpcResponseAndContext<boolean>>; |  | ||||||
|     confirmTransaction( |     confirmTransaction( | ||||||
|       signature: TransactionSignature, |       signature: TransactionSignature, | ||||||
|       commitment?: Commitment, |       confirmations?: number, | ||||||
|     ): Promise<boolean>; |     ): Promise<RpcResponseAndContext<SignatureStatus | null>>; | ||||||
|     getSlot(commitment?: Commitment): Promise<number>; |     getSlot(commitment?: Commitment): Promise<number>; | ||||||
|     getSlotLeader(commitment?: Commitment): Promise<string>; |     getSlotLeader(commitment?: Commitment): Promise<string>; | ||||||
|     getSignatureStatus( |     getSignatureStatus( | ||||||
| @@ -247,7 +243,7 @@ declare module '@solana/web3.js' { | |||||||
|     ): Promise<TransactionSignature>; |     ): Promise<TransactionSignature>; | ||||||
|     sendTransaction( |     sendTransaction( | ||||||
|       transaction: Transaction, |       transaction: Transaction, | ||||||
|       ...signers: Array<Account> |       signers: Array<Account>, | ||||||
|     ): Promise<TransactionSignature>; |     ): Promise<TransactionSignature>; | ||||||
|     sendEncodedTransaction( |     sendEncodedTransaction( | ||||||
|       encodedTransaction: string, |       encodedTransaction: string, | ||||||
| @@ -769,20 +765,15 @@ declare module '@solana/web3.js' { | |||||||
|   export function sendAndConfirmTransaction( |   export function sendAndConfirmTransaction( | ||||||
|     connection: Connection, |     connection: Connection, | ||||||
|     transaction: Transaction, |     transaction: Transaction, | ||||||
|     ...signers: Array<Account> |     signers: Array<Account>, | ||||||
|   ): Promise<TransactionSignature>; |     confirmations?: number, | ||||||
|  |  | ||||||
|   export function sendAndConfirmRecentTransaction( |  | ||||||
|     connection: Connection, |  | ||||||
|     transaction: Transaction, |  | ||||||
|     ...signers: Array<Account> |  | ||||||
|   ): Promise<TransactionSignature>; |   ): Promise<TransactionSignature>; | ||||||
|  |  | ||||||
|   // === src/util/send-and-confirm-raw-transaction.js === |   // === src/util/send-and-confirm-raw-transaction.js === | ||||||
|   export function sendAndConfirmRawTransaction( |   export function sendAndConfirmRawTransaction( | ||||||
|     connection: Connection, |     connection: Connection, | ||||||
|     wireTransaction: Buffer, |     wireTransaction: Buffer, | ||||||
|     commitment?: Commitment, |     confirmations?: number, | ||||||
|   ): Promise<TransactionSignature>; |   ): Promise<TransactionSignature>; | ||||||
|  |  | ||||||
|   // === src/util/cluster.js === |   // === src/util/cluster.js === | ||||||
|   | |||||||
| @@ -223,14 +223,10 @@ declare module '@solana/web3.js' { | |||||||
|       endSlot: number, |       endSlot: number, | ||||||
|     ): Promise<Array<TransactionSignature>>; |     ): Promise<Array<TransactionSignature>>; | ||||||
|     getVoteAccounts(commitment: ?Commitment): Promise<VoteAccountStatus>; |     getVoteAccounts(commitment: ?Commitment): Promise<VoteAccountStatus>; | ||||||
|     confirmTransactionAndContext( |  | ||||||
|       signature: TransactionSignature, |  | ||||||
|       commitment: ?Commitment, |  | ||||||
|     ): Promise<RpcResponseAndContext<boolean>>; |  | ||||||
|     confirmTransaction( |     confirmTransaction( | ||||||
|       signature: TransactionSignature, |       signature: TransactionSignature, | ||||||
|       commitment: ?Commitment, |       confirmations: ?number, | ||||||
|     ): Promise<boolean>; |     ): Promise<RpcResponseAndContext<SignatureStatus | null>>; | ||||||
|     getSlot(commitment: ?Commitment): Promise<number>; |     getSlot(commitment: ?Commitment): Promise<number>; | ||||||
|     getSlotLeader(commitment: ?Commitment): Promise<string>; |     getSlotLeader(commitment: ?Commitment): Promise<string>; | ||||||
|     getSignatureStatus( |     getSignatureStatus( | ||||||
| @@ -260,7 +256,7 @@ declare module '@solana/web3.js' { | |||||||
|     ): Promise<TransactionSignature>; |     ): Promise<TransactionSignature>; | ||||||
|     sendTransaction( |     sendTransaction( | ||||||
|       transaction: Transaction, |       transaction: Transaction, | ||||||
|       ...signers: Array<Account> |       signers: Array<Account>, | ||||||
|     ): Promise<TransactionSignature>; |     ): Promise<TransactionSignature>; | ||||||
|     sendEncodedTransaction( |     sendEncodedTransaction( | ||||||
|       encodedTransaction: string, |       encodedTransaction: string, | ||||||
| @@ -784,20 +780,15 @@ declare module '@solana/web3.js' { | |||||||
|   declare export function sendAndConfirmTransaction( |   declare export function sendAndConfirmTransaction( | ||||||
|     connection: Connection, |     connection: Connection, | ||||||
|     transaction: Transaction, |     transaction: Transaction, | ||||||
|     ...signers: Array<Account> |     signers: Array<Account>, | ||||||
|   ): Promise<TransactionSignature>; |     confirmations: ?number, | ||||||
|  |  | ||||||
|   declare export function sendAndConfirmRecentTransaction( |  | ||||||
|     connection: Connection, |  | ||||||
|     transaction: Transaction, |  | ||||||
|     ...signers: Array<Account> |  | ||||||
|   ): Promise<TransactionSignature>; |   ): Promise<TransactionSignature>; | ||||||
|  |  | ||||||
|   // === src/util/send-and-confirm-raw-transaction.js === |   // === src/util/send-and-confirm-raw-transaction.js === | ||||||
|   declare export function sendAndConfirmRawTransaction( |   declare export function sendAndConfirmRawTransaction( | ||||||
|     connection: Connection, |     connection: Connection, | ||||||
|     wireTransaction: Buffer, |     wireTransaction: Buffer, | ||||||
|     commitment: ?Commitment, |     confirmations: ?number, | ||||||
|   ): Promise<TransactionSignature>; |   ): Promise<TransactionSignature>; | ||||||
|  |  | ||||||
|   // === src/util/cluster.js === |   // === src/util/cluster.js === | ||||||
|   | |||||||
| @@ -469,13 +469,6 @@ const GetProgramAccountsRpcResult = jsonRpcResult( | |||||||
|   struct.array([ProgramAccountInfoResult]), |   struct.array([ProgramAccountInfoResult]), | ||||||
| ); | ); | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Expected JSON RPC response for the "confirmTransaction" message |  | ||||||
|  */ |  | ||||||
| const ConfirmTransactionAndContextRpcResult = jsonRpcResultAndContext( |  | ||||||
|   'boolean', |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Expected JSON RPC response for the "getSlot" message |  * Expected JSON RPC response for the "getSlot" message | ||||||
|  */ |  */ | ||||||
| @@ -1063,35 +1056,44 @@ export class Connection { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * Confirm the transaction identified by the specified signature, return with context |  | ||||||
|    */ |  | ||||||
|   async confirmTransactionAndContext( |  | ||||||
|     signature: TransactionSignature, |  | ||||||
|     commitment: ?Commitment, |  | ||||||
|   ): Promise<RpcResponseAndContext<boolean>> { |  | ||||||
|     const args = this._argsWithCommitment([signature], commitment); |  | ||||||
|     const unsafeRes = await this._rpcRequest('confirmTransaction', args); |  | ||||||
|     const res = ConfirmTransactionAndContextRpcResult(unsafeRes); |  | ||||||
|     if (res.error) { |  | ||||||
|       throw new Error('failed to confirm transaction: ' + res.error.message); |  | ||||||
|     } |  | ||||||
|     assert(typeof res.result !== 'undefined'); |  | ||||||
|     return res.result; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Confirm the transaction identified by the specified signature |    * Confirm the transaction identified by the specified signature | ||||||
|    */ |    */ | ||||||
|   async confirmTransaction( |   async confirmTransaction( | ||||||
|     signature: TransactionSignature, |     signature: TransactionSignature, | ||||||
|     commitment: ?Commitment, |     confirmations: ?number, | ||||||
|   ): Promise<boolean> { |   ): Promise<RpcResponseAndContext<SignatureStatus | null>> { | ||||||
|     return await this.confirmTransactionAndContext(signature, commitment) |     const NUM_STATUS_RETRIES = 10; | ||||||
|       .then(x => x.value) |  | ||||||
|       .catch(e => { |     const MS_PER_SECOND = 1000; | ||||||
|         throw new Error('failed to confirm transaction: ' + e); |     const MS_PER_SLOT = | ||||||
|       }); |       (DEFAULT_TICKS_PER_SLOT / NUM_TICKS_PER_SECOND) * MS_PER_SECOND; | ||||||
|  |  | ||||||
|  |     let statusRetries = NUM_STATUS_RETRIES; | ||||||
|  |     let statusResponse = await this.getSignatureStatus(signature); | ||||||
|  |     for (;;) { | ||||||
|  |       const status = statusResponse.value; | ||||||
|  |       if (status) { | ||||||
|  |         // Received a status, if not an error wait for confirmation | ||||||
|  |         statusRetries = NUM_STATUS_RETRIES; | ||||||
|  |         if ( | ||||||
|  |           status.err || | ||||||
|  |           status.confirmations === null || | ||||||
|  |           (typeof confirmations === 'number' && | ||||||
|  |             status.confirmations >= confirmations) | ||||||
|  |         ) { | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       } else if (--statusRetries <= 0) { | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // Sleep for approximately half a slot | ||||||
|  |       await sleep(MS_PER_SLOT / 2); | ||||||
|  |       statusResponse = await this.getSignatureStatus(signature); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return statusResponse; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
| @@ -1474,7 +1476,7 @@ export class Connection { | |||||||
|    */ |    */ | ||||||
|   async sendTransaction( |   async sendTransaction( | ||||||
|     transaction: Transaction, |     transaction: Transaction, | ||||||
|     ...signers: Array<Account> |     signers: Array<Account>, | ||||||
|   ): Promise<TransactionSignature> { |   ): Promise<TransactionSignature> { | ||||||
|     if (transaction.nonceInfo) { |     if (transaction.nonceInfo) { | ||||||
|       transaction.sign(...signers); |       transaction.sign(...signers); | ||||||
|   | |||||||
| @@ -30,10 +30,7 @@ export { | |||||||
|   SYSVAR_REWARDS_PUBKEY, |   SYSVAR_REWARDS_PUBKEY, | ||||||
|   SYSVAR_STAKE_HISTORY_PUBKEY, |   SYSVAR_STAKE_HISTORY_PUBKEY, | ||||||
| } from './sysvar'; | } from './sysvar'; | ||||||
| export { | export {sendAndConfirmTransaction} from './util/send-and-confirm-transaction'; | ||||||
|   sendAndConfirmTransaction, |  | ||||||
|   sendAndConfirmRecentTransaction, |  | ||||||
| } from './util/send-and-confirm-transaction'; |  | ||||||
| export {sendAndConfirmRawTransaction} from './util/send-and-confirm-raw-transaction'; | export {sendAndConfirmRawTransaction} from './util/send-and-confirm-raw-transaction'; | ||||||
| export {clusterApiUrl} from './util/cluster'; | export {clusterApiUrl} from './util/cluster'; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -65,7 +65,12 @@ export class Loader { | |||||||
|         space: data.length, |         space: data.length, | ||||||
|         programId, |         programId, | ||||||
|       }); |       }); | ||||||
|       await sendAndConfirmTransaction(connection, transaction, payer, program); |       await sendAndConfirmTransaction( | ||||||
|  |         connection, | ||||||
|  |         transaction, | ||||||
|  |         [payer, program], | ||||||
|  |         1, | ||||||
|  |       ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const dataLayout = BufferLayout.struct([ |     const dataLayout = BufferLayout.struct([ | ||||||
| @@ -102,7 +107,7 @@ export class Loader { | |||||||
|         data, |         data, | ||||||
|       }); |       }); | ||||||
|       transactions.push( |       transactions.push( | ||||||
|         sendAndConfirmTransaction(connection, transaction, payer, program), |         sendAndConfirmTransaction(connection, transaction, [payer, program], 1), | ||||||
|       ); |       ); | ||||||
|  |  | ||||||
|       // Delay ~1 tick between write transactions in an attempt to reduce AccountInUse errors |       // Delay ~1 tick between write transactions in an attempt to reduce AccountInUse errors | ||||||
| @@ -143,7 +148,12 @@ export class Loader { | |||||||
|         programId, |         programId, | ||||||
|         data, |         data, | ||||||
|       }); |       }); | ||||||
|       await sendAndConfirmTransaction(connection, transaction, payer, program); |       await sendAndConfirmTransaction( | ||||||
|  |         connection, | ||||||
|  |         transaction, | ||||||
|  |         [payer, program], | ||||||
|  |         1, | ||||||
|  |       ); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,54 +1,34 @@ | |||||||
| // @flow | // @flow | ||||||
|  |  | ||||||
| import {Connection} from '../connection'; | import {Connection} from '../connection'; | ||||||
| import type {Commitment} from '../connection'; |  | ||||||
| import {sleep} from './sleep'; |  | ||||||
| import type {TransactionSignature} from '../transaction'; | import type {TransactionSignature} from '../transaction'; | ||||||
| import {DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND} from '../timing'; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sign, send and confirm a raw transaction |  * Send and confirm a raw transaction | ||||||
|  */ |  */ | ||||||
| export async function sendAndConfirmRawTransaction( | export async function sendAndConfirmRawTransaction( | ||||||
|   connection: Connection, |   connection: Connection, | ||||||
|   rawTransaction: Buffer, |   rawTransaction: Buffer, | ||||||
|   commitment: ?Commitment, |   confirmations: ?number, | ||||||
| ): Promise<TransactionSignature> { | ): Promise<TransactionSignature> { | ||||||
|   const start = Date.now(); |   const start = Date.now(); | ||||||
|   const statusCommitment = commitment || connection.commitment || 'max'; |   const signature = await connection.sendRawTransaction(rawTransaction); | ||||||
|   let signature = await connection.sendRawTransaction(rawTransaction); |   const status = (await connection.confirmTransaction(signature, confirmations)) | ||||||
|  |     .value; | ||||||
|  |  | ||||||
|   // Wait up to a couple slots for a confirmation |  | ||||||
|   let status = null; |  | ||||||
|   let statusRetries = 6; |  | ||||||
|   for (;;) { |  | ||||||
|     status = (await connection.getSignatureStatus(signature)).value; |  | ||||||
|   if (status) { |   if (status) { | ||||||
|       if (statusCommitment === 'max' && status.confirmations === null) { |     if (status.err) { | ||||||
|         break; |  | ||||||
|       } else if (statusCommitment === 'recent') { |  | ||||||
|         break; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Sleep for approximately half a slot |  | ||||||
|     await sleep((500 * DEFAULT_TICKS_PER_SLOT) / NUM_TICKS_PER_SECOND); |  | ||||||
|  |  | ||||||
|     if (--statusRetries <= 0) { |  | ||||||
|       const duration = (Date.now() - start) / 1000; |  | ||||||
|       throw new Error( |  | ||||||
|         `Raw Transaction '${signature}' was not confirmed in ${duration.toFixed( |  | ||||||
|           2, |  | ||||||
|         )} seconds (${JSON.stringify(status)})`, |  | ||||||
|       ); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   if (status && !status.err) { |  | ||||||
|     return signature; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|       throw new Error( |       throw new Error( | ||||||
|         `Raw transaction ${signature} failed (${JSON.stringify(status)})`, |         `Raw transaction ${signature} failed (${JSON.stringify(status)})`, | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|  |     return signature; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const duration = (Date.now() - start) / 1000; | ||||||
|  |   throw new Error( | ||||||
|  |     `Raw transaction '${signature}' was not confirmed in ${duration.toFixed( | ||||||
|  |       2, | ||||||
|  |     )} seconds`, | ||||||
|  |   ); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,111 +1,52 @@ | |||||||
| // @flow | // @flow | ||||||
|  |  | ||||||
| import invariant from 'assert'; |  | ||||||
|  |  | ||||||
| import {Connection} from '../connection'; | import {Connection} from '../connection'; | ||||||
| import type {Commitment} from '../connection'; |  | ||||||
| import {Transaction} from '../transaction'; | import {Transaction} from '../transaction'; | ||||||
| import {sleep} from './sleep'; | import {sleep} from './sleep'; | ||||||
| import type {Account} from '../account'; | import type {Account} from '../account'; | ||||||
| import type {TransactionSignature} from '../transaction'; | import type {TransactionSignature} from '../transaction'; | ||||||
| import {DEFAULT_TICKS_PER_SLOT, NUM_TICKS_PER_SECOND} from '../timing'; |  | ||||||
|  |  | ||||||
| const MS_PER_SECOND = 1000; |  | ||||||
| const MS_PER_SLOT = |  | ||||||
|   (DEFAULT_TICKS_PER_SLOT / NUM_TICKS_PER_SECOND) * MS_PER_SECOND; |  | ||||||
|  |  | ||||||
| const NUM_SEND_RETRIES = 10; | const NUM_SEND_RETRIES = 10; | ||||||
| const NUM_STATUS_RETRIES = 10; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Sign, send and confirm a transaction with recent commitment level |  * Sign, send and confirm a transaction. | ||||||
|  */ |  * | ||||||
| export async function sendAndConfirmRecentTransaction( |  * If `confirmations` count is not specified, wait for transaction to be finalized. | ||||||
|   connection: Connection, |  | ||||||
|   transaction: Transaction, |  | ||||||
|   ...signers: Array<Account> |  | ||||||
| ): Promise<TransactionSignature> { |  | ||||||
|   return await _sendAndConfirmTransaction( |  | ||||||
|     connection, |  | ||||||
|     transaction, |  | ||||||
|     signers, |  | ||||||
|     'recent', |  | ||||||
|   ); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Sign, send and confirm a transaction |  | ||||||
|  */ |  */ | ||||||
| export async function sendAndConfirmTransaction( | export async function sendAndConfirmTransaction( | ||||||
|   connection: Connection, |  | ||||||
|   transaction: Transaction, |  | ||||||
|   ...signers: Array<Account> |  | ||||||
| ): Promise<TransactionSignature> { |  | ||||||
|   return await _sendAndConfirmTransaction(connection, transaction, signers); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function _sendAndConfirmTransaction( |  | ||||||
|   connection: Connection, |   connection: Connection, | ||||||
|   transaction: Transaction, |   transaction: Transaction, | ||||||
|   signers: Array<Account>, |   signers: Array<Account>, | ||||||
|   commitment: ?Commitment, |   confirmations: ?number, | ||||||
| ): Promise<TransactionSignature> { | ): Promise<TransactionSignature> { | ||||||
|   const statusCommitment = commitment || connection.commitment || 'max'; |  | ||||||
|  |  | ||||||
|   let sendRetries = NUM_SEND_RETRIES; |  | ||||||
|   let signature; |  | ||||||
|  |  | ||||||
|   for (;;) { |  | ||||||
|   const start = Date.now(); |   const start = Date.now(); | ||||||
|     signature = await connection.sendTransaction(transaction, ...signers); |   let sendRetries = NUM_SEND_RETRIES; | ||||||
|  |  | ||||||
|     // Wait up to a couple slots for a confirmation |  | ||||||
|     let status = null; |  | ||||||
|     let statusRetries = NUM_STATUS_RETRIES; |  | ||||||
|   for (;;) { |   for (;;) { | ||||||
|       status = (await connection.getSignatureStatus(signature)).value; |     const signature = await connection.sendTransaction(transaction, signers); | ||||||
|       if (status) { |     const status = ( | ||||||
|         // Recieved a status, if not an error wait for confirmation |       await connection.confirmTransaction(signature, confirmations) | ||||||
|         statusRetries = NUM_STATUS_RETRIES; |     ).value; | ||||||
|         if ( |  | ||||||
|           status.err || |  | ||||||
|           status.confirmations === null || |  | ||||||
|           (statusCommitment === 'recent' && status.confirmations >= 1) |  | ||||||
|         ) { |  | ||||||
|           break; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       if (--statusRetries <= 0) { |  | ||||||
|         break; |  | ||||||
|       } |  | ||||||
|       // Sleep for approximately half a slot |  | ||||||
|       await sleep(MS_PER_SLOT / 2); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (status) { |     if (status) { | ||||||
|       if (!status.err) { |       if (status.err) { | ||||||
|         break; |  | ||||||
|       } else if (!('AccountInUse' in status.err)) { |  | ||||||
|         throw new Error( |         throw new Error( | ||||||
|           `Transaction ${signature} failed (${JSON.stringify(status)})`, |           `Transaction ${signature} failed (${JSON.stringify(status)})`, | ||||||
|         ); |         ); | ||||||
|       } |       } | ||||||
|  |       return signature; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (--sendRetries <= 0) { |     if (--sendRetries <= 0) break; | ||||||
|       const duration = (Date.now() - start) / 1000; |  | ||||||
|       throw new Error( |  | ||||||
|         `Transaction '${signature}' was not confirmed in ${duration.toFixed( |  | ||||||
|           2, |  | ||||||
|         )} seconds (${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 | ||||||
|     await sleep(Math.random() * 100); |     await sleep(Math.random() * 100); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   invariant(signature !== undefined); |   const duration = (Date.now() - start) / 1000; | ||||||
|   return signature; |   throw new Error( | ||||||
|  |     `Transaction was not confirmed in ${duration.toFixed( | ||||||
|  |       2, | ||||||
|  |     )} seconds (${JSON.stringify(status)})`, | ||||||
|  |   ); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ test('load BPF C program', async () => { | |||||||
|     keys: [{pubkey: from.publicKey, isSigner: true, isWritable: true}], |     keys: [{pubkey: from.publicKey, isSigner: true, isWritable: true}], | ||||||
|     programId: program.publicKey, |     programId: program.publicKey, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmTransaction(connection, transaction, from); |   await sendAndConfirmTransaction(connection, transaction, [from], 1); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| test('load BPF Rust program', async () => { | test('load BPF Rust program', async () => { | ||||||
| @@ -73,5 +73,5 @@ test('load BPF Rust program', async () => { | |||||||
|     keys: [{pubkey: from.publicKey, isSigner: true, isWritable: true}], |     keys: [{pubkey: from.publicKey, isSigner: true, isWritable: true}], | ||||||
|     programId: program.publicKey, |     programId: program.publicKey, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmTransaction(connection, transaction, from); |   await sendAndConfirmTransaction(connection, transaction, [from], 1); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -14,6 +14,7 @@ import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch'; | |||||||
| import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash'; | import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash'; | ||||||
| import {url} from './url'; | import {url} from './url'; | ||||||
| import {sleep} from '../src/util/sleep'; | import {sleep} from '../src/util/sleep'; | ||||||
|  | import type {SignatureStatus, TransactionError} from '../src/connection'; | ||||||
|  |  | ||||||
| if (!mockRpcEnabled) { | if (!mockRpcEnabled) { | ||||||
|   // Testing max commitment level takes around 20s to complete |   // Testing max commitment level takes around 20s to complete | ||||||
| @@ -28,6 +29,29 @@ const errorResponse = { | |||||||
|   result: undefined, |   result: undefined, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | const verifySignatureStatus = ( | ||||||
|  |   status: SignatureStatus | null, | ||||||
|  |   err?: TransactionError, | ||||||
|  | ): SignatureStatus => { | ||||||
|  |   if (status === null) { | ||||||
|  |     expect(status).not.toBeNull(); | ||||||
|  |     throw new Error(); // unreachable | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   const expectedErr = err || null; | ||||||
|  |   expect(status.err).toEqual(expectedErr); | ||||||
|  |   expect(status.slot).toBeGreaterThanOrEqual(0); | ||||||
|  |   if (expectedErr !== null) return status; | ||||||
|  |  | ||||||
|  |   const confirmations = status.confirmations; | ||||||
|  |   if (typeof confirmations === 'number') { | ||||||
|  |     expect(confirmations).toBeGreaterThan(0); | ||||||
|  |   } else { | ||||||
|  |     expect(confirmations).toBeNull(); | ||||||
|  |   } | ||||||
|  |   return status; | ||||||
|  | }; | ||||||
|  |  | ||||||
| test('get account info - not found', async () => { | test('get account info - not found', async () => { | ||||||
|   const account = new Account(); |   const account = new Account(); | ||||||
|   const connection = new Connection(url); |   const connection = new Connection(url); | ||||||
| @@ -135,7 +159,7 @@ test('get program accounts', async () => { | |||||||
|     accountPubkey: account0.publicKey, |     accountPubkey: account0.publicKey, | ||||||
|     programId: programId.publicKey, |     programId: programId.publicKey, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmTransaction(connection, transaction, account0); |   await sendAndConfirmTransaction(connection, transaction, [account0], 1); | ||||||
|  |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
| @@ -180,7 +204,7 @@ test('get program accounts', async () => { | |||||||
|     programId: programId.publicKey, |     programId: programId.publicKey, | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   await sendAndConfirmTransaction(connection, transaction, account1); |   await sendAndConfirmTransaction(connection, transaction, [account1], 1); | ||||||
|  |  | ||||||
|   mockGetRecentBlockhash('recent'); |   mockGetRecentBlockhash('recent'); | ||||||
|   const {feeCalculator} = await connection.getRecentBlockhash(); |   const {feeCalculator} = await connection.getRecentBlockhash(); | ||||||
| @@ -493,8 +517,8 @@ test('confirm transaction - error', async () => { | |||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
|     { |     { | ||||||
|       method: 'confirmTransaction', |       method: 'getSignatureStatuses', | ||||||
|       params: [badTransactionSignature], |       params: [[badTransactionSignature]], | ||||||
|     }, |     }, | ||||||
|     errorResponse, |     errorResponse, | ||||||
|   ]); |   ]); | ||||||
| @@ -1367,15 +1391,17 @@ test('transaction failure', async () => { | |||||||
|     toPubkey: account.publicKey, |     toPubkey: account.publicKey, | ||||||
|     lamports: 10, |     lamports: 10, | ||||||
|   }); |   }); | ||||||
|   const signature = await connection.sendTransaction(transaction, account); |   const signature = await connection.sendTransaction(transaction, [account]); | ||||||
|  |  | ||||||
|  |   const expectedErr = {InstructionError: [0, 'AccountBorrowFailed']}; | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
|     { |     { | ||||||
|       method: 'confirmTransaction', |       method: 'getSignatureStatuses', | ||||||
|       params: [ |       params: [ | ||||||
|  |         [ | ||||||
|           '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', |           '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', | ||||||
|         {commitment: 'recent'}, |         ], | ||||||
|       ], |       ], | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -1384,16 +1410,23 @@ test('transaction failure', async () => { | |||||||
|         context: { |         context: { | ||||||
|           slot: 11, |           slot: 11, | ||||||
|         }, |         }, | ||||||
|         value: false, |         value: [ | ||||||
|  |           { | ||||||
|  |             slot: 0, | ||||||
|  |             confirmations: 1, | ||||||
|  |             status: {Err: expectedErr}, | ||||||
|  |             err: expectedErr, | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
|   ]); |   ]); | ||||||
|  |  | ||||||
|   // Wait for one confirmation |   // Wait for one confirmation | ||||||
|   await sleep(1000); |   const confirmResult = (await connection.confirmTransaction(signature, 1)) | ||||||
|   expect(await connection.confirmTransaction(signature)).toEqual(false); |     .value; | ||||||
|  |   verifySignatureStatus(confirmResult, expectedErr); | ||||||
|  |  | ||||||
|   const expectedErr = {InstructionError: [0, 'AccountBorrowFailed']}; |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
|     { |     { | ||||||
| @@ -1423,19 +1456,7 @@ test('transaction failure', async () => { | |||||||
|   ]); |   ]); | ||||||
|  |  | ||||||
|   const response = (await connection.getSignatureStatus(signature)).value; |   const response = (await connection.getSignatureStatus(signature)).value; | ||||||
|   if (response === null) { |   verifySignatureStatus(response, expectedErr); | ||||||
|     expect(response).not.toBeNull(); |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   expect(response.err).toEqual(expectedErr); |  | ||||||
|   expect(response.slot).toBeGreaterThanOrEqual(0); |  | ||||||
|   const responseConfirmations = response.confirmations; |  | ||||||
|   if (typeof responseConfirmations === 'number') { |  | ||||||
|     expect(responseConfirmations).toBeGreaterThan(0); |  | ||||||
|   } else { |  | ||||||
|     expect(responseConfirmations).toBeNull(); |  | ||||||
|   } |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
| test('transaction', async () => { | test('transaction', async () => { | ||||||
| @@ -1555,15 +1576,18 @@ test('transaction', async () => { | |||||||
|     toPubkey: accountTo.publicKey, |     toPubkey: accountTo.publicKey, | ||||||
|     lamports: 10, |     lamports: 10, | ||||||
|   }); |   }); | ||||||
|   const signature = await connection.sendTransaction(transaction, accountFrom); |   const signature = await connection.sendTransaction(transaction, [ | ||||||
|  |     accountFrom, | ||||||
|  |   ]); | ||||||
|  |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
|     { |     { | ||||||
|       method: 'confirmTransaction', |       method: 'getSignatureStatuses', | ||||||
|       params: [ |       params: [ | ||||||
|  |         [ | ||||||
|           '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', |           '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', | ||||||
|         {commitment: 'recent'}, |         ], | ||||||
|       ], |       ], | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -1572,24 +1596,22 @@ test('transaction', async () => { | |||||||
|         context: { |         context: { | ||||||
|           slot: 11, |           slot: 11, | ||||||
|         }, |         }, | ||||||
|         value: true, |         value: [ | ||||||
|  |           { | ||||||
|  |             slot: 0, | ||||||
|  |             confirmations: 1, | ||||||
|  |             status: {Ok: null}, | ||||||
|  |             err: null, | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
|   ]); |   ]); | ||||||
|  |  | ||||||
|   // Wait for one confirmation |   // Wait for one confirmation | ||||||
|   await sleep(1000); |   const confirmResult = (await connection.confirmTransaction(signature, 1)) | ||||||
|  |     .value; | ||||||
|   let i = 0; |   verifySignatureStatus(confirmResult); | ||||||
|   for (;;) { |  | ||||||
|     if (await connection.confirmTransaction(signature)) { |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|     console.log('not confirmed', signature); |  | ||||||
|     expect(mockRpcEnabled).toBe(false); |  | ||||||
|     expect(++i).toBeLessThan(10); |  | ||||||
|     await sleep(500); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
| @@ -1619,20 +1641,9 @@ test('transaction', async () => { | |||||||
|     }, |     }, | ||||||
|   ]); |   ]); | ||||||
|  |  | ||||||
|   const response = (await connection.getSignatureStatus(signature)).value; |   const response = verifySignatureStatus( | ||||||
|   if (response === null) { |     (await connection.getSignatureStatus(signature)).value, | ||||||
|     expect(response).not.toBeNull(); |   ); | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   expect(response.err).toBeNull(); |  | ||||||
|   expect(response.slot).toBeGreaterThanOrEqual(0); |  | ||||||
|   const responseConfirmations = response.confirmations; |  | ||||||
|   if (typeof responseConfirmations === 'number') { |  | ||||||
|     expect(responseConfirmations).toBeGreaterThan(0); |  | ||||||
|   } else { |  | ||||||
|     expect(responseConfirmations).toBeNull(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   const unprocessedSignature = |   const unprocessedSignature = | ||||||
|     '8WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk'; |     '8WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk'; | ||||||
| @@ -1670,28 +1681,22 @@ test('transaction', async () => { | |||||||
|     await connection.getSignatureStatuses([signature, unprocessedSignature]) |     await connection.getSignatureStatuses([signature, unprocessedSignature]) | ||||||
|   ).value; |   ).value; | ||||||
|   expect(responses.length).toEqual(2); |   expect(responses.length).toEqual(2); | ||||||
|  |  | ||||||
|   const firstResponse = responses[0]; |  | ||||||
|   expect(responses[1]).toBeNull(); |   expect(responses[1]).toBeNull(); | ||||||
|  |  | ||||||
|   if (firstResponse === null) { |   const firstResponse = verifySignatureStatus(responses[0]); | ||||||
|     expect(firstResponse).not.toBeNull(); |  | ||||||
|     return; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   expect(firstResponse.slot).toBeGreaterThanOrEqual(response.slot); |   expect(firstResponse.slot).toBeGreaterThanOrEqual(response.slot); | ||||||
|   expect(firstResponse.err).toEqual(response.err); |   expect(firstResponse.err).toEqual(response.err); | ||||||
|  |  | ||||||
|   const firstResponseConfirmations = firstResponse.confirmations; |   const responseConfirmations = response.confirmations; | ||||||
|   if ( |   if ( | ||||||
|     typeof responseConfirmations === 'number' && |     typeof responseConfirmations === 'number' && | ||||||
|     typeof firstResponseConfirmations === 'number' |     typeof firstResponse.confirmations === 'number' | ||||||
|   ) { |   ) { | ||||||
|     expect(firstResponseConfirmations).toBeGreaterThanOrEqual( |     expect(firstResponse.confirmations).toBeGreaterThanOrEqual( | ||||||
|       responseConfirmations, |       responseConfirmations, | ||||||
|     ); |     ); | ||||||
|   } else { |   } else { | ||||||
|     expect(firstResponseConfirmations).toBeNull(); |     expect(firstResponse.confirmations).toBeNull(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
| @@ -1775,21 +1780,12 @@ test('multi-instruction transaction', async () => { | |||||||
|       lamports: 100, |       lamports: 100, | ||||||
|     }), |     }), | ||||||
|   ); |   ); | ||||||
|   const signature = await connection.sendTransaction( |   const signature = await connection.sendTransaction(transaction, [ | ||||||
|     transaction, |  | ||||||
|     accountFrom, |     accountFrom, | ||||||
|     accountTo, |     accountTo, | ||||||
|   ); |   ]); | ||||||
|   let i = 0; |  | ||||||
|   for (;;) { |  | ||||||
|     if (await connection.confirmTransaction(signature)) { |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     expect(mockRpcEnabled).toBe(false); |   await connection.confirmTransaction(signature, 1); | ||||||
|     expect(++i).toBeLessThan(10); |  | ||||||
|     await sleep(500); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   const response = (await connection.getSignatureStatus(signature)).value; |   const response = (await connection.getSignatureStatus(signature)).value; | ||||||
|   if (response !== null) { |   if (response !== null) { | ||||||
| @@ -1839,7 +1835,7 @@ test('account change notification', async () => { | |||||||
|       toPubkey: programAccount.publicKey, |       toPubkey: programAccount.publicKey, | ||||||
|       lamports: balanceNeeded, |       lamports: balanceNeeded, | ||||||
|     }); |     }); | ||||||
|     await sendAndConfirmTransaction(connection, transaction, owner); |     await sendAndConfirmTransaction(connection, transaction, [owner], 1); | ||||||
|   } catch (err) { |   } catch (err) { | ||||||
|     await connection.removeAccountChangeListener(subscriptionId); |     await connection.removeAccountChangeListener(subscriptionId); | ||||||
|     throw err; |     throw err; | ||||||
| @@ -1903,7 +1899,7 @@ test('program account change notification', async () => { | |||||||
|       toPubkey: programAccount.publicKey, |       toPubkey: programAccount.publicKey, | ||||||
|       lamports: balanceNeeded, |       lamports: balanceNeeded, | ||||||
|     }); |     }); | ||||||
|     await sendAndConfirmTransaction(connection, transaction, owner); |     await sendAndConfirmTransaction(connection, transaction, [owner], 1); | ||||||
|   } catch (err) { |   } catch (err) { | ||||||
|     await connection.removeProgramAccountChangeListener(subscriptionId); |     await connection.removeProgramAccountChangeListener(subscriptionId); | ||||||
|     throw err; |     throw err; | ||||||
|   | |||||||
| @@ -103,7 +103,7 @@ test('create and query nonce account', async () => { | |||||||
|     authorizedPubkey: from.publicKey, |     authorizedPubkey: from.publicKey, | ||||||
|     lamports: minimumAmount, |     lamports: minimumAmount, | ||||||
|   }); |   }); | ||||||
|   await connection.sendTransaction(transaction, from, nonceAccount); |   await connection.sendTransaction(transaction, [from, nonceAccount]); | ||||||
|  |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
| @@ -222,7 +222,7 @@ test('create and query nonce account with seed', async () => { | |||||||
|     authorizedPubkey: from.publicKey, |     authorizedPubkey: from.publicKey, | ||||||
|     lamports: minimumAmount, |     lamports: minimumAmount, | ||||||
|   }); |   }); | ||||||
|   await connection.sendTransaction(transaction, from); |   await connection.sendTransaction(transaction, [from]); | ||||||
|  |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import { | |||||||
|   Connection, |   Connection, | ||||||
|   Lockup, |   Lockup, | ||||||
|   PublicKey, |   PublicKey, | ||||||
|   sendAndConfirmRecentTransaction, |   sendAndConfirmTransaction, | ||||||
|   LAMPORTS_PER_SOL, |   LAMPORTS_PER_SOL, | ||||||
|   StakeAuthorizationLayout, |   StakeAuthorizationLayout, | ||||||
|   StakeInstruction, |   StakeInstruction, | ||||||
| @@ -268,11 +268,11 @@ test('live staking actions', async () => { | |||||||
|       lamports: minimumAmount + 42, |       lamports: minimumAmount + 42, | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     await sendAndConfirmRecentTransaction( |     await sendAndConfirmTransaction( | ||||||
|       connection, |       connection, | ||||||
|       createAndInitialize, |       createAndInitialize, | ||||||
|       from, |       [from, newStakeAccount], | ||||||
|       newStakeAccount, |       0, | ||||||
|     ); |     ); | ||||||
|     expect(await connection.getBalance(newStakeAccount.publicKey)).toEqual( |     expect(await connection.getBalance(newStakeAccount.publicKey)).toEqual( | ||||||
|       minimumAmount + 42, |       minimumAmount + 42, | ||||||
| @@ -283,7 +283,7 @@ test('live staking actions', async () => { | |||||||
|       authorizedPubkey: authorized.publicKey, |       authorizedPubkey: authorized.publicKey, | ||||||
|       votePubkey, |       votePubkey, | ||||||
|     }); |     }); | ||||||
|     await sendAndConfirmRecentTransaction(connection, delegation, authorized); |     await sendAndConfirmTransaction(connection, delegation, [authorized], 0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Create Stake account with seed |   // Create Stake account with seed | ||||||
| @@ -304,10 +304,11 @@ test('live staking actions', async () => { | |||||||
|     lamports: 3 * minimumAmount + 42, |     lamports: 3 * minimumAmount + 42, | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   await sendAndConfirmRecentTransaction( |   await sendAndConfirmTransaction( | ||||||
|     connection, |     connection, | ||||||
|     createAndInitializeWithSeed, |     createAndInitializeWithSeed, | ||||||
|     from, |     [from], | ||||||
|  |     0, | ||||||
|   ); |   ); | ||||||
|   let originalStakeBalance = await connection.getBalance(newAccountPubkey); |   let originalStakeBalance = await connection.getBalance(newAccountPubkey); | ||||||
|   expect(originalStakeBalance).toEqual(3 * minimumAmount + 42); |   expect(originalStakeBalance).toEqual(3 * minimumAmount + 42); | ||||||
| @@ -317,7 +318,7 @@ test('live staking actions', async () => { | |||||||
|     authorizedPubkey: authorized.publicKey, |     authorizedPubkey: authorized.publicKey, | ||||||
|     votePubkey, |     votePubkey, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmRecentTransaction(connection, delegation, authorized); |   await sendAndConfirmTransaction(connection, delegation, [authorized], 0); | ||||||
|  |  | ||||||
|   // Test that withdraw fails before deactivation |   // Test that withdraw fails before deactivation | ||||||
|   const recipient = new Account(); |   const recipient = new Account(); | ||||||
| @@ -328,7 +329,7 @@ test('live staking actions', async () => { | |||||||
|     lamports: 1000, |     lamports: 1000, | ||||||
|   }); |   }); | ||||||
|   await expect( |   await expect( | ||||||
|     sendAndConfirmRecentTransaction(connection, withdraw, authorized), |     sendAndConfirmTransaction(connection, withdraw, [authorized], 0), | ||||||
|   ).rejects.toThrow(); |   ).rejects.toThrow(); | ||||||
|  |  | ||||||
|   // Split stake |   // Split stake | ||||||
| @@ -339,12 +340,7 @@ test('live staking actions', async () => { | |||||||
|     splitStakePubkey: newStake.publicKey, |     splitStakePubkey: newStake.publicKey, | ||||||
|     lamports: minimumAmount + 20, |     lamports: minimumAmount + 20, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmRecentTransaction( |   await sendAndConfirmTransaction(connection, split, [authorized, newStake], 0); | ||||||
|     connection, |  | ||||||
|     split, |  | ||||||
|     authorized, |  | ||||||
|     newStake, |  | ||||||
|   ); |  | ||||||
|  |  | ||||||
|   // Authorize to new account |   // Authorize to new account | ||||||
|   const newAuthorized = new Account(); |   const newAuthorized = new Account(); | ||||||
| @@ -356,14 +352,14 @@ test('live staking actions', async () => { | |||||||
|     newAuthorizedPubkey: newAuthorized.publicKey, |     newAuthorizedPubkey: newAuthorized.publicKey, | ||||||
|     stakeAuthorizationType: StakeAuthorizationLayout.Withdrawer, |     stakeAuthorizationType: StakeAuthorizationLayout.Withdrawer, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmRecentTransaction(connection, authorize, authorized); |   await sendAndConfirmTransaction(connection, authorize, [authorized], 0); | ||||||
|   authorize = StakeProgram.authorize({ |   authorize = StakeProgram.authorize({ | ||||||
|     stakePubkey: newAccountPubkey, |     stakePubkey: newAccountPubkey, | ||||||
|     authorizedPubkey: authorized.publicKey, |     authorizedPubkey: authorized.publicKey, | ||||||
|     newAuthorizedPubkey: newAuthorized.publicKey, |     newAuthorizedPubkey: newAuthorized.publicKey, | ||||||
|     stakeAuthorizationType: StakeAuthorizationLayout.Staker, |     stakeAuthorizationType: StakeAuthorizationLayout.Staker, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmRecentTransaction(connection, authorize, authorized); |   await sendAndConfirmTransaction(connection, authorize, [authorized], 0); | ||||||
|  |  | ||||||
|   // Test old authorized can't deactivate |   // Test old authorized can't deactivate | ||||||
|   let deactivateNotAuthorized = StakeProgram.deactivate({ |   let deactivateNotAuthorized = StakeProgram.deactivate({ | ||||||
| @@ -371,10 +367,11 @@ test('live staking actions', async () => { | |||||||
|     authorizedPubkey: authorized.publicKey, |     authorizedPubkey: authorized.publicKey, | ||||||
|   }); |   }); | ||||||
|   await expect( |   await expect( | ||||||
|     sendAndConfirmRecentTransaction( |     sendAndConfirmTransaction( | ||||||
|       connection, |       connection, | ||||||
|       deactivateNotAuthorized, |       deactivateNotAuthorized, | ||||||
|       authorized, |       [authorized], | ||||||
|  |       0, | ||||||
|     ), |     ), | ||||||
|   ).rejects.toThrow(); |   ).rejects.toThrow(); | ||||||
|  |  | ||||||
| @@ -383,7 +380,7 @@ test('live staking actions', async () => { | |||||||
|     stakePubkey: newAccountPubkey, |     stakePubkey: newAccountPubkey, | ||||||
|     authorizedPubkey: newAuthorized.publicKey, |     authorizedPubkey: newAuthorized.publicKey, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmRecentTransaction(connection, deactivate, newAuthorized); |   await sendAndConfirmTransaction(connection, deactivate, [newAuthorized], 0); | ||||||
|  |  | ||||||
|   // Test that withdraw succeeds after deactivation |   // Test that withdraw succeeds after deactivation | ||||||
|   withdraw = StakeProgram.withdraw({ |   withdraw = StakeProgram.withdraw({ | ||||||
| @@ -392,7 +389,7 @@ test('live staking actions', async () => { | |||||||
|     toPubkey: recipient.publicKey, |     toPubkey: recipient.publicKey, | ||||||
|     lamports: minimumAmount + 20, |     lamports: minimumAmount + 20, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmRecentTransaction(connection, withdraw, newAuthorized); |   await sendAndConfirmTransaction(connection, withdraw, [newAuthorized], 0); | ||||||
|   const balance = await connection.getBalance(newAccountPubkey); |   const balance = await connection.getBalance(newAccountPubkey); | ||||||
|   expect(balance).toEqual(minimumAmount + 2); |   expect(balance).toEqual(minimumAmount + 2); | ||||||
|   const recipientBalance = await connection.getBalance(recipient.publicKey); |   const recipientBalance = await connection.getBalance(recipient.publicKey); | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ import { | |||||||
|   SystemProgram, |   SystemProgram, | ||||||
|   Transaction, |   Transaction, | ||||||
|   TransactionInstruction, |   TransactionInstruction, | ||||||
|   sendAndConfirmRecentTransaction, |   sendAndConfirmTransaction, | ||||||
|   LAMPORTS_PER_SOL, |   LAMPORTS_PER_SOL, | ||||||
| } from '../src'; | } from '../src'; | ||||||
| import {NONCE_ACCOUNT_LENGTH} from '../src/nonce-account'; | import {NONCE_ACCOUNT_LENGTH} from '../src/nonce-account'; | ||||||
| @@ -293,11 +293,11 @@ test('live Nonce actions', async () => { | |||||||
|     authorizedPubkey: from.publicKey, |     authorizedPubkey: from.publicKey, | ||||||
|     lamports: minimumAmount, |     lamports: minimumAmount, | ||||||
|   }); |   }); | ||||||
|   await sendAndConfirmRecentTransaction( |   await sendAndConfirmTransaction( | ||||||
|     connection, |     connection, | ||||||
|     createNonceAccount, |     createNonceAccount, | ||||||
|     from, |     [from, nonceAccount], | ||||||
|     nonceAccount, |     0, | ||||||
|   ); |   ); | ||||||
|   const nonceBalance = await connection.getBalance(nonceAccount.publicKey); |   const nonceBalance = await connection.getBalance(nonceAccount.publicKey); | ||||||
|   expect(nonceBalance).toEqual(minimumAmount); |   expect(nonceBalance).toEqual(minimumAmount); | ||||||
| @@ -325,7 +325,7 @@ test('live Nonce actions', async () => { | |||||||
|       authorizedPubkey: from.publicKey, |       authorizedPubkey: from.publicKey, | ||||||
|     }), |     }), | ||||||
|   ); |   ); | ||||||
|   await sendAndConfirmRecentTransaction(connection, advanceNonce, from); |   await sendAndConfirmTransaction(connection, advanceNonce, [from], 0); | ||||||
|   const nonceQuery3 = await connection.getNonce(nonceAccount.publicKey); |   const nonceQuery3 = await connection.getNonce(nonceAccount.publicKey); | ||||||
|   if (nonceQuery3 === null) { |   if (nonceQuery3 === null) { | ||||||
|     expect(nonceQuery3).not.toBeNull(); |     expect(nonceQuery3).not.toBeNull(); | ||||||
| @@ -344,7 +344,7 @@ test('live Nonce actions', async () => { | |||||||
|       newAuthorizedPubkey: newAuthority.publicKey, |       newAuthorizedPubkey: newAuthority.publicKey, | ||||||
|     }), |     }), | ||||||
|   ); |   ); | ||||||
|   await sendAndConfirmRecentTransaction(connection, authorizeNonce, from); |   await sendAndConfirmTransaction(connection, authorizeNonce, [from], 0); | ||||||
|  |  | ||||||
|   let transfer = SystemProgram.transfer({ |   let transfer = SystemProgram.transfer({ | ||||||
|     fromPubkey: from.publicKey, |     fromPubkey: from.publicKey, | ||||||
| @@ -359,11 +359,11 @@ test('live Nonce actions', async () => { | |||||||
|     }), |     }), | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   await sendAndConfirmRecentTransaction( |   await sendAndConfirmTransaction( | ||||||
|     connection, |     connection, | ||||||
|     transfer, |     transfer, | ||||||
|     from, |     [from, newAuthority], | ||||||
|     newAuthority, |     0, | ||||||
|   ); |   ); | ||||||
|   const toBalance = await connection.getBalance(to.publicKey); |   const toBalance = await connection.getBalance(to.publicKey); | ||||||
|   expect(toBalance).toEqual(minimumAmount); |   expect(toBalance).toEqual(minimumAmount); | ||||||
| @@ -380,11 +380,7 @@ test('live Nonce actions', async () => { | |||||||
|       toPubkey: withdrawAccount.publicKey, |       toPubkey: withdrawAccount.publicKey, | ||||||
|     }), |     }), | ||||||
|   ); |   ); | ||||||
|   await sendAndConfirmRecentTransaction( |   await sendAndConfirmTransaction(connection, withdrawNonce, [newAuthority], 0); | ||||||
|     connection, |  | ||||||
|     withdrawNonce, |  | ||||||
|     newAuthority, |  | ||||||
|   ); |  | ||||||
|   expect(await connection.getBalance(nonceAccount.publicKey)).toEqual(0); |   expect(await connection.getBalance(nonceAccount.publicKey)).toEqual(0); | ||||||
|   const withdrawBalance = await connection.getBalance( |   const withdrawBalance = await connection.getBalance( | ||||||
|     withdrawAccount.publicKey, |     withdrawAccount.publicKey, | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ import {Account, Connection, SystemProgram, LAMPORTS_PER_SOL} from '../src'; | |||||||
| import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch'; | import {mockRpc, mockRpcEnabled} from './__mocks__/node-fetch'; | ||||||
| import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash'; | import {mockGetRecentBlockhash} from './mockrpc/get-recent-blockhash'; | ||||||
| import {url} from './url'; | import {url} from './url'; | ||||||
| import {sleep} from '../src/util/sleep'; |  | ||||||
|  |  | ||||||
| if (!mockRpcEnabled) { | if (!mockRpcEnabled) { | ||||||
|   // The default of 5 seconds is too slow for live testing sometimes |   // The default of 5 seconds is too slow for live testing sometimes | ||||||
| @@ -106,19 +105,19 @@ test('transaction-payer', async () => { | |||||||
|     lamports: 10, |     lamports: 10, | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   const signature = await connection.sendTransaction( |   const signature = await connection.sendTransaction(transaction, [ | ||||||
|     transaction, |  | ||||||
|     accountPayer, |     accountPayer, | ||||||
|     accountFrom, |     accountFrom, | ||||||
|   ); |   ]); | ||||||
|  |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
|     { |     { | ||||||
|       method: 'confirmTransaction', |       method: 'getSignatureStatuses', | ||||||
|       params: [ |       params: [ | ||||||
|  |         [ | ||||||
|           '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', |           '3WE5w4B7v59x6qjyC4FbG2FEKYKQfvsJwqSxNVmtMjT8TQ31hsZieDHcSgqzxiAoTL56n2w5TncjqEKjLhtF4Vk', | ||||||
|         {commitment: 'recent'}, |         ], | ||||||
|       ], |       ], | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
| @@ -127,21 +126,19 @@ test('transaction-payer', async () => { | |||||||
|         context: { |         context: { | ||||||
|           slot: 11, |           slot: 11, | ||||||
|         }, |         }, | ||||||
|         value: true, |         value: [ | ||||||
|  |           { | ||||||
|  |             slot: 0, | ||||||
|  |             confirmations: 1, | ||||||
|  |             status: {Ok: null}, | ||||||
|  |             err: null, | ||||||
|  |           }, | ||||||
|  |         ], | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
|   ]); |   ]); | ||||||
|  |  | ||||||
|   let i = 0; |   await connection.confirmTransaction(signature, 1); | ||||||
|   for (;;) { |  | ||||||
|     if (await connection.confirmTransaction(signature)) { |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     expect(mockRpcEnabled).toBe(false); |  | ||||||
|     expect(++i).toBeLessThan(10); |  | ||||||
|     await sleep(500); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   mockRpc.push([ |   mockRpc.push([ | ||||||
|     url, |     url, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user