Skip to main content

hiero_sdk/token/
token_delete_transaction.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use 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    BoxGrpcFuture,
22    Error,
23    TokenId,
24    Transaction,
25    ValidateChecksums,
26};
27
28/// Marks a token as deleted, though it will remain in the ledger.
29///
30/// The operation must be signed by the specified Admin Key of the Token.
31///
32/// Once deleted update, mint, burn, wipe, freeze, unfreeze, grant kyc, revoke
33/// kyc and token transfer transactions will resolve to `TOKEN_WAS_DELETED`.
34///
35/// - If admin key is not set, Transaction will result in `TOKEN_IS_IMMUTABlE`.
36/// - If invalid token is specified, transaction will result in `INVALID_TOKEN_ID`
37pub type TokenDeleteTransaction = Transaction<TokenDeleteTransactionData>;
38
39#[derive(Debug, Clone, Default)]
40pub struct TokenDeleteTransactionData {
41    /// The token to be deleted.
42    token_id: Option<TokenId>,
43}
44
45impl TokenDeleteTransaction {
46    /// Returns the token to be deleted.
47    #[must_use]
48    pub fn get_token_id(&self) -> Option<TokenId> {
49        self.data().token_id
50    }
51
52    /// Sets the token to be deleted.
53    pub fn token_id(&mut self, token_id: impl Into<TokenId>) -> &mut Self {
54        self.data_mut().token_id = Some(token_id.into());
55        self
56    }
57}
58
59impl TransactionData for TokenDeleteTransactionData {}
60
61impl TransactionExecute for TokenDeleteTransactionData {
62    fn execute(
63        &self,
64        channel: Channel,
65        request: services::Transaction,
66    ) -> BoxGrpcFuture<'_, services::TransactionResponse> {
67        Box::pin(async { TokenServiceClient::new(channel).delete_token(request).await })
68    }
69}
70
71impl ValidateChecksums for TokenDeleteTransactionData {
72    fn validate_checksums(&self, ledger_id: &RefLedgerId) -> Result<(), Error> {
73        self.token_id.validate_checksums(ledger_id)
74    }
75}
76
77impl ToTransactionDataProtobuf for TokenDeleteTransactionData {
78    fn to_transaction_data_protobuf(
79        &self,
80        chunk_info: &ChunkInfo,
81    ) -> services::transaction_body::Data {
82        let _ = chunk_info.assert_single_transaction();
83
84        services::transaction_body::Data::TokenDeletion(self.to_protobuf())
85    }
86}
87
88impl ToSchedulableTransactionDataProtobuf for TokenDeleteTransactionData {
89    fn to_schedulable_transaction_data_protobuf(
90        &self,
91    ) -> services::schedulable_transaction_body::Data {
92        services::schedulable_transaction_body::Data::TokenDeletion(self.to_protobuf())
93    }
94}
95
96impl From<TokenDeleteTransactionData> for AnyTransactionData {
97    fn from(transaction: TokenDeleteTransactionData) -> Self {
98        Self::TokenDelete(transaction)
99    }
100}
101
102impl FromProtobuf<services::TokenDeleteTransactionBody> for TokenDeleteTransactionData {
103    fn from_protobuf(pb: services::TokenDeleteTransactionBody) -> crate::Result<Self> {
104        Ok(Self { token_id: Option::from_protobuf(pb.token)? })
105    }
106}
107
108impl ToProtobuf for TokenDeleteTransactionData {
109    type Protobuf = services::TokenDeleteTransactionBody;
110
111    fn to_protobuf(&self) -> Self::Protobuf {
112        services::TokenDeleteTransactionBody { token: self.token_id.to_protobuf() }
113    }
114}
115
116#[cfg(test)]
117mod tests {
118
119    use expect_test::expect_file;
120    use hiero_sdk_proto::services;
121
122    use crate::protobuf::{
123        FromProtobuf,
124        ToProtobuf,
125    };
126    use crate::token::TokenDeleteTransactionData;
127    use crate::transaction::test_helpers::{
128        check_body,
129        transaction_body,
130        TEST_TOKEN_ID,
131    };
132    use crate::{
133        AnyTransaction,
134        TokenDeleteTransaction,
135    };
136
137    fn make_transaction() -> TokenDeleteTransaction {
138        let mut tx = TokenDeleteTransaction::new_for_tests();
139
140        tx.token_id(TEST_TOKEN_ID).freeze().unwrap();
141
142        tx
143    }
144
145    #[test]
146    fn seriralize() {
147        let tx = make_transaction();
148
149        let tx = transaction_body(tx);
150
151        let tx = check_body(tx);
152
153        expect_file!["./snapshots/token_delete_transaction/serialize.txt"].assert_debug_eq(&tx);
154    }
155
156    #[test]
157    fn to_from_bytes() {
158        let tx = make_transaction();
159
160        let tx2 = AnyTransaction::from_bytes(&tx.to_bytes().unwrap()).unwrap();
161
162        let tx = transaction_body(tx);
163        let tx2 = transaction_body(tx2);
164
165        assert_eq!(tx, tx2);
166    }
167
168    #[test]
169    fn from_proto_body() {
170        let tx = services::TokenDeleteTransactionBody { token: Some(TEST_TOKEN_ID.to_protobuf()) };
171
172        let data = TokenDeleteTransactionData::from_protobuf(tx).unwrap();
173
174        assert_eq!(data.token_id, Some(TEST_TOKEN_ID));
175    }
176
177    #[test]
178    fn get_set_token_id() {
179        let mut tx = TokenDeleteTransaction::new();
180
181        let tx2 = tx.token_id(TEST_TOKEN_ID);
182
183        assert_eq!(tx2.get_token_id(), Some(TEST_TOKEN_ID));
184    }
185
186    #[test]
187    #[should_panic]
188    fn get_set_token_id_frozen_panic() {
189        let mut tx = make_transaction();
190
191        tx.token_id(TEST_TOKEN_ID);
192    }
193}