hiero_sdk/token/
token_grant_kyc_transaction.rs1use hiero_sdk_proto::services;
4use hiero_sdk_proto::services::token_service_client::TokenServiceClient;
5use tonic::transport::Channel;
6
7use crate::ledger_id::RefLedgerId;
8use crate::protobuf::{
9 FromProtobuf,
10 ToProtobuf,
11};
12use crate::transaction::{
13 AnyTransactionData,
14 ChunkInfo,
15 ToSchedulableTransactionDataProtobuf,
16 ToTransactionDataProtobuf,
17 TransactionData,
18 TransactionExecute,
19};
20use crate::{
21 AccountId,
22 BoxGrpcFuture,
23 Error,
24 TokenId,
25 Transaction,
26 ValidateChecksums,
27};
28
29pub type TokenGrantKycTransaction = Transaction<TokenGrantKycTransactionData>;
41
42#[derive(Debug, Clone, Default)]
43pub struct TokenGrantKycTransactionData {
44 account_id: Option<AccountId>,
46
47 token_id: Option<TokenId>,
49}
50
51impl TokenGrantKycTransaction {
52 #[must_use]
54 pub fn get_account_id(&self) -> Option<AccountId> {
55 self.data().account_id
56 }
57
58 pub fn account_id(&mut self, account_id: AccountId) -> &mut Self {
60 self.data_mut().account_id = Some(account_id);
61 self
62 }
63
64 #[must_use]
66 pub fn get_token_id(&self) -> Option<TokenId> {
67 self.data().token_id
68 }
69
70 pub fn token_id(&mut self, token_id: impl Into<TokenId>) -> &mut Self {
72 self.data_mut().token_id = Some(token_id.into());
73 self
74 }
75}
76
77impl TransactionData for TokenGrantKycTransactionData {}
78
79impl TransactionExecute for TokenGrantKycTransactionData {
80 fn execute(
81 &self,
82 channel: Channel,
83 request: services::Transaction,
84 ) -> BoxGrpcFuture<'_, services::TransactionResponse> {
85 Box::pin(async {
86 TokenServiceClient::new(channel).grant_kyc_to_token_account(request).await
87 })
88 }
89}
90
91impl ValidateChecksums for TokenGrantKycTransactionData {
92 fn validate_checksums(&self, ledger_id: &RefLedgerId) -> Result<(), Error> {
93 self.account_id.validate_checksums(ledger_id)?;
94 self.token_id.validate_checksums(ledger_id)
95 }
96}
97
98impl ToTransactionDataProtobuf for TokenGrantKycTransactionData {
99 fn to_transaction_data_protobuf(
100 &self,
101 chunk_info: &ChunkInfo,
102 ) -> services::transaction_body::Data {
103 let _ = chunk_info.assert_single_transaction();
104
105 services::transaction_body::Data::TokenGrantKyc(self.to_protobuf())
106 }
107}
108
109impl ToSchedulableTransactionDataProtobuf for TokenGrantKycTransactionData {
110 fn to_schedulable_transaction_data_protobuf(
111 &self,
112 ) -> services::schedulable_transaction_body::Data {
113 services::schedulable_transaction_body::Data::TokenGrantKyc(self.to_protobuf())
114 }
115}
116
117impl From<TokenGrantKycTransactionData> for AnyTransactionData {
118 fn from(transaction: TokenGrantKycTransactionData) -> Self {
119 Self::TokenGrantKyc(transaction)
120 }
121}
122
123impl FromProtobuf<services::TokenGrantKycTransactionBody> for TokenGrantKycTransactionData {
124 fn from_protobuf(pb: services::TokenGrantKycTransactionBody) -> crate::Result<Self> {
125 Ok(Self {
126 account_id: Option::from_protobuf(pb.account)?,
127 token_id: Option::from_protobuf(pb.token)?,
128 })
129 }
130}
131
132impl ToProtobuf for TokenGrantKycTransactionData {
133 type Protobuf = services::TokenGrantKycTransactionBody;
134
135 fn to_protobuf(&self) -> Self::Protobuf {
136 services::TokenGrantKycTransactionBody {
137 token: self.token_id.to_protobuf(),
138 account: self.account_id.to_protobuf(),
139 }
140 }
141}
142
143#[cfg(test)]
144mod tests {
145 use expect_test::expect;
146 use hiero_sdk_proto::services;
147
148 use crate::protobuf::{
149 FromProtobuf,
150 ToProtobuf,
151 };
152 use crate::token::TokenGrantKycTransactionData;
153 use crate::transaction::test_helpers::{
154 check_body,
155 transaction_body,
156 };
157 use crate::{
158 AccountId,
159 AnyTransaction,
160 TokenGrantKycTransaction,
161 TokenId,
162 };
163
164 const TEST_TOKEN_ID: TokenId = TokenId::new(4, 2, 0);
165 const TEST_ACCOUNT_ID: AccountId =
166 AccountId { shard: 6, realm: 9, num: 0, alias: None, evm_address: None, checksum: None };
167
168 fn make_transaction() -> TokenGrantKycTransaction {
169 let mut tx = TokenGrantKycTransaction::new_for_tests();
170
171 tx.account_id(TEST_ACCOUNT_ID).token_id(TEST_TOKEN_ID).freeze().unwrap();
172
173 tx
174 }
175
176 #[test]
177 fn serialize() {
178 let tx = make_transaction();
179
180 let tx = transaction_body(tx);
181
182 let tx = check_body(tx);
183
184 expect![[r#"
185 TokenGrantKyc(
186 TokenGrantKycTransactionBody {
187 token: Some(
188 TokenId {
189 shard_num: 4,
190 realm_num: 2,
191 token_num: 0,
192 },
193 ),
194 account: Some(
195 AccountId {
196 shard_num: 6,
197 realm_num: 9,
198 account: Some(
199 AccountNum(
200 0,
201 ),
202 ),
203 },
204 ),
205 },
206 )
207 "#]]
208 .assert_debug_eq(&tx)
209 }
210
211 #[test]
212 fn to_from_bytes() {
213 let tx = make_transaction();
214
215 let tx2 = AnyTransaction::from_bytes(&tx.to_bytes().unwrap()).unwrap();
216
217 let tx = transaction_body(tx);
218
219 let tx2 = transaction_body(tx2);
220
221 assert_eq!(tx, tx2);
222 }
223
224 #[test]
225 fn from_proto_body() {
226 let tx = services::TokenGrantKycTransactionBody {
227 account: Some(TEST_ACCOUNT_ID.to_protobuf()),
228 token: Some(TEST_TOKEN_ID.to_protobuf()),
229 };
230
231 let data = TokenGrantKycTransactionData::from_protobuf(tx).unwrap();
232
233 assert_eq!(data.account_id, Some(TEST_ACCOUNT_ID));
234 assert_eq!(data.token_id, Some(TEST_TOKEN_ID));
235 }
236
237 #[test]
238 fn get_set_account_id() {
239 let mut tx = TokenGrantKycTransaction::new();
240
241 tx.account_id(TEST_ACCOUNT_ID);
242
243 assert_eq!(tx.get_account_id(), Some(TEST_ACCOUNT_ID));
244 }
245
246 #[test]
247 #[should_panic]
248 fn get_set_account_id_frozen_panic() {
249 let mut tx = make_transaction();
250
251 tx.account_id(TEST_ACCOUNT_ID);
252 }
253
254 #[test]
255 fn get_set_token_id() {
256 let mut tx = TokenGrantKycTransaction::new();
257
258 tx.token_id(TEST_TOKEN_ID);
259
260 assert_eq!(tx.get_token_id(), Some(TEST_TOKEN_ID));
261 }
262
263 #[test]
264 #[should_panic]
265 fn get_set_token_id_frozen_panic() {
266 let mut tx = make_transaction();
267
268 tx.token_id(TEST_TOKEN_ID);
269 }
270}