store median in Answer struct
This commit is contained in:
parent
96a701663e
commit
ff0033e540
|
@ -37,6 +37,9 @@ pub enum Error {
|
|||
#[error("No resolve answer")]
|
||||
NoResolvedAnswer,
|
||||
|
||||
#[error("No submitted value")]
|
||||
NoSubmission,
|
||||
|
||||
#[error("Unknown error")]
|
||||
UnknownError,
|
||||
}
|
||||
|
|
|
@ -14,54 +14,22 @@ use borsh_state::InitBorshState;
|
|||
use solana_program::{
|
||||
account_info::AccountInfo, program_error::ProgramError, program_pack::IsInitialized,
|
||||
};
|
||||
use state::Aggregator;
|
||||
use state::{Aggregator, Answer};
|
||||
|
||||
#[cfg(not(feature = "no-entrypoint"))]
|
||||
pub mod entrypoint;
|
||||
|
||||
pub struct ResolvedMedian {
|
||||
pub value: u64,
|
||||
pub updated_at: u64,
|
||||
pub created_at: u64,
|
||||
}
|
||||
|
||||
/// Read resolved median value from the aggregator answer submissions
|
||||
pub fn read_median(
|
||||
aggregator_info: &AccountInfo,
|
||||
answer_submissions_info: &AccountInfo,
|
||||
) -> Result<ResolvedMedian, ProgramError> {
|
||||
) -> Result<Answer, ProgramError> {
|
||||
let aggregator = Aggregator::load_initialized(&aggregator_info)?;
|
||||
|
||||
if !aggregator.answer.is_initialized() {
|
||||
return Err(Error::NoResolvedAnswer)?;
|
||||
}
|
||||
|
||||
let submissions = aggregator.answer_submissions(answer_submissions_info)?;
|
||||
|
||||
let mut values: Vec<_> = submissions
|
||||
.data
|
||||
.iter()
|
||||
.filter(|s| s.is_initialized())
|
||||
.map(|s| s.value)
|
||||
.collect();
|
||||
|
||||
// get median value
|
||||
values.sort();
|
||||
|
||||
let median: u64;
|
||||
let l = values.len();
|
||||
let i = l / 2;
|
||||
if l % 2 == 0 {
|
||||
median = (values[i] + values[i - 1]) / 2;
|
||||
} else {
|
||||
median = values[i];
|
||||
}
|
||||
|
||||
Ok(ResolvedMedian {
|
||||
value: median,
|
||||
updated_at: aggregator.answer.updated_at,
|
||||
created_at: aggregator.answer.created_at,
|
||||
})
|
||||
Ok(aggregator.answer)
|
||||
}
|
||||
|
||||
// Export current sdk types for downstream users building with a different
|
||||
|
|
|
@ -258,11 +258,13 @@ impl<'a> SubmitContext<'a> {
|
|||
answer.created_at = now;
|
||||
answer.updated_at = now;
|
||||
answer_submissions.data = round_submissions.data;
|
||||
|
||||
} else {
|
||||
answer.updated_at = now;
|
||||
answer_submissions.data[i] = new_submission;
|
||||
}
|
||||
|
||||
answer.median = answer_submissions.median()?;
|
||||
answer_submissions.save(self.answer_submissions)?;
|
||||
|
||||
Ok(())
|
||||
|
@ -833,6 +835,7 @@ mod tests {
|
|||
assert_eq!(answer.round_id, 1);
|
||||
assert_eq!(answer.updated_at, time);
|
||||
assert_eq!(answer.created_at, time);
|
||||
assert_eq!(answer.median, 15);
|
||||
|
||||
assert_eq!(tt.answer_submission(0)?.value, 10);
|
||||
assert_eq!(tt.answer_submission(1)?.value, 20);
|
||||
|
|
|
@ -66,6 +66,40 @@ pub struct Submissions {
|
|||
// pub data: Vec<Submission>,
|
||||
}
|
||||
|
||||
pub struct ResolvedMedian {
|
||||
pub value: u64,
|
||||
pub updated_at: u64,
|
||||
pub created_at: u64,
|
||||
}
|
||||
|
||||
impl Submissions {
|
||||
pub fn median(&self) -> Result<u64, ProgramError> {
|
||||
let mut values: Vec<_> = self.data
|
||||
.iter()
|
||||
.filter(|s| s.is_initialized())
|
||||
.map(|s| s.value)
|
||||
.collect();
|
||||
|
||||
if values.is_empty() {
|
||||
return Err(Error::NoSubmission)?;
|
||||
}
|
||||
|
||||
// get median value
|
||||
values.sort();
|
||||
|
||||
let median: u64;
|
||||
let l = values.len();
|
||||
let i = l / 2;
|
||||
if l % 2 == 0 {
|
||||
median = (values[i] + values[i - 1]) / 2;
|
||||
} else {
|
||||
median = values[i];
|
||||
}
|
||||
|
||||
Ok(median)
|
||||
}
|
||||
}
|
||||
|
||||
impl IsInitialized for Submissions {
|
||||
fn is_initialized(&self) -> bool {
|
||||
self.is_initialized
|
||||
|
@ -84,6 +118,7 @@ pub struct Round {
|
|||
#[derive(Clone, Debug, BorshSerialize, BorshDeserialize, BorshSchema, Default, PartialEq)]
|
||||
pub struct Answer {
|
||||
pub round_id: u64,
|
||||
pub median: u64,
|
||||
pub created_at: u64,
|
||||
pub updated_at: u64,
|
||||
}
|
||||
|
|
|
@ -161,6 +161,7 @@ class Round extends Serialization {
|
|||
|
||||
class Answer extends Serialization {
|
||||
public round_id!: BN
|
||||
public median!: BN
|
||||
public created_at!: BN
|
||||
public updated_at!: BN
|
||||
|
||||
|
@ -168,6 +169,7 @@ class Answer extends Serialization {
|
|||
kind: "struct",
|
||||
fields: [
|
||||
["round_id", "u64"],
|
||||
["median", "u64"],
|
||||
["created_at", "u64"],
|
||||
["updated_at", "u64"],
|
||||
],
|
||||
|
@ -175,7 +177,7 @@ class Answer extends Serialization {
|
|||
}
|
||||
|
||||
export class Aggregator extends Serialization {
|
||||
public static size = 189
|
||||
public static size = 197
|
||||
|
||||
public config!: AggregatorConfig
|
||||
public roundSubmissions!: PublicKey
|
||||
|
|
Loading…
Reference in New Issue