templar_common/oracle/proxy/
governance.rs

1use near_sdk::near;
2
3use crate::{
4    gen_ext_governance, governance::Validatable, oracle::pyth::PriceIdentifier, time::Nanoseconds,
5};
6
7use super::Proxy;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[near(serializers = [json, borsh])]
11pub enum Operation {
12    SetProxy {
13        id: PriceIdentifier,
14        proxy: Option<Proxy>,
15    },
16    SetActionTtl {
17        new_ttl: Nanoseconds,
18    },
19}
20
21impl Validatable for Operation {
22    type OnCreateError = ValidationError;
23    type OnExecuteError = ValidationError;
24
25    fn on_create(&self) -> Result<(), Self::OnCreateError> {
26        match self {
27            Operation::SetProxy {
28                proxy: Some(proxy), ..
29            } if proxy.entries.is_empty() => Err(ValidationError::EmptyProxyDefinition),
30            _ => Ok(()),
31        }
32    }
33
34    fn on_execute(&self) -> Result<(), Self::OnExecuteError> {
35        self.on_create()
36    }
37}
38
39#[derive(Debug, thiserror::Error, PartialEq, Eq)]
40pub enum ValidationError {
41    #[error("Empty proxy definition is not allowed")]
42    EmptyProxyDefinition,
43}
44
45gen_ext_governance!(ext_proxy_governance, ProxyGovernanceInterface, Operation);
46
47#[cfg(test)]
48mod tests {
49    use super::*;
50    use crate::oracle::OracleRequest;
51    use rstest::rstest;
52
53    fn invalid_operation() -> Operation {
54        Operation::SetProxy {
55            id: PriceIdentifier([0xaa; 32]),
56            proxy: Some(Proxy::median_low([])),
57        }
58    }
59
60    fn valid_operation() -> Operation {
61        Operation::SetProxy {
62            id: PriceIdentifier([0xff; 32]),
63            proxy: Some(Proxy::median_low([OracleRequest::pyth(
64                "pyth-oracle.near".parse().unwrap(),
65                PriceIdentifier([0xdd; 32]),
66            )
67            .into()])),
68        }
69    }
70
71    #[rstest]
72    #[case::valid(valid_operation())]
73    #[should_panic = "EmptyProxyDefinition"]
74    #[case::invalid(invalid_operation())]
75    fn on_create(#[case] operation: Operation) {
76        operation.on_create().unwrap();
77    }
78
79    #[rstest]
80    #[case::valid(valid_operation())]
81    #[should_panic = "EmptyProxyDefinition"]
82    #[case::invalid(invalid_operation())]
83    fn on_execute(#[case] operation: Operation) {
84        operation.on_execute().unwrap();
85    }
86}