tonlib_core/message/sbt/
owner_info.rs

1use num_bigint::BigUint;
2
3use super::SBT_OWNER_INFO;
4use crate::cell::{ArcCell, Cell, CellBuilder};
5use crate::message::{HasOpcode, TonMessage, TonMessageError};
6use crate::TonAddress;
7
8/// Creates a body for sbt ownership proof according to TL-B schema:
9///
10/// ```raw
11/// owner_info#0dd607e3
12///   query_id:uint64
13///   item_id:uint256
14///   initiator:MsgAddress
15///   owner:MsgAddress
16///   data:^Cell
17///   revoked_at:uint64
18///   content:(Maybe ^Cell)
19/// = InternalMsgBody;
20/// ```
21#[derive(Clone, Debug, PartialEq)]
22pub struct OwnerInfoMessage {
23    /// arbitrary request number.
24    pub query_id: u64,
25    /// id of NFT.
26    pub item_id: BigUint,
27    /// address of request initiator.
28    pub initiator: TonAddress,
29    /// current owner's address.
30    pub owner: TonAddress,
31    /// data cell passed in prove_ownership.
32    pub data: ArcCell,
33    /// unix time when SBT was revoked, 0 if it was not.
34    pub revoked_at: u64,
35    /// NFT's content, it is passed if with_content was true in prove_ownership.
36    pub content: Option<ArcCell>,
37}
38
39impl OwnerInfoMessage {
40    pub fn new(
41        item_id: BigUint,
42        owner: &TonAddress,
43        initiator: &TonAddress,
44        data: ArcCell,
45        revoked_at: u64,
46        content: Option<ArcCell>,
47    ) -> Self {
48        OwnerInfoMessage {
49            query_id: 0,
50            item_id,
51            initiator: initiator.clone(),
52            owner: owner.clone(),
53            data,
54            revoked_at,
55            content,
56        }
57    }
58}
59
60impl TonMessage for OwnerInfoMessage {
61    fn build(&self) -> Result<Cell, TonMessageError> {
62        let mut builder = CellBuilder::new();
63        builder.store_u32(32, Self::opcode())?;
64        builder.store_u64(64, self.query_id)?;
65        builder.store_uint(256, &self.item_id)?;
66        builder.store_address(&self.initiator)?;
67        builder.store_address(&self.owner)?;
68        builder.store_reference(&self.data)?;
69        builder.store_u64(64, self.revoked_at)?;
70        builder.store_ref_cell_optional(self.content.as_ref())?;
71        Ok(builder.build()?)
72    }
73
74    fn parse(cell: &Cell) -> Result<Self, TonMessageError> {
75        let mut parser = cell.parser();
76
77        let opcode: u32 = parser.load_u32(32)?;
78        let query_id = parser.load_u64(64)?;
79        let item_id = parser.load_uint(256)?;
80        let initiator = parser.load_address()?;
81        let owner = parser.load_address()?;
82        let data = parser.next_reference()?;
83        let revoked_at = parser.load_u64(64)?;
84        let content = parser.load_maybe_cell_ref()?;
85        parser.ensure_empty()?;
86
87        let result = OwnerInfoMessage {
88            query_id,
89            item_id,
90            initiator,
91            owner,
92            data,
93            revoked_at,
94            content,
95        };
96        result.verify_opcode(opcode)?;
97        Ok(result)
98    }
99}
100
101impl HasOpcode for OwnerInfoMessage {
102    fn set_query_id(&mut self, query_id: u64) {
103        self.query_id = query_id;
104    }
105
106    fn query_id(&self) -> u64 {
107        self.query_id
108    }
109
110    fn opcode() -> u32 {
111        SBT_OWNER_INFO
112    }
113}
114
115#[cfg(test)]
116mod tests {
117    use std::sync::Arc;
118
119    use num_bigint::BigUint;
120
121    use super::OwnerInfoMessage;
122    use crate::cell::{ArcCell, CellBuilder};
123    use crate::message::{HasOpcode, TonMessage};
124    use crate::TonAddress;
125    #[test]
126    fn sbt_owner_info_msg_test() {
127        let query_id = 1234567890;
128        let item_id = BigUint::from(123u64);
129
130        let initiator =
131            &TonAddress::from_base64_url("EQAW42HutyDem98Be1f27PoXobghh81umTQ-cGgaKVmRLS7-")
132                .unwrap();
133        let owner =
134            &TonAddress::from_base64_url("EQAd8QRKoA5sKcug9bwK6vMdmhSAoAxr8vvABvC1TCeTude5")
135                .unwrap();
136
137        let data: ArcCell = Arc::new(
138            CellBuilder::new()
139                .store_u32(12, 123)
140                .unwrap()
141                .build()
142                .unwrap(),
143        );
144        let revoked_at = 123456;
145        let content = Some(Arc::new(
146            CellBuilder::new()
147                .store_u32(12, 456)
148                .unwrap()
149                .build()
150                .unwrap(),
151        ));
152
153        let expected = OwnerInfoMessage {
154            query_id,
155            item_id: item_id.clone(),
156            initiator: initiator.clone(),
157            owner: owner.clone(),
158            data: data.clone(),
159            revoked_at,
160            content: content.clone(),
161        };
162
163        let build_result =
164            OwnerInfoMessage::new(item_id, owner, initiator, data, revoked_at, content)
165                .with_query_id(query_id)
166                .build();
167        assert!(build_result.is_ok());
168
169        let cell = build_result.unwrap();
170        let parse_result = OwnerInfoMessage::parse(&cell);
171        assert!(parse_result.is_ok());
172
173        let parsed_msg = parse_result.unwrap();
174        assert_eq!(expected, parsed_msg);
175    }
176}