tonlib_core/message/jetton/
burn.rs

1use num_bigint::BigUint;
2
3use super::JETTON_BURN;
4use crate::cell::{ArcCell, Cell, CellBuilder};
5use crate::message::{HasOpcode, TonMessage, TonMessageError};
6use crate::TonAddress;
7
8/// Creates a body for jetton burn according to TL-B schema:
9///
10/// ```raw
11/// burn#595f07bc query_id:uint64 amount:(VarUInteger 16)
12///               response_destination:MsgAddress custom_payload:(Maybe ^Cell)
13///               = InternalMsgBody;
14/// ```
15#[derive(Clone, Debug, PartialEq)]
16pub struct JettonBurnMessage {
17    /// arbitrary request number.
18    pub query_id: u64,
19    /// amount of burned jettons
20    pub amount: BigUint,
21    /// address where to send a response with confirmation of a successful burn and the rest of the incoming message coins.
22    pub response_destination: TonAddress,
23    /// optional custom data (which is used by either sender or receiver jetton wallet for inner logic).
24    pub custom_payload: Option<ArcCell>,
25}
26
27impl JettonBurnMessage {
28    pub fn new(amount: &BigUint) -> Self {
29        JettonBurnMessage {
30            query_id: 0,
31            amount: amount.clone(),
32            response_destination: TonAddress::NULL,
33            custom_payload: None,
34        }
35    }
36
37    pub fn with_response_destination(&mut self, response_destination: &TonAddress) -> &mut Self {
38        self.response_destination = response_destination.clone();
39        self
40    }
41
42    pub fn with_custom_payload(&mut self, custom_payload: ArcCell) -> &mut Self {
43        self.custom_payload = Some(custom_payload);
44        self
45    }
46}
47
48impl TonMessage for JettonBurnMessage {
49    fn build(&self) -> Result<Cell, TonMessageError> {
50        let mut builder = CellBuilder::new();
51        builder.store_u32(32, Self::opcode())?;
52        builder.store_u64(64, self.query_id)?;
53        builder.store_coins(&self.amount)?;
54        builder.store_address(&self.response_destination)?;
55        builder.store_ref_cell_optional(self.custom_payload.as_ref())?;
56
57        Ok(builder.build()?)
58    }
59
60    fn parse(cell: &Cell) -> Result<Self, TonMessageError> {
61        let mut parser = cell.parser();
62
63        let opcode: u32 = parser.load_u32(32)?;
64        let query_id = parser.load_u64(64)?;
65
66        let amount = parser.load_coins()?;
67        let response_destination = parser.load_address()?;
68        let custom_payload = parser.load_maybe_cell_ref()?;
69        parser.ensure_empty()?;
70
71        let result = JettonBurnMessage {
72            query_id,
73            amount,
74            response_destination,
75            custom_payload,
76        };
77        result.verify_opcode(opcode)?;
78        Ok(result)
79    }
80}
81
82impl HasOpcode for JettonBurnMessage {
83    fn set_query_id(&mut self, query_id: u64) {
84        self.query_id = query_id;
85    }
86
87    fn query_id(&self) -> u64 {
88        self.query_id
89    }
90
91    fn opcode() -> u32 {
92        JETTON_BURN
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use std::str::FromStr;
99
100    use num_bigint::BigUint;
101
102    use crate::cell::BagOfCells;
103    use crate::message::{HasOpcode, JettonBurnMessage, TonMessage, TonMessageError};
104    use crate::TonAddress;
105
106    const JETTON_BURN_WITH_CUSTOM_PAYLOAD_INDICATOR_MSG: &str =  "b5ee9c72010101010033000062595f07bc0000009b5946deef3080f21800b026e71919f2c839f639f078d9ee6bc9d7592ebde557edf03661141c7c5f2ea2";
107    const NOT_BURN: &str = "b5ee9c72010101010035000066595f07bc0000000000000001545d964b800800cd324c114b03f846373734c74b3c3287e1a8c2c732b5ea563a17c6276ef4af30";
108
109    #[test]
110    fn test_jetton_burn_parser() -> Result<(), TonMessageError> {
111        let boc_with_indicator =
112            BagOfCells::parse_hex(JETTON_BURN_WITH_CUSTOM_PAYLOAD_INDICATOR_MSG)?;
113        let cell_with_indicator = boc_with_indicator.single_root()?;
114        let result_jetton_transfer_msg_with_indicator: JettonBurnMessage =
115            JettonBurnMessage::parse(&cell_with_indicator)?;
116
117        let expected_jetton_transfer_msg = JettonBurnMessage {
118            query_id: 667217747695,
119            amount: BigUint::from(528161u64),
120            response_destination: TonAddress::from_str(
121                "EQBYE3OMjPlkHPsc-Dxs9zXk66yXXvKr9vgbMIoOPi-XUa-f",
122            )
123            .unwrap(),
124            custom_payload: None,
125        };
126
127        assert_eq!(
128            expected_jetton_transfer_msg,
129            result_jetton_transfer_msg_with_indicator
130        );
131
132        let boc = BagOfCells::parse_hex(NOT_BURN)?;
133        let cell = boc.single_root()?;
134
135        let result_jetton_transfer_msg = JettonBurnMessage::parse(&cell)?;
136
137        let expected_jetton_transfer_msg = JettonBurnMessage {
138            query_id: 1,
139            amount: BigUint::from(300000000000u64),
140            response_destination: TonAddress::from_str(
141                "EQBmmSYIpYH8IxubmmOlnhlD8NRhY5la9SsdC-MTt3pXmOSI",
142            )
143            .unwrap(),
144            custom_payload: None,
145        };
146
147        assert_eq!(expected_jetton_transfer_msg, result_jetton_transfer_msg);
148        Ok(())
149    }
150
151    #[test]
152    fn test_jetton_burn_builder() {
153        let result_cell = JettonBurnMessage::new(&BigUint::from(528161u64))
154            .with_query_id(667217747695)
155            .with_response_destination(
156                &TonAddress::from_str("EQBYE3OMjPlkHPsc-Dxs9zXk66yXXvKr9vgbMIoOPi-XUa-f").unwrap(),
157            )
158            .build()
159            .unwrap();
160
161        let result_boc_serialized = BagOfCells::from_root(result_cell).serialize(false).unwrap();
162        let expected_boc_serialized =
163            hex::decode(JETTON_BURN_WITH_CUSTOM_PAYLOAD_INDICATOR_MSG).unwrap();
164
165        assert_eq!(expected_boc_serialized, result_boc_serialized);
166
167        let result_cell = JettonBurnMessage {
168            query_id: 1,
169            amount: BigUint::from(300000000000u64),
170            response_destination: TonAddress::from_str(
171                "EQBmmSYIpYH8IxubmmOlnhlD8NRhY5la9SsdC-MTt3pXmOSI",
172            )
173            .unwrap(),
174            custom_payload: None,
175        }
176        .build()
177        .unwrap();
178
179        let result_boc_serialized = BagOfCells::from_root(result_cell).serialize(false).unwrap();
180        let expected_boc_serialized = hex::decode(NOT_BURN).unwrap();
181
182        assert_eq!(expected_boc_serialized, result_boc_serialized);
183    }
184}