mod program_test; use { mpl_token_metadata::accounts::{MasterEdition, Metadata}, program_test::StablebondProgramTest, solana_program_test::{tokio, ProgramTestContext}, solana_sdk::{ instruction::InstructionError, signature::{Keypair, Signer}, transaction::{Transaction, TransactionError}, }, spl_associated_token_account::get_associated_token_address, stablebond_sdk::{ accounts::Config, errors::StablebondError, find_config_pda, find_payment_feed_pda, instructions::{ InitializeConfig, InitializeConfigInstructionArgs, UpdateOracleType, UpdateOracleTypeInstructionArgs, }, types::{OracleSetup, PaymentFeedInfo, PaymentFeedType}, }, }; struct ExecuteTestContext { context: ProgramTestContext, admin: Keypair, nft_collection_mint: Keypair, usdc_mxn_payment_feed: PaymentFeedInfo, usdc_usd_payment_feed: PaymentFeedInfo, } async fn setup() -> ExecuteTestContext { let pt = StablebondProgramTest::start_new().await; let admin = pt.admin; let nft_collection_mint = pt.nft_collection_mint; let usdc_mxn_payment_feed = pt.usdc_mxn_payment_feed; let usdc_usd_payment_feed = pt.usdc_usd_payment_feed; let context = pt.context; ExecuteTestContext { context, admin, nft_collection_mint, usdc_mxn_payment_feed, usdc_usd_payment_feed, } } #[tokio::test] async fn update_oracle_type() { let mut et = setup().await; let initialize_config_ix_args = InitializeConfigInstructionArgs { oracle: OracleSetup::Stub, usdc_mxn_payment_feed: et.usdc_mxn_payment_feed.clone(), usdc_usd_payment_feed: et.usdc_usd_payment_feed, }; let initialize_config_ix = InitializeConfig { admin_wallet: et.admin.pubkey(), config_account: find_config_pda().0, config_token_account: get_associated_token_address( &find_config_pda().0, &et.nft_collection_mint.pubkey(), ), mint_account: et.nft_collection_mint.pubkey(), payment_mint_account: et.usdc_mxn_payment_feed.payment_mint, metadata_account: Metadata::find_pda(&et.nft_collection_mint.pubkey()).0, master_edition_account: MasterEdition::find_pda(&et.nft_collection_mint.pubkey()).0, usdc_mxn_feed_account: find_payment_feed_pda(PaymentFeedType::UsdcMxn).0, usdc_usd_feed_account: find_payment_feed_pda(PaymentFeedType::UsdcUsd).0, token_program: spl_token::id(), associated_token_program: spl_associated_token_account::id(), metadata_program: mpl_token_metadata::ID, system_program: solana_program::system_program::id(), } .instruction(initialize_config_ix_args); let ixs = &[initialize_config_ix]; let transaction = Transaction::new_signed_with_payer( ixs, Some(&et.admin.pubkey()), &[&et.admin, &et.nft_collection_mint], et.context.last_blockhash, ); et.context .banks_client .process_transaction(transaction) .await .unwrap(); let config_account = et .context .banks_client .get_account(find_config_pda().0) .await .unwrap() .unwrap(); let config = Config::from_bytes(&config_account.data).unwrap(); assert!(config.oracle_setup == OracleSetup::Stub); let update_update_oracle_type_args = UpdateOracleTypeInstructionArgs { oracle_setup: OracleSetup::PythEma, }; let update_oracle_type = UpdateOracleType { admin_wallet: et.admin.pubkey(), config_account: find_config_pda().0, system_program: solana_program::system_program::id(), } .instruction(update_update_oracle_type_args); let ixs = &[update_oracle_type]; let transaction = Transaction::new_signed_with_payer( ixs, Some(&et.admin.pubkey()), &[&et.admin], et.context.last_blockhash, ); et.context .banks_client .process_transaction(transaction) .await .unwrap(); let config_account = et .context .banks_client .get_account(find_config_pda().0) .await .unwrap() .unwrap(); let config = Config::from_bytes(&config_account.data).unwrap(); assert!(config.oracle_setup == OracleSetup::PythEma); } #[tokio::test] async fn fail_update_oracle_type_with_same_type() { let mut et = setup().await; let initialize_config_ix_args = InitializeConfigInstructionArgs { oracle: OracleSetup::Stub, usdc_mxn_payment_feed: et.usdc_mxn_payment_feed.clone(), usdc_usd_payment_feed: et.usdc_usd_payment_feed, }; let initialize_config_ix = InitializeConfig { admin_wallet: et.admin.pubkey(), config_account: find_config_pda().0, config_token_account: get_associated_token_address( &find_config_pda().0, &et.nft_collection_mint.pubkey(), ), mint_account: et.nft_collection_mint.pubkey(), payment_mint_account: et.usdc_mxn_payment_feed.payment_mint, metadata_account: Metadata::find_pda(&et.nft_collection_mint.pubkey()).0, master_edition_account: MasterEdition::find_pda(&et.nft_collection_mint.pubkey()).0, usdc_mxn_feed_account: find_payment_feed_pda(PaymentFeedType::UsdcMxn).0, usdc_usd_feed_account: find_payment_feed_pda(PaymentFeedType::UsdcUsd).0, token_program: spl_token::id(), associated_token_program: spl_associated_token_account::id(), metadata_program: mpl_token_metadata::ID, system_program: solana_program::system_program::id(), } .instruction(initialize_config_ix_args); let ixs = &[initialize_config_ix]; let transaction = Transaction::new_signed_with_payer( ixs, Some(&et.admin.pubkey()), &[&et.admin, &et.nft_collection_mint], et.context.last_blockhash, ); et.context .banks_client .process_transaction(transaction) .await .unwrap(); let config_account = et .context .banks_client .get_account(find_config_pda().0) .await .unwrap() .unwrap(); let config = Config::from_bytes(&config_account.data).unwrap(); assert!(config.oracle_setup == OracleSetup::Stub); let update_update_oracle_type_args = UpdateOracleTypeInstructionArgs { oracle_setup: OracleSetup::Stub, }; let update_oracle_type = UpdateOracleType { admin_wallet: et.admin.pubkey(), config_account: find_config_pda().0, system_program: solana_program::system_program::id(), } .instruction(update_update_oracle_type_args); let ixs = &[update_oracle_type]; let transaction = Transaction::new_signed_with_payer( ixs, Some(&et.admin.pubkey()), &[&et.admin], et.context.last_blockhash, ); let error = et .context .banks_client .process_transaction(transaction) .await .err() .unwrap() .unwrap(); match error { TransactionError::InstructionError(_, InstructionError::Custom(error_index)) => { let program_error = StablebondError::InvalidArgument as u32; assert_eq!(error_index, program_error + 6000); } _ => { panic!("Wrong error occurs while testing updating oracle type"); } } } #[tokio::test] async fn fail_update_oracle_with_invalid_admin() { let mut et = setup().await; let initialize_config_ix_args = InitializeConfigInstructionArgs { oracle: OracleSetup::Stub, usdc_mxn_payment_feed: et.usdc_mxn_payment_feed.clone(), usdc_usd_payment_feed: et.usdc_usd_payment_feed, }; let initialize_config_ix = InitializeConfig { admin_wallet: et.admin.pubkey(), config_account: find_config_pda().0, config_token_account: get_associated_token_address( &find_config_pda().0, &et.nft_collection_mint.pubkey(), ), mint_account: et.nft_collection_mint.pubkey(), payment_mint_account: et.usdc_mxn_payment_feed.payment_mint, metadata_account: Metadata::find_pda(&et.nft_collection_mint.pubkey()).0, master_edition_account: MasterEdition::find_pda(&et.nft_collection_mint.pubkey()).0, usdc_mxn_feed_account: find_payment_feed_pda(PaymentFeedType::UsdcMxn).0, usdc_usd_feed_account: find_payment_feed_pda(PaymentFeedType::UsdcUsd).0, token_program: spl_token::id(), associated_token_program: spl_associated_token_account::id(), metadata_program: mpl_token_metadata::ID, system_program: solana_program::system_program::id(), } .instruction(initialize_config_ix_args); let ixs = &[initialize_config_ix]; let transaction = Transaction::new_signed_with_payer( ixs, Some(&et.admin.pubkey()), &[&et.admin, &et.nft_collection_mint], et.context.last_blockhash, ); et.context .banks_client .process_transaction(transaction) .await .unwrap(); let config_account = et .context .banks_client .get_account(find_config_pda().0) .await .unwrap() .unwrap(); let config = Config::from_bytes(&config_account.data).unwrap(); assert!(config.oracle_setup == OracleSetup::Stub); let update_update_oracle_type_args = UpdateOracleTypeInstructionArgs { oracle_setup: OracleSetup::Stub, }; let update_oracle_type = UpdateOracleType { admin_wallet: et.context.payer.pubkey(), config_account: find_config_pda().0, system_program: solana_program::system_program::id(), } .instruction(update_update_oracle_type_args); let ixs = &[update_oracle_type]; let transaction = Transaction::new_signed_with_payer( ixs, Some(&et.context.payer.pubkey()), &[&et.context.payer], et.context.last_blockhash, ); let error = et .context .banks_client .process_transaction(transaction) .await .err() .unwrap() .unwrap(); match error { TransactionError::InstructionError(_, InstructionError::Custom(error_index)) => { let program_error = StablebondError::AdminConfigMismatch as u32; assert_eq!(error_index, program_error + 6000); } _ => { panic!("Wrong error occurs while testing updating oracle type"); } } }