1use crate::error::Result;
2use crate::{
3 model::{Amount, Id, PrivateKey, Proof, PublicKey},
4 util::{sign_order, BinarySerializer, Hash},
5};
6
7use super::{Order, OrderType, PriceMode, SignedOrder};
8
9#[derive(Eq, PartialEq, Clone, Debug)]
10pub struct OrderInfoV4 {
11 id: Id,
12 chain_id: u8,
13 timestamp: u64,
14 sender: PublicKey,
15 fee: Amount,
16 order_type: OrderType,
17 amount: Amount,
18 price: Amount,
19 matcher: PublicKey,
20 expiration: u64,
21 proofs: Vec<Proof>,
22 price_mode: PriceMode,
23 }
26
27impl OrderInfoV4 {
28 #[allow(clippy::too_many_arguments)]
29 pub fn new(
30 id: Id,
31 chain_id: u8,
32 timestamp: u64,
33 sender: PublicKey,
34 fee: Amount,
35 order_type: OrderType,
36 amount: Amount,
37 price: Amount,
38 matcher: PublicKey,
39 expiration: u64,
40 proofs: Vec<Proof>,
41 price_mode: PriceMode,
42 ) -> Self {
43 Self {
44 id,
45 chain_id,
46 timestamp,
47 sender,
48 fee,
49 order_type,
50 amount,
51 price,
52 matcher,
53 expiration,
54 proofs,
55 price_mode,
56 }
57 }
58
59 pub fn chain_id(&self) -> u8 {
60 self.chain_id
61 }
62
63 pub fn version(&self) -> u8 {
64 4
65 }
66
67 pub fn sender(&self) -> PublicKey {
68 self.sender.clone()
69 }
70
71 pub fn timestamp(&self) -> u64 {
72 self.timestamp
73 }
74
75 pub fn fee(&self) -> Amount {
76 self.fee.clone()
77 }
78
79 pub fn order_type(&self) -> OrderType {
80 self.order_type.clone()
81 }
82
83 pub fn amount(&self) -> Amount {
84 self.amount.clone()
85 }
86
87 pub fn price(&self) -> Amount {
88 self.price.clone()
89 }
90
91 pub fn matcher(&self) -> PublicKey {
92 self.matcher.clone()
93 }
94
95 pub fn expiration(&self) -> u64 {
96 self.expiration
97 }
98
99 pub fn id(&self) -> Id {
100 self.id.clone()
101 }
102
103 pub fn proofs(&self) -> Vec<Proof> {
104 self.proofs.clone()
105 }
106
107 pub fn with_proofs(mut self, proofs: Vec<Proof>) -> Self {
108 self.proofs = proofs;
109 self
110 }
111
112 pub fn price_mode(&self) -> PriceMode {
113 self.price_mode.clone()
114 }
115}
116
117#[derive(Eq, PartialEq, Clone, Debug)]
118pub struct OrderV4 {
119 chain_id: u8,
120 timestamp: u64,
121 sender: PublicKey,
122 fee: Amount,
123 order_type: OrderType,
124 amount: Amount,
125 price: Amount,
126 matcher: PublicKey,
127 expiration: u64,
128 price_mode: PriceMode,
129 }
131
132#[allow(clippy::too_many_arguments)]
134impl OrderV4 {
135 pub fn new(
136 chain_id: u8,
137 timestamp: u64,
138 sender: PublicKey,
139 fee: Amount,
140 order_type: OrderType,
141 amount: Amount,
142 price: Amount,
143 matcher: PublicKey,
144 expiration: u64,
145 price_mode: PriceMode,
146 ) -> Self {
147 Self {
148 chain_id,
149 timestamp,
150 sender,
151 fee,
152 order_type,
153 amount,
154 price,
155 matcher,
156 expiration,
157 price_mode,
158 }
159 }
160
161 pub fn chain_id(&self) -> u8 {
162 self.chain_id
163 }
164
165 pub fn version(&self) -> u8 {
166 4
167 }
168
169 pub fn sender(&self) -> PublicKey {
170 self.sender.clone()
171 }
172
173 pub fn timestamp(&self) -> u64 {
174 self.timestamp
175 }
176
177 pub fn fee(&self) -> Amount {
178 self.fee.clone()
179 }
180
181 pub fn order_type(&self) -> OrderType {
182 self.order_type.clone()
183 }
184
185 pub fn amount(&self) -> Amount {
186 self.amount.clone()
187 }
188
189 pub fn price(&self) -> Amount {
190 self.price.clone()
191 }
192
193 pub fn matcher(&self) -> PublicKey {
194 self.matcher.clone()
195 }
196
197 pub fn expiration(&self) -> u64 {
198 self.expiration
199 }
200
201 pub fn price_mode(&self) -> PriceMode {
202 self.price_mode.clone()
203 }
204
205 pub fn id(&self) -> Result<Id> {
206 Ok(Id::from_bytes(&Hash::blake(&self.bytes()?)?))
207 }
208
209 pub fn bytes(&self) -> Result<Vec<u8>> {
210 BinarySerializer::order_body_bytes(&Order::V4(self.clone()))
211 }
212
213 pub fn sign(&self, private_key: &PrivateKey) -> Result<SignedOrder> {
218 sign_order(&Order::V4(self.clone()), private_key)
219 }
220
221 pub fn default_expiration(current_time: u64) -> u64 {
222 current_time + (30 * 24 * 60 * 60 * 1000)
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use crate::model::{Amount, AssetId, ByteString, PublicKey};
229
230 use super::OrderV4;
231
232 #[test]
233 fn test_order_id_calculation() {
234 let order = OrderV4 {
235 chain_id: 84,
236 timestamp: 1666571041063,
237 sender: PublicKey::from_string("BDSyopLzAjMYvQSm4XuMA2gtjP5TPoZMWQ1sxnzTE1Y8")
238 .expect("failed to parse sender public key"),
239 fee: Amount::new(
240 99143,
241 Some(
242 AssetId::from_string("25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT")
243 .expect("failed to parse asset id"),
244 ),
245 ),
246 order_type: super::OrderType::Buy,
247 amount: Amount::new(660949620, None),
248 price: Amount::new(
249 15000000,
250 Some(
251 AssetId::from_string("25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT")
252 .expect("failed to parse asset id"),
253 ),
254 ),
255 price_mode: super::PriceMode::AssetDecimals,
256 matcher: PublicKey::from_string("8QUAqtTckM5B8gvcuP7mMswat9SjKUuafJMusEoSn1Gy")
257 .expect("failed to parse matcher public key"),
258 expiration: 1669080241063,
259 };
260
261 assert_eq!(
262 "3DCDNkx3iw9UBhKfQgibxrCes1uXPeMaexpgf5kQyz18",
263 order.id().expect("failed to calculate order id").encoded()
264 );
265 }
266}