@@ -92,7 +92,32 @@ fn main() -> Result<()> {
9292 & merkle_price_updates[ 0 ] ,
9393 ) ?;
9494 }
95+ Action :: PostTwapUpdate {
96+ start_payload,
97+ end_payload,
98+ } => {
99+ let rpc_client = RpcClient :: new ( url) ;
100+ let payer =
101+ read_keypair_file ( & * shellexpand:: tilde ( & keypair) ) . expect ( "Keypair not found" ) ;
95102
103+ let start_payload_bytes: Vec < u8 > = base64:: decode ( start_payload) ?;
104+ let end_payload_bytes: Vec < u8 > = base64:: decode ( end_payload) ?;
105+
106+ let ( start_vaa, start_merkle_price_updates) =
107+ deserialize_accumulator_update_data ( start_payload_bytes) ?;
108+ let ( end_vaa, end_merkle_price_updates) =
109+ deserialize_accumulator_update_data ( end_payload_bytes) ?;
110+
111+ process_write_encoded_vaa_and_post_twap_update (
112+ & rpc_client,
113+ & start_vaa,
114+ & end_vaa,
115+ wormhole,
116+ & payer,
117+ & start_merkle_price_updates[ 0 ] ,
118+ & end_merkle_price_updates[ 0 ] ,
119+ ) ?;
120+ }
96121 Action :: InitializeWormholeReceiver { } => {
97122 let rpc_client = RpcClient :: new ( url) ;
98123 let payer =
@@ -367,36 +392,174 @@ pub fn process_write_encoded_vaa_and_post_price_update(
367392 merkle_price_update : & MerklePriceUpdate ,
368393) -> Result < Pubkey > {
369394 let encoded_vaa_keypair = Keypair :: new ( ) ;
395+
396+ // Transaction 1: Create and initialize VAA
397+ let init_instructions = init_encoded_vaa_and_write_initial_data_ixs (
398+ & payer. pubkey ( ) ,
399+ vaa,
400+ & wormhole,
401+ & encoded_vaa_keypair,
402+ ) ?;
403+ process_transaction (
404+ rpc_client,
405+ init_instructions,
406+ & vec ! [ payer, & encoded_vaa_keypair] ,
407+ ) ?;
408+
409+ // Transaction 2: Write remaining VAA data, verify VAA, and post price update
410+ let price_update_keypair = Keypair :: new ( ) ;
411+ let mut update_instructions = vec ! [ ComputeBudgetInstruction :: set_compute_unit_limit( 600_000 ) ] ;
412+
413+ update_instructions. extend ( write_remaining_data_and_verify_vaa_ixs (
414+ & payer. pubkey ( ) ,
415+ vaa,
416+ & encoded_vaa_keypair. pubkey ( ) ,
417+ wormhole,
418+ ) ?) ;
419+
420+ update_instructions. push ( pyth_solana_receiver:: instruction:: PostUpdate :: populate (
421+ payer. pubkey ( ) ,
422+ payer. pubkey ( ) ,
423+ encoded_vaa_keypair. pubkey ( ) ,
424+ price_update_keypair. pubkey ( ) ,
425+ merkle_price_update. clone ( ) ,
426+ get_random_treasury_id ( ) ,
427+ ) ) ;
428+
429+ process_transaction (
430+ rpc_client,
431+ update_instructions,
432+ & vec ! [ payer, & price_update_keypair] ,
433+ ) ?;
434+
435+ Ok ( price_update_keypair. pubkey ( ) )
436+ }
437+
438+ /// This function verifies start & end VAAs from Hermes via Wormhole to produce encoded VAAs,
439+ /// and then posts a TWAP update using the encoded VAAs. Returns the TwapUpdate account pubkey.
440+ ///
441+ /// The operation is split up into 4 transactions:
442+ /// 1. Creates and initializes the start VAA account and writes its first part
443+ /// 2. Creates and initializes the end VAA account and writes its first part
444+ /// 3. Writes the remaining data for both VAAs and verifies them
445+ /// 4. Posts the TWAP update
446+ pub fn process_write_encoded_vaa_and_post_twap_update (
447+ rpc_client : & RpcClient ,
448+ start_vaa : & [ u8 ] ,
449+ end_vaa : & [ u8 ] ,
450+ wormhole : Pubkey ,
451+ payer : & Keypair ,
452+ start_merkle_price_update : & MerklePriceUpdate ,
453+ end_merkle_price_update : & MerklePriceUpdate ,
454+ ) -> Result < Pubkey > {
455+ // Create keypairs for both encoded VAAs
456+ let start_encoded_vaa_keypair = Keypair :: new ( ) ;
457+ let end_encoded_vaa_keypair = Keypair :: new ( ) ;
458+
459+ // Transaction 1: Create and initialize start VAA
460+ let start_init_instructions = init_encoded_vaa_and_write_initial_data_ixs (
461+ & payer. pubkey ( ) ,
462+ start_vaa,
463+ & wormhole,
464+ & start_encoded_vaa_keypair,
465+ ) ?;
466+ process_transaction (
467+ rpc_client,
468+ start_init_instructions,
469+ & vec ! [ payer, & start_encoded_vaa_keypair] ,
470+ ) ?;
471+
472+ // Transaction 2: Create and initialize end VAA
473+ let end_init_instructions = init_encoded_vaa_and_write_initial_data_ixs (
474+ & payer. pubkey ( ) ,
475+ end_vaa,
476+ & wormhole,
477+ & end_encoded_vaa_keypair,
478+ ) ?;
479+ process_transaction (
480+ rpc_client,
481+ end_init_instructions,
482+ & vec ! [ payer, & end_encoded_vaa_keypair] ,
483+ ) ?;
484+
485+ // Transaction 3: Write remaining VAA data and verify both VAAs
486+ let mut verify_instructions = vec ! [ ComputeBudgetInstruction :: set_compute_unit_limit( 400_000 ) ] ;
487+ verify_instructions. extend ( write_remaining_data_and_verify_vaa_ixs (
488+ & payer. pubkey ( ) ,
489+ start_vaa,
490+ & start_encoded_vaa_keypair. pubkey ( ) ,
491+ wormhole,
492+ ) ?) ;
493+ verify_instructions. extend ( write_remaining_data_and_verify_vaa_ixs (
494+ & payer. pubkey ( ) ,
495+ end_vaa,
496+ & end_encoded_vaa_keypair. pubkey ( ) ,
497+ wormhole,
498+ ) ?) ;
499+ process_transaction ( rpc_client, verify_instructions, & vec ! [ payer] ) ?;
500+
501+ // Transaction 4: Post TWAP update
502+ let twap_update_keypair = Keypair :: new ( ) ;
503+ let post_instructions = vec ! [
504+ ComputeBudgetInstruction :: set_compute_unit_limit( 400_000 ) ,
505+ pyth_solana_receiver:: instruction:: PostTwapUpdate :: populate(
506+ payer. pubkey( ) ,
507+ payer. pubkey( ) ,
508+ start_encoded_vaa_keypair. pubkey( ) ,
509+ end_encoded_vaa_keypair. pubkey( ) ,
510+ twap_update_keypair. pubkey( ) ,
511+ start_merkle_price_update. clone( ) ,
512+ end_merkle_price_update. clone( ) ,
513+ get_random_treasury_id( ) ,
514+ ) ,
515+ ] ;
516+ process_transaction (
517+ rpc_client,
518+ post_instructions,
519+ & vec ! [ payer, & twap_update_keypair] ,
520+ ) ?;
521+
522+ Ok ( twap_update_keypair. pubkey ( ) )
523+ }
524+
525+ /// Creates instructions to initialize an encoded VAA account and write the first part of the VAA data
526+ pub fn init_encoded_vaa_and_write_initial_data_ixs (
527+ payer : & Pubkey ,
528+ vaa : & [ u8 ] ,
529+ wormhole : & Pubkey ,
530+ encoded_vaa_keypair : & Keypair ,
531+ ) -> Result < Vec < Instruction > > {
370532 let encoded_vaa_size: usize = vaa. len ( ) + VAA_START ;
371533
372534 let create_encoded_vaa = system_instruction:: create_account (
373- & payer. pubkey ( ) ,
535+ payer,
374536 & encoded_vaa_keypair. pubkey ( ) ,
375537 Rent :: default ( ) . minimum_balance ( encoded_vaa_size) ,
376538 encoded_vaa_size as u64 ,
377- & wormhole,
539+ wormhole,
378540 ) ;
541+
379542 let init_encoded_vaa_accounts = wormhole_core_bridge_solana:: accounts:: InitEncodedVaa {
380- write_authority : payer. pubkey ( ) ,
543+ write_authority : * payer,
381544 encoded_vaa : encoded_vaa_keypair. pubkey ( ) ,
382545 }
383546 . to_account_metas ( None ) ;
384547
385548 let init_encoded_vaa_instruction = Instruction {
386- program_id : wormhole,
549+ program_id : * wormhole,
387550 accounts : init_encoded_vaa_accounts,
388551 data : wormhole_core_bridge_solana:: instruction:: InitEncodedVaa . data ( ) ,
389552 } ;
390553
391554 let write_encoded_vaa_accounts = wormhole_core_bridge_solana:: accounts:: WriteEncodedVaa {
392- write_authority : payer. pubkey ( ) ,
555+ write_authority : * payer,
393556 draft_vaa : encoded_vaa_keypair. pubkey ( ) ,
394557 }
395558 . to_account_metas ( None ) ;
396559
397- let write_encoded_vaa_accounts_instruction = Instruction {
398- program_id : wormhole,
399- accounts : write_encoded_vaa_accounts. clone ( ) ,
560+ let write_encoded_vaa_instruction = Instruction {
561+ program_id : * wormhole,
562+ accounts : write_encoded_vaa_accounts,
400563 data : wormhole_core_bridge_solana:: instruction:: WriteEncodedVaa {
401564 args : WriteEncodedVaaArgs {
402565 index : 0 ,
@@ -406,18 +569,27 @@ pub fn process_write_encoded_vaa_and_post_price_update(
406569 . data ( ) ,
407570 } ;
408571
409- // 1st transaction
410- process_transaction (
411- rpc_client,
412- vec ! [
413- create_encoded_vaa,
414- init_encoded_vaa_instruction,
415- write_encoded_vaa_accounts_instruction,
416- ] ,
417- & vec ! [ payer, & encoded_vaa_keypair] ,
418- ) ?;
572+ Ok ( vec ! [
573+ create_encoded_vaa,
574+ init_encoded_vaa_instruction,
575+ write_encoded_vaa_instruction,
576+ ] )
577+ }
578+
579+ /// Creates instructions to write remaining VAA data and verify the VAA
580+ pub fn write_remaining_data_and_verify_vaa_ixs (
581+ payer : & Pubkey ,
582+ vaa : & [ u8 ] ,
583+ encoded_vaa_keypair : & Pubkey ,
584+ wormhole : Pubkey ,
585+ ) -> Result < Vec < Instruction > > {
586+ let write_encoded_vaa_accounts = wormhole_core_bridge_solana:: accounts:: WriteEncodedVaa {
587+ write_authority : * payer,
588+ draft_vaa : * encoded_vaa_keypair,
589+ }
590+ . to_account_metas ( None ) ;
419591
420- let write_encoded_vaa_accounts_instruction_2 = Instruction {
592+ let write_encoded_vaa_instruction = Instruction {
421593 program_id : wormhole,
422594 accounts : write_encoded_vaa_accounts,
423595 data : wormhole_core_bridge_solana:: instruction:: WriteEncodedVaa {
@@ -432,13 +604,10 @@ pub fn process_write_encoded_vaa_and_post_price_update(
432604 let ( header, _) : ( Header , Body < & RawMessage > ) = serde_wormhole:: from_slice ( vaa) . unwrap ( ) ;
433605 let guardian_set = GuardianSet :: key ( & wormhole, header. guardian_set_index ) ;
434606
435- let request_compute_units_instruction: Instruction =
436- ComputeBudgetInstruction :: set_compute_unit_limit ( 600_000 ) ;
437-
438607 let verify_encoded_vaa_accounts = wormhole_core_bridge_solana:: accounts:: VerifyEncodedVaaV1 {
439608 guardian_set,
440- write_authority : payer. pubkey ( ) ,
441- draft_vaa : encoded_vaa_keypair. pubkey ( ) ,
609+ write_authority : * payer,
610+ draft_vaa : * encoded_vaa_keypair,
442611 }
443612 . to_account_metas ( None ) ;
444613
@@ -448,30 +617,10 @@ pub fn process_write_encoded_vaa_and_post_price_update(
448617 data : wormhole_core_bridge_solana:: instruction:: VerifyEncodedVaaV1 { } . data ( ) ,
449618 } ;
450619
451- let price_update_keypair = Keypair :: new ( ) ;
452-
453- let post_update_instructions = pyth_solana_receiver:: instruction:: PostUpdate :: populate (
454- payer. pubkey ( ) ,
455- payer. pubkey ( ) ,
456- encoded_vaa_keypair. pubkey ( ) ,
457- price_update_keypair. pubkey ( ) ,
458- merkle_price_update. clone ( ) ,
459- get_random_treasury_id ( ) ,
460- ) ;
461-
462- // 2nd transaction
463- process_transaction (
464- rpc_client,
465- vec ! [
466- request_compute_units_instruction,
467- write_encoded_vaa_accounts_instruction_2,
468- verify_encoded_vaa_instruction,
469- post_update_instructions,
470- ] ,
471- & vec ! [ payer, & price_update_keypair] ,
472- ) ?;
473-
474- Ok ( price_update_keypair. pubkey ( ) )
620+ Ok ( vec ! [
621+ write_encoded_vaa_instruction,
622+ verify_encoded_vaa_instruction,
623+ ] )
475624}
476625
477626pub fn process_transaction (
0 commit comments