| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- pub mod attestation_cfg;
- use borsh::{
- BorshDeserialize,
- BorshSerialize,
- };
- use solana_client::rpc_client::RpcClient;
- use solana_program::{
- hash::Hash,
- instruction::{
- AccountMeta,
- Instruction,
- },
- pubkey::Pubkey,
- system_program,
- sysvar::{
- clock,
- rent,
- },
- };
- use solana_sdk::transaction::Transaction;
- use solitaire::{
- processors::seeded::Seeded,
- AccountState,
- ErrBox,
- };
- use solitaire_client::{
- AccEntry,
- Keypair,
- SolSigner,
- ToInstruction,
- };
- use bridge::{
- accounts::{
- Bridge,
- FeeCollector,
- Sequence,
- SequenceDerivationData,
- },
- types::ConsistencyLevel,
- };
- use p2w_sdk::P2WEmitter;
- use pyth2wormhole::{
- attest::P2W_MAX_BATCH_SIZE,
- config::P2WConfigAccount,
- initialize::InitializeAccounts,
- set_config::SetConfigAccounts,
- AttestData,
- Pyth2WormholeConfig,
- };
- pub use attestation_cfg::{
- AttestationConfig,
- P2WSymbol,
- };
- pub fn gen_init_tx(
- payer: Keypair,
- p2w_addr: Pubkey,
- new_owner_addr: Pubkey,
- wh_prog: Pubkey,
- pyth_owner_addr: Pubkey,
- latest_blockhash: Hash,
- ) -> Result<Transaction, ErrBox> {
- use AccEntry::*;
- let payer_pubkey = payer.pubkey();
- let accs = InitializeAccounts {
- payer: Signer(payer),
- new_config: Derived(p2w_addr),
- };
- let config = Pyth2WormholeConfig {
- max_batch_size: P2W_MAX_BATCH_SIZE,
- owner: new_owner_addr,
- wh_prog: wh_prog,
- pyth_owner: pyth_owner_addr,
- };
- let ix_data = (pyth2wormhole::instruction::Instruction::Initialize, config);
- let (ix, signers) = accs.to_ix(p2w_addr, ix_data.try_to_vec()?.as_slice())?;
- let tx_signed = Transaction::new_signed_with_payer::<Vec<&Keypair>>(
- &[ix],
- Some(&payer_pubkey),
- signers.iter().collect::<Vec<_>>().as_ref(),
- latest_blockhash,
- );
- Ok(tx_signed)
- }
- pub fn gen_set_config_tx(
- payer: Keypair,
- p2w_addr: Pubkey,
- owner: Keypair,
- new_owner_addr: Pubkey,
- new_wh_prog: Pubkey,
- new_pyth_owner_addr: Pubkey,
- latest_blockhash: Hash,
- ) -> Result<Transaction, ErrBox> {
- use AccEntry::*;
- let payer_pubkey = payer.pubkey();
- let accs = SetConfigAccounts {
- payer: Signer(payer),
- current_owner: Signer(owner),
- config: Derived(p2w_addr),
- };
- let config = Pyth2WormholeConfig {
- max_batch_size: P2W_MAX_BATCH_SIZE,
- owner: new_owner_addr,
- wh_prog: new_wh_prog,
- pyth_owner: new_pyth_owner_addr,
- };
- let ix_data = (pyth2wormhole::instruction::Instruction::SetConfig, config);
- let (ix, signers) = accs.to_ix(p2w_addr, ix_data.try_to_vec()?.as_slice())?;
- let tx_signed = Transaction::new_signed_with_payer::<Vec<&Keypair>>(
- &[ix],
- Some(&payer_pubkey),
- signers.iter().collect::<Vec<_>>().as_ref(),
- latest_blockhash,
- );
- Ok(tx_signed)
- }
- /// Get the current config account data for given p2w program address
- pub fn get_config_account(
- rpc_client: &RpcClient,
- p2w_addr: &Pubkey,
- ) -> Result<Pyth2WormholeConfig, ErrBox> {
- let p2w_config_addr = P2WConfigAccount::<{ AccountState::Initialized }>::key(None, p2w_addr);
- let config = Pyth2WormholeConfig::try_from_slice(
- rpc_client.get_account_data(&p2w_config_addr)?.as_slice(),
- )?;
- Ok(config)
- }
- /// Generate an Instruction for making the attest() contract
- /// call.
- pub fn gen_attest_tx(
- p2w_addr: Pubkey,
- p2w_config: &Pyth2WormholeConfig, // Must be fresh, not retrieved inside to keep side effects away
- payer: &Keypair,
- symbols: &[P2WSymbol],
- wh_msg: &Keypair,
- latest_blockhash: Hash,
- ) -> Result<Transaction, ErrBox> {
- let emitter_addr = P2WEmitter::key(None, &p2w_addr);
- let seq_addr = Sequence::key(
- &SequenceDerivationData {
- emitter_key: &emitter_addr,
- },
- &p2w_config.wh_prog,
- );
- let p2w_config_addr = P2WConfigAccount::<{ AccountState::Initialized }>::key(None, &p2w_addr);
- if symbols.len() > p2w_config.max_batch_size as usize {
- return Err(format!(
- "Expected up to {} symbols for batch, {} were found",
- p2w_config.max_batch_size,
- symbols.len()
- )
- .into());
- }
- // Initial attest() accounts
- let mut acc_metas = vec![
- // payer
- AccountMeta::new(payer.pubkey(), true),
- // system_program
- AccountMeta::new_readonly(system_program::id(), false),
- // config
- AccountMeta::new_readonly(p2w_config_addr, false),
- ];
- // Batch contents and padding if applicable
- let mut padded_symbols = {
- let mut not_padded: Vec<_> = symbols
- .iter()
- .map(|s| {
- vec![
- AccountMeta::new_readonly(s.product_addr, false),
- AccountMeta::new_readonly(s.price_addr, false),
- ]
- })
- .flatten()
- .collect();
- // Align to max batch size with null accounts
- let mut padding_accounts =
- vec![
- AccountMeta::new_readonly(Pubkey::new_from_array([0u8; 32]), false);
- 2 * (p2w_config.max_batch_size as usize - symbols.len())
- ];
- not_padded.append(&mut padding_accounts);
- not_padded
- };
- acc_metas.append(&mut padded_symbols);
- // Continue with other pyth2wormhole accounts
- let mut acc_metas_remainder = vec![
- // clock
- AccountMeta::new_readonly(clock::id(), false),
- // wh_prog
- AccountMeta::new_readonly(p2w_config.wh_prog, false),
- // wh_bridge
- AccountMeta::new(
- Bridge::<{ AccountState::Initialized }>::key(None, &p2w_config.wh_prog),
- false,
- ),
- // wh_message
- AccountMeta::new(wh_msg.pubkey(), true),
- // wh_emitter
- AccountMeta::new_readonly(emitter_addr, false),
- // wh_sequence
- AccountMeta::new(seq_addr, false),
- // wh_fee_collector
- AccountMeta::new(FeeCollector::<'_>::key(None, &p2w_config.wh_prog), false),
- AccountMeta::new_readonly(rent::id(), false),
- ];
- acc_metas.append(&mut acc_metas_remainder);
- let ix_data = (
- pyth2wormhole::instruction::Instruction::Attest,
- AttestData {
- consistency_level: ConsistencyLevel::Finalized,
- },
- );
- let ix = Instruction::new_with_bytes(p2w_addr, ix_data.try_to_vec()?.as_slice(), acc_metas);
- let tx_signed = Transaction::new_signed_with_payer::<Vec<&Keypair>>(
- &[ix],
- Some(&payer.pubkey()),
- &vec![&payer, &wh_msg],
- latest_blockhash,
- );
- Ok(tx_signed)
- }
|