7
7
SystemProgram ,
8
8
PACKET_DATA_SIZE ,
9
9
ConfirmOptions ,
10
+ sendAndConfirmRawTransaction ,
10
11
} from "@solana/web3.js" ;
11
12
import { BN } from "bn.js" ;
12
13
import { AnchorProvider } from "@coral-xyz/anchor" ;
@@ -17,7 +18,7 @@ import {
17
18
deriveFeeCollectorKey ,
18
19
} from "@certusone/wormhole-sdk/lib/cjs/solana/wormhole" ;
19
20
import { ExecutePostedVaa } from "./governance_payload/ExecutePostedVaa" ;
20
- import { getOpsKey , getProposalInstructions } from "./multisig" ;
21
+ import { getOpsKey } from "./multisig" ;
21
22
import { PythCluster } from "@pythnetwork/client/lib/cluster" ;
22
23
import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider" ;
23
24
import SquadsMesh , { getIxAuthorityPDA , getTxPDA } from "@sqds/mesh" ;
@@ -26,8 +27,8 @@ import { mapKey } from "./remote_executor";
26
27
import { WORMHOLE_ADDRESS } from "./wormhole" ;
27
28
28
29
export const MAX_EXECUTOR_PAYLOAD_SIZE = PACKET_DATA_SIZE - 687 ; // Bigger payloads won't fit in one addInstruction call when adding to the proposal
29
- export const SIZE_OF_SIGNED_BATCH = 30 ;
30
30
export const MAX_INSTRUCTIONS_PER_PROPOSAL = 256 - 1 ;
31
+ export const MAX_NUMBER_OF_RETRIES = 5 ;
31
32
32
33
type SquadInstruction = {
33
34
instruction : TransactionInstruction ;
@@ -256,13 +257,7 @@ export class MultisigVault {
256
257
ixToSend . push ( await this . approveProposalIx ( proposalAddress ) ) ;
257
258
258
259
const txToSend = batchIntoTransactions ( ixToSend ) ;
259
- for ( let i = 0 ; i < txToSend . length ; i += SIZE_OF_SIGNED_BATCH ) {
260
- await this . getAnchorProvider ( ) . sendAll (
261
- txToSend . slice ( i , i + SIZE_OF_SIGNED_BATCH ) . map ( ( tx ) => {
262
- return { tx, signers : [ ] } ;
263
- } )
264
- ) ;
265
- }
260
+ await this . sendAllTransactions ( txToSend ) ;
266
261
return proposalAddress ;
267
262
}
268
263
@@ -367,18 +362,58 @@ export class MultisigVault {
367
362
368
363
const txToSend = batchIntoTransactions ( ixToSend ) ;
369
364
370
- for ( let i = 0 ; i < txToSend . length ; i += SIZE_OF_SIGNED_BATCH ) {
371
- await this . getAnchorProvider ( {
372
- preflightCommitment : "processed" ,
373
- commitment : "confirmed" ,
374
- } ) . sendAll (
375
- txToSend . slice ( i , i + SIZE_OF_SIGNED_BATCH ) . map ( ( tx ) => {
376
- return { tx, signers : [ ] } ;
377
- } )
378
- ) ;
379
- }
365
+ await this . sendAllTransactions ( txToSend ) ;
380
366
return newProposals ;
381
367
}
368
+
369
+ async sendAllTransactions ( transactions : Transaction [ ] ) {
370
+ const provider = this . getAnchorProvider ( {
371
+ preflightCommitment : "processed" ,
372
+ commitment : "processed" ,
373
+ } ) ;
374
+
375
+ let needToFetchBlockhash = true ; // We don't fetch blockhash everytime to save time
376
+ let blockhash : string = "" ;
377
+ for ( let [ index , tx ] of transactions . entries ( ) ) {
378
+ console . log ( "Trying to send transaction : " + index ) ;
379
+ let numberOfRetries = 0 ;
380
+ let txHasLanded = false ;
381
+
382
+ while ( ! txHasLanded ) {
383
+ try {
384
+ if ( needToFetchBlockhash ) {
385
+ blockhash = ( await provider . connection . getLatestBlockhash ( ) )
386
+ . blockhash ;
387
+ needToFetchBlockhash = false ;
388
+ }
389
+ tx . feePayer = tx . feePayer || provider . wallet . publicKey ;
390
+ tx . recentBlockhash = blockhash ;
391
+ provider . wallet . signTransaction ( tx ) ;
392
+ await sendAndConfirmRawTransaction (
393
+ provider . connection ,
394
+ tx . serialize ( ) ,
395
+ provider . opts
396
+ ) ;
397
+ txHasLanded = true ;
398
+ } catch ( e ) {
399
+ if ( numberOfRetries >= MAX_NUMBER_OF_RETRIES ) {
400
+ // Cap the number of retries
401
+ throw Error ( "Maximum number of retries exceeded" ) ;
402
+ }
403
+ const message = ( e as any ) . toString ( ) . split ( "\n" ) [ 0 ] ;
404
+ if (
405
+ message ==
406
+ "Error: failed to send transaction: Transaction simulation failed: Blockhash not found"
407
+ ) {
408
+ // If blockhash has expired, we need to fetch a new one
409
+ needToFetchBlockhash = true ;
410
+ }
411
+ console . log ( e ) ;
412
+ numberOfRetries += 1 ;
413
+ }
414
+ }
415
+ }
416
+ }
382
417
}
383
418
384
419
/**
0 commit comments