tonlib_core/message/jetton/
transfer_notification.rs1use num_bigint::BigUint;
2
3use super::JETTON_TRANSFER_NOTIFICATION;
4use crate::cell::{ArcCell, Cell, CellBuilder, EitherCellLayout, EMPTY_ARC_CELL};
5use crate::message::{HasOpcode, TonMessage, TonMessageError};
6use crate::TonAddress;
7
8#[derive(Clone, Debug, PartialEq)]
16pub struct JettonTransferNotificationMessage {
17 pub query_id: u64,
19 pub amount: BigUint,
21 pub sender: TonAddress,
23 pub forward_payload: ArcCell,
25
26 pub forward_payload_layout: EitherCellLayout,
27}
28
29impl JettonTransferNotificationMessage {
30 pub fn new(sender: &TonAddress, amount: &BigUint) -> Self {
31 JettonTransferNotificationMessage {
32 query_id: 0,
33 amount: amount.clone(),
34 sender: sender.clone(),
35 forward_payload: EMPTY_ARC_CELL.clone(),
36 forward_payload_layout: EitherCellLayout::Native,
37 }
38 }
39
40 pub fn with_forward_payload(&mut self, forward_payload: ArcCell) -> &mut Self {
41 self.forward_payload = forward_payload;
42 self
43 }
44
45 pub fn set_either_cell_layout(&mut self, layout: EitherCellLayout) -> &mut Self {
46 self.forward_payload_layout = layout;
47 self
48 }
49}
50
51impl TonMessage for JettonTransferNotificationMessage {
52 fn build(&self) -> Result<Cell, TonMessageError> {
53 let mut builder = CellBuilder::new();
54 builder.store_u32(32, Self::opcode())?;
55 builder.store_u64(64, self.query_id)?;
56 builder.store_coins(&self.amount)?;
57 builder.store_address(&self.sender)?;
58 builder
59 .store_either_cell_or_cell_ref(&self.forward_payload, self.forward_payload_layout)?;
60
61 Ok(builder.build()?)
62 }
63
64 fn parse(cell: &Cell) -> Result<Self, TonMessageError> {
65 let mut parser = cell.parser();
66
67 let opcode: u32 = parser.load_u32(32)?;
68 let query_id = parser.load_u64(64)?;
69
70 let amount = parser.load_coins()?;
71 let sender = parser.load_address()?;
72 let forward_payload = parser.load_either_cell_or_cell_ref()?;
73 parser.ensure_empty()?;
74
75 let result = JettonTransferNotificationMessage {
76 query_id,
77 amount,
78 sender,
79 forward_payload,
80 forward_payload_layout: EitherCellLayout::Native,
81 };
82 result.verify_opcode(opcode)?;
83
84 Ok(result)
85 }
86}
87
88impl HasOpcode for JettonTransferNotificationMessage {
89 fn set_query_id(&mut self, query_id: u64) {
90 self.query_id = query_id;
91 }
92
93 fn query_id(&self) -> u64 {
94 self.query_id
95 }
96
97 fn opcode() -> u32 {
98 JETTON_TRANSFER_NOTIFICATION
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use std::str::FromStr;
105 use std::sync::Arc;
106
107 use num_bigint::BigUint;
108
109 use crate::cell::{BagOfCells, Cell, EitherCellLayout};
110 use crate::message::{JettonTransferNotificationMessage, TonMessage};
111 use crate::TonAddress;
112
113 const JETTON_TRANSFER_NOTIFICATION_MSG: &str = "b5ee9c720101020100a60001647362d09c000000d2c7ceef23401312d008003be20895401cd8539741eb7815d5e63b3429014018d7e5f7800de16a984f27730100dd25938561800f2465b65c76b1b562f32423676970b431319419d5f45ffd2eeb2155ce6ab7eacc78ee0250ef0300077c4112a8039b0a72e83d6f02babcc766852028031afcbef001bc2d5309e4ee700257a672371a90e149b7d25864dbfd44827cc1e8a30df1b1e0c4338502ade2ad96";
114 const TRANSFER_NOTIFICATION_PAYLOAD: &str = "25938561800f2465b65c76b1b562f32423676970b431319419d5f45ffd2eeb2155ce6ab7eacc78ee0250ef0300077c4112a8039b0a72e83d6f02babcc766852028031afcbef001bc2d5309e4ee700257a672371a90e149b7d25864dbfd44827cc1e8a30df1b1e0c4338502ade2ad94";
115
116 #[test]
117 fn test_jetton_transfer_notification_parser() -> anyhow::Result<()> {
118 let boc = BagOfCells::parse_hex(JETTON_TRANSFER_NOTIFICATION_MSG)?;
119 let cell = boc.single_root()?;
120
121 let expected_jetton_transfer_notification_msg = JettonTransferNotificationMessage {
122 query_id: 905295359779,
123 amount: BigUint::from(20000000u64),
124 sender: TonAddress::from_str("EQAd8QRKoA5sKcug9bwK6vMdmhSAoAxr8vvABvC1TCeTude5")?,
125 forward_payload: Arc::new(Cell::new(
126 hex::decode(TRANSFER_NOTIFICATION_PAYLOAD).unwrap(),
127 886,
128 vec![],
129 false,
130 )?),
131 forward_payload_layout: EitherCellLayout::Native,
132 };
133 let result_jetton_transfer_msg = JettonTransferNotificationMessage::parse(&cell)?;
134
135 assert_eq!(
136 expected_jetton_transfer_notification_msg,
137 result_jetton_transfer_msg
138 );
139 Ok(())
140 }
141
142 #[test]
143 fn test_jetton_transfer_notification_builder() -> anyhow::Result<()> {
144 let jetton_transfer_notification_msg = JettonTransferNotificationMessage {
145 query_id: 905295359779,
146 amount: BigUint::from(20000000u64),
147 sender: TonAddress::from_str("EQAd8QRKoA5sKcug9bwK6vMdmhSAoAxr8vvABvC1TCeTude5")
148 .unwrap(),
149 forward_payload: Arc::new(Cell::new(
150 hex::decode(TRANSFER_NOTIFICATION_PAYLOAD).unwrap(),
151 886,
152 vec![],
153 false,
154 )?),
155 forward_payload_layout: EitherCellLayout::Native,
156 };
157
158 let result_cell = jetton_transfer_notification_msg.build()?;
159
160 let expected_boc_serialized = hex::decode(JETTON_TRANSFER_NOTIFICATION_MSG)?;
161 let result_boc_serialized = BagOfCells::from_root(result_cell).serialize(false)?;
162
163 assert_eq!(expected_boc_serialized, result_boc_serialized);
164 Ok(())
165 }
166}