everscale_types/models/message/
in_message.rs1use crate::cell::*;
2use crate::dict::AugDictExtra;
3use crate::error::Error;
4use crate::models::{
5 CurrencyCollection, ExtInMsgInfo, IntMsgInfo, Lazy, Message, MsgEnvelope, MsgInfo,
6 OwnedMessage, Transaction,
7};
8use crate::num::Tokens;
9
10#[derive(Default, PartialEq, Eq, Clone, Debug, Store, Load)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct ImportFees {
14 pub fees_collected: Tokens,
16 pub value_imported: CurrencyCollection,
18}
19
20impl AugDictExtra for ImportFees {
21 fn comp_add(
22 left: &mut CellSlice,
23 right: &mut CellSlice,
24 b: &mut CellBuilder,
25 cx: &mut dyn CellContext,
26 ) -> Result<(), Error> {
27 let left = ok!(Self::load_from(left));
28 let right = ok!(Self::load_from(right));
29
30 Self {
31 fees_collected: ok!(left
32 .fees_collected
33 .checked_add(right.fees_collected)
34 .ok_or(Error::IntOverflow)),
35 value_imported: ok!(left.value_imported.checked_add(&right.value_imported)),
36 }
37 .store_into(b, cx)
38 }
39}
40
41#[derive(Clone, Debug, Eq, PartialEq)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize))]
44#[cfg_attr(feature = "serde", serde(tag = "ty"))]
45pub enum InMsg {
46 External(InMsgExternal),
48 Immediate(InMsgFinal),
50 Final(InMsgFinal),
52 Transit(InMsgTransit),
54}
55
56impl InMsg {
57 const MSG_IMPORT_EXT: u8 = 0b000;
58 const MSG_IMPORT_IMM: u8 = 0b011;
59 const MSG_IMPORT_FIN: u8 = 0b100;
60 const MSG_IMPORT_TR: u8 = 0b101;
61
62 pub fn load_transaction(&self) -> Result<Option<Transaction>, Error> {
70 match self {
71 Self::External(msg) => msg.load_transaction().map(Some),
72 Self::Immediate(msg) | Self::Final(msg) => msg.load_transaction().map(Some),
73 Self::Transit(_) => Ok(None),
74 }
75 }
76
77 pub fn transaction_cell(&self) -> Option<Cell> {
85 match self {
86 Self::External(msg) => Some(msg.transaction.cell.clone()),
87 Self::Immediate(msg) | Self::Final(msg) => Some(msg.transaction.cell.clone()),
88 Self::Transit(_) => None,
89 }
90 }
91
92 pub fn load_msg(&self) -> Result<Message<'_>, Error> {
94 match self {
95 Self::External(msg) => msg.load_in_msg(),
96 Self::Immediate(msg) => msg.load_in_msg(),
97 Self::Final(msg) => msg.load_in_msg(),
98 Self::Transit(msg) => msg.load_in_msg(),
99 }
100 }
101
102 pub fn load_msg_owned(&self) -> Result<OwnedMessage, Error> {
104 match self {
105 Self::External(x) => x.load_in_msg_owned(),
106 Self::Immediate(x) => x.load_in_msg_owned(),
107 Self::Final(x) => x.load_in_msg_owned(),
108 Self::Transit(x) => x.load_in_msg_owned(),
109 }
110 }
111
112 pub fn load_msg_cell(&self) -> Result<Cell, Error> {
114 match self {
115 Self::External(msg) => Ok(msg.in_msg.cell.clone()),
116 Self::Immediate(msg) => msg.load_in_msg_cell(),
117 Self::Final(msg) => msg.load_in_msg_cell(),
118 Self::Transit(msg) => msg.load_in_msg_cell(),
119 }
120 }
121
122 pub fn in_msg_envelope_cell(&self) -> Option<Cell> {
124 match self {
125 Self::External(_) => None,
126 Self::Immediate(msg) => Some(msg.in_msg_envelope.cell.clone()),
127 Self::Final(msg) => Some(msg.in_msg_envelope.cell.clone()),
128 Self::Transit(msg) => Some(msg.in_msg_envelope.cell.clone()),
129 }
130 }
131
132 pub fn load_in_msg_envelope(&self) -> Result<Option<MsgEnvelope>, Error> {
134 match self {
135 Self::External(_) => Ok(None),
136 Self::Immediate(msg) => msg.load_in_msg_envelope().map(Some),
137 Self::Final(msg) => msg.load_in_msg_envelope().map(Some),
138 Self::Transit(msg) => msg.load_in_msg_envelope().map(Some),
139 }
140 }
141
142 pub fn out_msg_envelope_cell(&self) -> Option<Cell> {
144 match self {
145 Self::External(_) => None,
146 Self::Immediate(_) => None,
147 Self::Final(_) => None,
148 Self::Transit(msg) => Some(msg.out_msg_envelope.cell.clone()),
149 }
150 }
151
152 pub fn load_out_msg_envelope(&self) -> Result<Option<MsgEnvelope>, Error> {
154 match self {
155 Self::External(_) => Ok(None),
156 Self::Immediate(_) => Ok(None),
157 Self::Final(_) => Ok(None),
158 Self::Transit(ref x) => x.load_out_msg_envelope().map(Some),
159 }
160 }
161
162 pub fn compute_fees(&self) -> Result<ImportFees, Error> {
164 Ok(match self {
165 Self::External(_) => ImportFees::default(),
166 Self::Immediate(msg) => {
167 let info = ok!(msg.load_in_msg_info());
168 ImportFees {
169 fees_collected: info.fwd_fee,
170 value_imported: CurrencyCollection::ZERO,
171 }
172 }
173 Self::Final(msg) => {
174 let env = ok!(msg.load_in_msg_envelope());
175 if msg.fwd_fee != env.fwd_fee_remaining {
176 return Err(Error::InvalidData);
177 }
178
179 let info = ok!(env.load_message_info());
180
181 let mut value_imported = info.value;
182 ok!(value_imported.try_add_assign_tokens(info.ihr_fee));
183 ok!(value_imported.try_add_assign_tokens(env.fwd_fee_remaining));
184
185 ImportFees {
186 fees_collected: env.fwd_fee_remaining,
187 value_imported,
188 }
189 }
190 Self::Transit(msg) => {
191 let env = ok!(msg.load_in_msg_envelope());
192 if env.fwd_fee_remaining < msg.transit_fee {
193 return Err(Error::InvalidData);
194 }
195
196 let info = ok!(env.load_message_info());
197
198 let mut value_imported = info.value;
199 ok!(value_imported.try_add_assign_tokens(info.ihr_fee));
200 ok!(value_imported.try_add_assign_tokens(env.fwd_fee_remaining));
201
202 ImportFees {
203 fees_collected: msg.transit_fee,
204 value_imported,
205 }
206 }
207 })
208 }
209}
210
211impl Store for InMsg {
212 fn store_into(&self, builder: &mut CellBuilder, cx: &mut dyn CellContext) -> Result<(), Error> {
213 match self {
214 Self::External(msg) => {
215 ok!(builder.store_small_uint(Self::MSG_IMPORT_EXT, 3));
216 msg.store_into(builder, cx)
217 }
218 Self::Immediate(msg) => {
219 ok!(builder.store_small_uint(Self::MSG_IMPORT_IMM, 3));
220 msg.store_into(builder, cx)
221 }
222 Self::Final(msg) => {
223 ok!(builder.store_small_uint(Self::MSG_IMPORT_FIN, 3));
224 msg.store_into(builder, cx)
225 }
226 Self::Transit(msg) => {
227 ok!(builder.store_small_uint(Self::MSG_IMPORT_TR, 3));
228 msg.store_into(builder, cx)
229 }
230 }
231 }
232}
233
234impl<'a> Load<'a> for InMsg {
235 fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
236 match ok!(slice.load_small_uint(3)) {
237 Self::MSG_IMPORT_EXT => InMsgExternal::load_from(slice).map(Self::External),
238 Self::MSG_IMPORT_IMM => InMsgFinal::load_from(slice).map(Self::Immediate),
239 Self::MSG_IMPORT_FIN => InMsgFinal::load_from(slice).map(Self::Final),
240 Self::MSG_IMPORT_TR => InMsgTransit::load_from(slice).map(Self::Transit),
241 _ => Err(Error::InvalidTag),
242 }
243 }
244}
245
246#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
248#[cfg_attr(feature = "serde", derive(serde::Serialize))]
249#[cfg_attr(feature = "serde", serde(tag = "ty"))]
250pub struct InMsgExternal {
251 #[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
253 pub in_msg: Lazy<OwnedMessage>,
254 #[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
256 pub transaction: Lazy<Transaction>,
257}
258
259impl InMsgExternal {
260 pub fn load_in_msg_info(&self) -> Result<ExtInMsgInfo, Error> {
262 if let MsgInfo::ExtIn(info) = ok!(<_>::load_from(&mut ok!(self.in_msg.cell.as_slice()))) {
263 Ok(info)
264 } else {
265 Err(Error::InvalidData)
266 }
267 }
268
269 pub fn load_in_msg(&self) -> Result<Message<'_>, Error> {
271 self.in_msg.cast_ref::<Message<'_>>().load()
272 }
273
274 pub fn load_in_msg_owned(&self) -> Result<OwnedMessage, Error> {
276 self.in_msg.load()
277 }
278
279 pub fn load_transaction(&self) -> Result<Transaction, Error> {
281 self.transaction.load()
282 }
283}
284
285#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
287#[cfg_attr(feature = "serde", derive(serde::Serialize))]
288pub struct InMsgFinal {
289 pub in_msg_envelope: Lazy<MsgEnvelope>,
291 #[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
293 pub transaction: Lazy<Transaction>,
294 pub fwd_fee: Tokens,
296}
297
298impl InMsgFinal {
299 pub fn load_in_msg_envelope(&self) -> Result<MsgEnvelope, Error> {
301 self.in_msg_envelope.load()
302 }
303
304 pub fn load_in_msg(&self) -> Result<Message<'_>, Error> {
306 let mut envelope = ok!(self.in_msg_envelope.cell.as_slice());
307 Message::load_from(&mut ok!(envelope.load_reference_as_slice()))
308 }
309
310 pub fn load_in_msg_info(&self) -> Result<IntMsgInfo, Error> {
312 let mut envelope = ok!(self.in_msg_envelope.cell.as_slice());
313 let mut message = ok!(envelope.load_reference_as_slice());
314 if let MsgInfo::Int(info) = ok!(<_>::load_from(&mut message)) {
315 Ok(info)
316 } else {
317 Err(Error::InvalidData)
318 }
319 }
320
321 pub fn load_in_msg_owned(&self) -> Result<OwnedMessage, Error> {
323 let mut envelope = ok!(self.in_msg_envelope.cell.as_slice());
324 OwnedMessage::load_from(&mut ok!(envelope.load_reference_as_slice()))
325 }
326
327 pub fn load_in_msg_cell(&self) -> Result<Cell, Error> {
329 ok!(self.in_msg_envelope.cell.as_slice()).load_reference_cloned()
330 }
331
332 pub fn in_msg_envelope_hash(&self) -> &HashBytes {
334 self.in_msg_envelope.cell.repr_hash()
335 }
336
337 pub fn load_transaction(&self) -> Result<Transaction, Error> {
339 self.transaction.load()
340 }
341}
342
343#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
345#[cfg_attr(feature = "serde", derive(serde::Serialize))]
346pub struct InMsgTransit {
347 pub in_msg_envelope: Lazy<MsgEnvelope>,
349 pub out_msg_envelope: Lazy<MsgEnvelope>,
351 pub transit_fee: Tokens,
353}
354
355impl InMsgTransit {
356 pub fn load_in_msg(&self) -> Result<Message<'_>, Error> {
358 let mut envelope = ok!(self.in_msg_envelope.cell.as_slice());
359 Message::load_from(&mut ok!(envelope.load_reference_as_slice()))
360 }
361
362 pub fn load_in_msg_owned(&self) -> Result<OwnedMessage, Error> {
364 let mut envelope = ok!(self.in_msg_envelope.cell.as_slice());
365 OwnedMessage::load_from(&mut ok!(envelope.load_reference_as_slice()))
366 }
367
368 pub fn load_out_msg(&self) -> Result<Message<'_>, Error> {
370 let mut envelope = ok!(self.out_msg_envelope.cell.as_slice());
371 Message::load_from(&mut ok!(envelope.load_reference_as_slice()))
372 }
373
374 pub fn load_out_msg_owned(&self) -> Result<OwnedMessage, Error> {
376 let mut envelope = ok!(self.out_msg_envelope.cell.as_slice());
377 OwnedMessage::load_from(&mut ok!(envelope.load_reference_as_slice()))
378 }
379
380 pub fn load_in_msg_cell(&self) -> Result<Cell, Error> {
382 ok!(self.in_msg_envelope.cell.as_slice()).load_reference_cloned()
383 }
384
385 pub fn load_out_msg_cell(&self) -> Result<Cell, Error> {
387 ok!(self.out_msg_envelope.cell.as_slice()).load_reference_cloned()
388 }
389
390 pub fn load_in_msg_envelope(&self) -> Result<MsgEnvelope, Error> {
392 self.in_msg_envelope.load()
393 }
394
395 pub fn load_out_msg_envelope(&self) -> Result<MsgEnvelope, Error> {
397 self.out_msg_envelope.load()
398 }
399
400 pub fn in_msg_envelope_hash(&self) -> &HashBytes {
402 self.in_msg_envelope.cell.repr_hash()
403 }
404
405 pub fn out_msg_envelope_hash(&self) -> &HashBytes {
407 self.out_msg_envelope.cell.repr_hash()
408 }
409}