/home/runner/work/creditcoin/creditcoin/pallets/creditcoin/src/types/loan_terms.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use core::ops::Deref; |
2 | | |
3 | | use crate::CurrencyId; |
4 | | |
5 | | use super::ExternalAmount; |
6 | | use codec::{Decode, Encode, MaxEncodedLen}; |
7 | | use frame_support::RuntimeDebug; |
8 | | use scale_info::TypeInfo; |
9 | | use sp_std::convert::TryFrom; |
10 | | |
11 | | pub type RatePerPeriod = u64; |
12 | | pub type Decimals = u64; |
13 | 2.24k | #[derive(Clone1.45k , Copy, Encode1.30k , Decode, Eq, P627 artialEq627 , RuntimeDebug14 , TypeInfo2 , MaxEncodedLen14 )] |
14 | 1 | pub struct Duration { |
15 | | secs: u64, |
16 | | nanos: u32, |
17 | | } |
18 | | |
19 | | const MILLIS_PER_SEC: u64 = 1_000; |
20 | | const NANOS_PER_MILLI: u32 = 1_000_000; |
21 | | |
22 | | impl Duration { |
23 | 1 | pub const fn new(secs: u64, nanos: u32) -> Self { |
24 | 1 | Self { secs, nanos } |
25 | 1 | } |
26 | 456 | pub const fn from_millis(millis: u64) -> Self { |
27 | 456 | Self { |
28 | 456 | secs: millis / MILLIS_PER_SEC, |
29 | 456 | nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI, |
30 | 456 | } |
31 | 456 | } |
32 | | |
33 | 309 | pub const fn is_zero(&self) -> bool { |
34 | 309 | self.secs == 0 && self.nanos == 01 |
35 | 309 | } |
36 | | } |
37 | | |
38 | 1.11k | #[derive(Clone728 , Copy, E646 ncode646 , Decode, Eq, PartialEq315 , R8 untimeDebug8 , TypeInfo2 , MaxEncodedLen8 )] |
39 | 1 | pub enum InterestType { |
40 | | Simple, |
41 | | Compound, |
42 | | } |
43 | | |
44 | 1.11k | #[derive(Clone726 , Encode645 , Decode, Eq, P309 artialEq309 , RuntimeDebug7 , TypeInfo4 , MaxEncodedLen7 )] |
45 | 1 | pub struct InterestRate { |
46 | | pub rate_per_period: RatePerPeriod, |
47 | | pub decimals: Decimals, |
48 | | pub period: Duration, |
49 | | pub interest_type: InterestType, |
50 | | } |
51 | | |
52 | 1.10k | #[derive(Clone724 , Encode633 , Decode, Eq, P48 artialEq48 , RuntimeDebug6 , TypeInfo4 , MaxEncodedLen6 )] |
53 | 1 | pub struct LoanTerms<Hash> { |
54 | | pub amount: ExternalAmount, |
55 | | pub interest_rate: InterestRate, |
56 | | pub term_length: Duration, |
57 | | pub currency: CurrencyId<Hash>, |
58 | | } |
59 | | |
60 | 403 | #[derive(Clone148 , Encode, Decode, Eq, PartialEq16 , RuntimeDebug2 , TypeInfo1 , MaxEncodedLen2 )] |
61 | 192 | pub struct AskTerms<Hash>(LoanTerms<Hash>); |
62 | | |
63 | | impl<Hash> Deref for AskTerms<Hash> { |
64 | | type Target = LoanTerms<Hash>; |
65 | | |
66 | 756 | fn deref(&self) -> &Self::Target { |
67 | 756 | &self.0 |
68 | 756 | } |
69 | | } |
70 | | |
71 | 1 | #[derive(Clone, Copy, RuntimeDebug)] |
72 | | pub struct InvalidTermLengthError; |
73 | | |
74 | | impl<T: crate::Config> From<InvalidTermLengthError> for crate::Error<T> { |
75 | 1 | fn from(_: InvalidTermLengthError) -> Self { |
76 | 1 | Self::InvalidTermLength |
77 | 1 | } |
78 | | } |
79 | | |
80 | | impl<Hash> TryFrom<LoanTerms<Hash>> for AskTerms<Hash> { |
81 | | type Error = InvalidTermLengthError; |
82 | 154 | fn try_from(terms: LoanTerms<Hash>) -> Result<Self, Self::Error> { |
83 | 154 | if terms.term_length.is_zero() { |
84 | 0 | return Err(InvalidTermLengthError); |
85 | 154 | } |
86 | 154 | |
87 | 154 | Ok(Self(terms)) |
88 | 154 | } |
89 | | } |
90 | | |
91 | | impl<Hash> AskTerms<Hash> { |
92 | 252 | pub fn match_with(&self, bid_terms: &BidTerms<Hash>) -> bool { |
93 | 252 | self.amount == bid_terms.amount |
94 | 252 | && self.interest_rate == bid_terms.interest_rate |
95 | 252 | && self.term_length == bid_terms.term_length |
96 | 252 | } |
97 | | |
98 | 120 | pub fn agreed_terms(&self, bid_terms: BidTerms<Hash>) -> Option<LoanTerms<Hash>> { |
99 | 120 | self.match_with(&bid_terms).then_some(bid_terms.0) |
100 | 120 | } |
101 | | } |
102 | | |
103 | 403 | #[derive(Clone149 , Encode, Decode, Eq, PartialEq16 , RuntimeDebug2 , TypeInfo1 , MaxEncodedLen2 )] |
104 | 192 | pub struct BidTerms<Hash>(LoanTerms<Hash>); |
105 | | |
106 | | impl<Hash> Deref for BidTerms<Hash> { |
107 | | type Target = LoanTerms<Hash>; |
108 | | |
109 | 756 | fn deref(&self) -> &Self::Target { |
110 | 756 | &self.0 |
111 | 756 | } |
112 | | } |
113 | | |
114 | | impl<Hash> TryFrom<LoanTerms<Hash>> for BidTerms<Hash> { |
115 | | type Error = InvalidTermLengthError; |
116 | 155 | fn try_from(terms: LoanTerms<Hash>) -> Result<Self, Self::Error> { |
117 | 155 | if terms.term_length.is_zero() { |
118 | 1 | return Err(InvalidTermLengthError); |
119 | 154 | } |
120 | 154 | |
121 | 154 | Ok(Self(terms)) |
122 | 155 | } |
123 | | } |
124 | | |
125 | | impl<Hash> BidTerms<Hash> { |
126 | 1 | pub fn match_with(&self, ask_terms: &AskTerms<Hash>) -> bool { |
127 | 1 | ask_terms.match_with(self) |
128 | 1 | } |
129 | | |
130 | 1 | pub fn agreed_terms(self, ask_terms: &AskTerms<Hash>) -> Option<LoanTerms<Hash>> { |
131 | 1 | ask_terms.agreed_terms(self) |
132 | 1 | } |
133 | | } |
134 | | |
135 | | #[cfg(test)] |
136 | | impl Default for LoanTerms<sp_core::H256> { |
137 | 182 | fn default() -> Self { |
138 | 182 | Self { |
139 | 182 | amount: Default::default(), |
140 | 182 | interest_rate: InterestRate::default(), |
141 | 182 | term_length: Duration::from_millis(100_000), |
142 | 182 | currency: CurrencyId::new::<crate::mock::Test>(&crate::Currency::default()), |
143 | 182 | } |
144 | 182 | } |
145 | | } |
146 | | #[cfg(test)] |
147 | | impl Default for InterestRate { |
148 | 208 | fn default() -> Self { |
149 | 208 | Self { |
150 | 208 | rate_per_period: 0, |
151 | 208 | decimals: 1, |
152 | 208 | period: Duration::from_millis(100_000), |
153 | 208 | interest_type: InterestType::Simple, |
154 | 208 | } |
155 | 208 | } |
156 | | } |