1use crate::core_types::{Coin, MsgInternal};
2
3use crate::messages::Message;
4use crypto::digest::Digest;
5use crypto::sha2::Sha256;
6use serde::{Deserialize, Serialize};
7use std::ops::Add;
8
9#[derive(Deserialize, Serialize, Debug)]
10
11pub struct MsgAggregateExchangeRatePreVote {
13 pub feeder: String,
14 pub hash: String,
15 pub validator: String,
16}
17
18impl MsgInternal for MsgAggregateExchangeRatePreVote {}
19impl MsgAggregateExchangeRatePreVote {
20 pub fn create(hash: String, feeder: String, validator: String) -> anyhow::Result<Message> {
22 let internal = MsgAggregateExchangeRatePreVote {
23 feeder,
24 hash,
25 validator,
26 };
27 Ok(Message {
28 s_type: "oracle/MsgAggregateExchangeRatePrevote".into(),
29 value: serde_json::to_value(internal)?,
30 })
31 }
32}
33
34#[derive(Deserialize, Serialize, Debug)]
35
36pub struct MsgAggregateExchangeRateVote {
38 pub exchange_rates: String,
39 pub feeder: String,
40 pub salt: String,
42 pub validator: String,
43}
44
45fn generate_hash<'a>(salt: &'a str, exchange_string: &'a str, validator: &'a str) -> String {
47 let mut sha = Sha256::new();
48 let mut to_hash: String = String::new();
49 to_hash = to_hash.add(salt);
50 to_hash = to_hash.add(":");
51 to_hash = to_hash.add(exchange_string);
52 to_hash = to_hash.add(":");
53 to_hash = to_hash.add(validator);
54 sha.input_str(&to_hash);
55 let full_hash = sha.result_str();
56 full_hash.split_at(40).0.parse().unwrap()
57}
58impl MsgInternal for MsgAggregateExchangeRateVote {}
59impl MsgAggregateExchangeRateVote {
60 fn generate_hash(&self, previous_salt: &str) -> String {
61 generate_hash(previous_salt, &self.exchange_rates, &self.validator)
62 }
63
64 pub fn create_internal(
65 salt: String,
66 exchange_rates: Vec<Coin>,
67 feeder: String,
68 validator: String,
69 ) -> MsgAggregateExchangeRateVote {
70 let mut new_rates: Vec<Coin> = Vec::with_capacity(exchange_rates.len());
71 for rate in exchange_rates {
72 new_rates.push(rate);
73 }
74 new_rates.sort_by(|a, b| a.denom.cmp(&b.denom));
75 let coins = new_rates
76 .iter()
77 .map(|f| f.to_string())
78 .collect::<Vec<String>>()
79 .join(",");
80 MsgAggregateExchangeRateVote {
81 salt,
82 exchange_rates: coins,
83 feeder,
84 validator,
85 }
86 }
87 pub fn create(
89 salt: String,
90 exchange_rates: Vec<Coin>,
91 feeder: String,
92 validator: String,
93 ) -> anyhow::Result<Message> {
94 let internal =
95 MsgAggregateExchangeRateVote::create_internal(salt, exchange_rates, feeder, validator);
96 Ok(Message {
97 s_type: "oracle/MsgAggregateExchangeRateVote".into(),
98 value: serde_json::to_value(internal)?,
99 })
100 }
101 pub fn create_from_internal(internal: MsgAggregateExchangeRateVote) -> anyhow::Result<Message> {
103 Ok(Message {
106 s_type: "oracle/MsgAggregateExchangeRateVote".into(),
107 value: serde_json::to_value(internal)?,
108 })
109 }
110
111 pub fn gen_pre_vote(&self, previous_salt: &str) -> anyhow::Result<Message> {
114 MsgAggregateExchangeRatePreVote::create(
115 self.generate_hash(previous_salt),
116 self.feeder.clone(),
117 self.validator.clone(),
118 )
119 }
120}
121
122#[derive(Deserialize, Serialize, Debug)]
123pub struct MsgDelegateFeedConsent {
126 pub delegate: String,
127 pub operator: String,
128}
129impl MsgInternal for MsgDelegateFeedConsent {}
130impl MsgDelegateFeedConsent {
131 pub fn create(operator: String, delegate: String) -> anyhow::Result<Message> {
133 let internal = MsgDelegateFeedConsent { delegate, operator };
134 Ok(Message {
135 s_type: "oracle/MsgDelegateFeedConsent".into(),
136 value: serde_json::to_value(internal)?,
137 })
138 }
139}
140
141#[cfg(test)]
142mod tst {
143 use super::*;
144 #[test]
145 pub fn test_agg() -> anyhow::Result<()> {
146 let exchange_rate_str = "22.540203133218404887uaud,21.645596278923282692ucad,15.966787551658593971uchf,113.167767068332957759ucny,14.449845494375560683ueur,12.582839885411827405ugbp,135.474594500430895984uhkd,1300.213822842493250029uinr,1900.8256376511075722ujpy,20351.150811544637337767ukrw,49749.106615326838874584umnt,12.154984433357638529usdr,23.143090361112943758usgd,0.0uthb,17.444833658754882816uusd";
147 let exchange_rates = Coin::parse_coins(exchange_rate_str)?;
148 let salt = String::from("df59");
149 let feeder = String::from("terra1824vxwh43h9d3qczj4jvc3qphlf2evfp9w0ph9");
150 let validator = String::from("terravaloper1usws7c2c6cs7nuc8vma9qzaky5pkgvm2ujy8ny");
151 let hash = "36681b69da96623a6ae12c2a51448b7426fdd64e";
152 let coins = exchange_rates
153 .iter()
154 .map(|f| f.to_string())
155 .collect::<Vec<String>>()
156 .join(",");
157 assert_eq!(coins, exchange_rate_str);
158
159 assert_eq!(generate_hash(&salt, exchange_rate_str, &validator), hash);
160 let vote_1 = MsgAggregateExchangeRateVote::create_internal(
161 salt.clone(),
162 exchange_rates,
163 feeder,
164 validator,
165 );
166
167 assert_eq!(vote_1.generate_hash(&salt), hash);
168 Ok(())
172 }
173 #[test]
174 pub fn tst_hash() -> anyhow::Result<()> {
175 let exchange_rates= "22.540203133218404887uaud,21.645596278923282692ucad,15.966787551658593971uchf,113.167767068332957759ucny,14.449845494375560683ueur,12.582839885411827405ugbp,135.474594500430895984uhkd,1300.213822842493250029uinr,1900.8256376511075722ujpy,20351.150811544637337767ukrw,49749.106615326838874584umnt,12.154984433357638529usdr,23.143090361112943758usgd,0.0uthb,17.444833658754882816uusd";
176 let salt = "df59";
177 let validator = "terravaloper1usws7c2c6cs7nuc8vma9qzaky5pkgvm2ujy8ny";
178 let hash = "36681b69da96623a6ae12c2a51448b7426fdd64e";
179 assert_eq!(hash, generate_hash(salt, exchange_rates, validator));
180 let exchange_rates2="22.548222362821767308uaud,21.653297230216244188ucad,15.972468127589880034uchf,113.208029274598674692ucny,14.454986380997906048ueur,12.58731653903855345ugbp,135.522792907175522923uhkd,1300.676405771192471765uinr,1901.501902950678788445ujpy,20358.286256112132944846ukrw,49766.806079087327983387umnt,12.159308866922868479usdr,23.151324082621141584usgd,0.0uthb,17.451040085807700841uusd";
181 let salt2 = "6dd4";
182 let validator2 = "terravaloper1usws7c2c6cs7nuc8vma9qzaky5pkgvm2ujy8ny";
183 let hash2 = "54a849b1b3b510f5f0b7c5405ed2cc74cd283251";
184 assert_eq!(hash2, generate_hash(salt2, exchange_rates2, validator2));
185
186 Ok(())
187 }
188}