use rialo_s_instruction::{AccountMeta, Instruction};
use rialo_s_program::system_program;
use rialo_s_pubkey::Pubkey;
use rialo_types::{Nonce, RexId};
use serde::{Deserialize, Serialize};
pub use crate::state::RexUpdate;
pub const REX_REPORT_SEED: &[u8] = b"rex_report";
pub const REX_REPORT_PAYER_SEED: &[u8] = b"report_payer";
pub const REX_UPDATE_PAYER: Pubkey =
Pubkey::from_str_const("Qrac1eUpdatePayer11111111111111111111111111");
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub enum RexProcessorInstruction {
Report {
rex_id: RexId,
updates: Vec<RexUpdate>,
},
}
impl RexProcessorInstruction {
pub fn report(payer: Pubkey, rex_id: RexId, updates: Vec<RexUpdate>) -> Instruction {
use rialo_events_core::derive_event_address;
use crate::event::RexReportEvent;
let (report_key, _bump) = derive_report_address(&rex_id.creator, rex_id.nonce);
let event = RexReportEvent::new(rex_id);
let (event_key, _bump) = derive_event_address(&event.instance_topic(), &crate::id());
Instruction::new_with_bincode(
crate::id(),
&RexProcessorInstruction::Report { rex_id, updates },
vec![
AccountMeta::new(payer, true),
AccountMeta::new(report_key, false),
AccountMeta::new(event_key, false),
AccountMeta::new_readonly(system_program::id(), false),
],
)
}
}
pub fn derive_report_address<NONCE: Into<Nonce>>(creator: &Pubkey, nonce: NONCE) -> (Pubkey, u8) {
let nonce: Nonce = nonce.into();
Pubkey::find_program_address(
&[REX_REPORT_SEED, &creator.to_bytes(), nonce.as_bytes()],
&crate::id(),
)
}
#[cfg(test)]
mod tests {
use rialo_events_core::RialoEvent;
use rialo_s_pubkey::Pubkey;
use super::*;
#[derive(Default, RialoEvent)]
struct TestEvent {
name: String,
value: u64,
}
#[test]
fn test_report_rex_updates() {
use rialo_events_core::derive_event_address;
use crate::event::RexReportEvent;
let authority_key = [0; 96];
let payer = Pubkey::new_unique();
let data = vec![0, 1, 2, 3];
let updates = vec![RexUpdate::new(data, authority_key)];
let nonce = Nonce::from(b"test-rex-42");
let rex_id = RexId::new(payer, nonce);
let instruction = RexProcessorInstruction::report(payer, rex_id, updates.clone());
let event = RexReportEvent::new(rex_id);
let (expected_event_key, _) = derive_event_address(&event.instance_topic(), &crate::id());
let expected_accounts = vec![
AccountMeta::new(payer, true),
AccountMeta::new(
derive_report_address(&rex_id.creator, rex_id.nonce).0,
false,
),
AccountMeta::new(expected_event_key, false),
AccountMeta::new_readonly(system_program::id(), false),
];
let expected_data = bincode::serialize(&RexProcessorInstruction::Report {
rex_id,
updates: updates.clone(),
})
.unwrap();
assert_eq!(instruction.data, expected_data);
assert_eq!(instruction.accounts, expected_accounts);
assert_eq!(instruction.program_id, crate::id());
}
#[test]
fn test_report_address_derivation() {
let creator = Pubkey::new_unique();
let (report_pubkey1, _) = derive_report_address(&creator, b"test-rex-a42");
let (report_pubkey2, _) = derive_report_address(&creator, b"test-rex-43");
assert_ne!(report_pubkey1, report_pubkey2);
}
}