tonlib_core/message/sbt/
ownership_proof.rs

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