Skip to content

Commit 48e702f

Browse files
authored
Add support for creating feeds in genesis (smartcontractkit#79)
* feat: add feedbuilder to genesis config * add genesis feed test * add feeds to config * import sp std prelude * update types.json with latest feedconfigof * add specs * export feedbuilder and add example * add spec with admin without endowment * add serde json * try to parse and update chainlink feed config * document modified chain option * allow json string as parameter * fix: make compatible with new bounded desc
1 parent 56ef905 commit 48e702f

File tree

17 files changed

+924
-128
lines changed

17 files changed

+924
-128
lines changed

pallet-chainlink-feed/src/benchmarking.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ benchmarks! {
625625
reduce_debt {
626626
let caller: T::AccountId = whitelisted_caller();
627627
let pallet_admin: T::AccountId = ChainlinkFeed::<T>::pallet_admin();
628-
assert_is_ok(ChainlinkFeed::<T>::set_feed_creator(RawOrigin::Signed(pallet_admin).into(), caller.clone()));
628+
assert_is_ok(ChainlinkFeed::<T>::set_feed_creator(RawOrigin::Signed(pallet_admin.clone()).into(), caller.clone()));
629629
let oracle: T::AccountId = account("oracle", 0, SEED);
630630
let admin: T::AccountId = account("oracle_admin", 0, SEED);
631631
let payment = 600u32.into();

pallet-chainlink-feed/src/feed.rs

+208
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
//! utils for creating feeds
2+
3+
use crate::{BalanceOf, Config, FeedConfig, RoundId};
4+
use frame_support::{
5+
sp_runtime::traits::{One, Zero},
6+
BoundedVec, Parameter,
7+
};
8+
use sp_std::prelude::*;
9+
10+
use frame_support::sp_std::convert::TryInto;
11+
use frame_support::traits::Get;
12+
#[cfg(feature = "std")]
13+
use serde::{Deserialize, Serialize};
14+
15+
/// Builder with all the parameters to call the `create_feed`
16+
#[derive(Clone)]
17+
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
18+
pub struct FeedBuilder<AccountId, Balance, BlockNumber, Value> {
19+
#[cfg_attr(
20+
feature = "std",
21+
serde(bound(
22+
serialize = "Option<AccountId>: Serialize",
23+
deserialize = "Option<AccountId>: Deserialize<'de>"
24+
))
25+
)]
26+
pub owner: Option<AccountId>,
27+
#[cfg_attr(
28+
feature = "std",
29+
serde(bound(
30+
serialize = "Option<Balance>: Serialize",
31+
deserialize = "Option<Balance>: Deserialize<'de>"
32+
))
33+
)]
34+
pub payment: Option<Balance>,
35+
#[cfg_attr(
36+
feature = "std",
37+
serde(bound(
38+
serialize = "Option<BlockNumber>: Serialize",
39+
deserialize = "Option<BlockNumber>: Deserialize<'de>"
40+
))
41+
)]
42+
pub timeout: Option<BlockNumber>,
43+
#[cfg_attr(
44+
feature = "std",
45+
serde(bound(
46+
serialize = "Option<(Value, Value)>: Serialize",
47+
deserialize = "Option<(Value, Value)>: Deserialize<'de>"
48+
))
49+
)]
50+
pub value_bounds: Option<(Value, Value)>,
51+
pub min_submissions: Option<u32>,
52+
pub description: Option<Vec<u8>>,
53+
pub decimals: Option<u8>,
54+
pub restart_delay: Option<u32>,
55+
#[cfg_attr(
56+
feature = "std",
57+
serde(bound(
58+
serialize = "Option<Vec<(AccountId, AccountId)>>: Serialize",
59+
deserialize = "Option<Vec<(AccountId, AccountId)>>: Deserialize<'de>"
60+
))
61+
)]
62+
pub oracles: Option<Vec<(AccountId, AccountId)>>,
63+
pub pruning_window: Option<u32>,
64+
#[cfg_attr(
65+
feature = "std",
66+
serde(bound(
67+
serialize = "Option<Balance>: Serialize",
68+
deserialize = "Option<Balance>: Deserialize<'de>"
69+
))
70+
)]
71+
pub max_debt: Option<Balance>,
72+
}
73+
74+
impl<AccountId, Balance, BlockNumber, Value> FeedBuilder<AccountId, Balance, BlockNumber, Value>
75+
where
76+
AccountId: Parameter,
77+
Balance: Parameter + Zero,
78+
BlockNumber: Parameter,
79+
Value: Parameter,
80+
{
81+
pub fn new() -> Self {
82+
Self::default()
83+
}
84+
85+
pub fn owner(mut self, o: AccountId) -> Self {
86+
self.owner = Some(o);
87+
self
88+
}
89+
90+
pub fn payment(mut self, p: Balance) -> Self {
91+
self.payment = Some(p);
92+
self
93+
}
94+
95+
pub fn timeout(mut self, t: BlockNumber) -> Self {
96+
self.timeout = Some(t);
97+
self
98+
}
99+
100+
pub fn value_bounds(mut self, min: Value, max: Value) -> Self {
101+
self.value_bounds = Some((min, max));
102+
self
103+
}
104+
105+
pub fn min_submissions(mut self, m: u32) -> Self {
106+
self.min_submissions = Some(m);
107+
self
108+
}
109+
110+
pub fn description(mut self, d: Vec<u8>) -> Self {
111+
self.description = Some(d);
112+
self
113+
}
114+
115+
pub fn restart_delay(mut self, d: u32) -> Self {
116+
self.restart_delay = Some(d);
117+
self
118+
}
119+
120+
pub fn oracles(mut self, o: Vec<(AccountId, AccountId)>) -> Self {
121+
self.oracles = Some(o);
122+
self
123+
}
124+
125+
pub fn decimals(mut self, decimals: u8) -> Self {
126+
self.decimals = Some(decimals);
127+
self
128+
}
129+
130+
pub fn pruning_window(mut self, w: u32) -> Self {
131+
self.pruning_window = Some(w);
132+
self
133+
}
134+
135+
pub fn max_debt(mut self, v: Balance) -> Self {
136+
self.max_debt = Some(v);
137+
self
138+
}
139+
140+
/// turn the builder into a storage `FeedConfig`
141+
pub fn build<'a, StringLimit: Get<u32>>(
142+
self,
143+
) -> Result<
144+
FeedConfig<AccountId, Balance, BlockNumber, Value, BoundedVec<u8, StringLimit>>,
145+
&'static str,
146+
> {
147+
let oracles = self.oracles.ok_or("Feed requires oracles.")?;
148+
let submission_count_bounds = (
149+
self.min_submissions
150+
.ok_or("Feed requires min_submissions.")?,
151+
oracles.len() as u32,
152+
);
153+
154+
let description = if let Some(desc) = self.description {
155+
desc.try_into().map_err(|_| "Feed description too long.")?
156+
} else {
157+
Default::default()
158+
};
159+
160+
let config = FeedConfig {
161+
owner: self.owner.ok_or("Feed requires owner.")?,
162+
pending_owner: None,
163+
submission_value_bounds: self.value_bounds.ok_or("Feed requires value_bounds.")?,
164+
submission_count_bounds,
165+
payment: self.payment.ok_or("Feed requires payment.")?,
166+
timeout: self.timeout.ok_or("Feed requires timeout.")?,
167+
decimals: self.decimals.ok_or("Feed requires decimals.")?,
168+
description,
169+
restart_delay: self.restart_delay.ok_or("Feed requires restart_delay.")?,
170+
reporting_round: Zero::zero(),
171+
latest_round: Zero::zero(),
172+
first_valid_round: None,
173+
oracle_count: Zero::zero(),
174+
pruning_window: self.pruning_window.unwrap_or(RoundId::MAX),
175+
next_round_to_prune: RoundId::one(),
176+
debt: Zero::zero(),
177+
max_debt: self.max_debt,
178+
};
179+
Ok(config)
180+
}
181+
}
182+
183+
impl<AccountId, Balance, BlockNumber, Value> Default
184+
for FeedBuilder<AccountId, Balance, BlockNumber, Value>
185+
{
186+
fn default() -> Self {
187+
Self {
188+
owner: None,
189+
payment: None,
190+
timeout: None,
191+
value_bounds: None,
192+
min_submissions: None,
193+
description: None,
194+
decimals: None,
195+
restart_delay: None,
196+
oracles: None,
197+
pruning_window: None,
198+
max_debt: None,
199+
}
200+
}
201+
}
202+
203+
pub type FeedBuilderOf<T> = FeedBuilder<
204+
<T as frame_system::Config>::AccountId,
205+
BalanceOf<T>,
206+
<T as frame_system::Config>::BlockNumber,
207+
<T as Config>::Value,
208+
>;

0 commit comments

Comments
 (0)