1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * ‌
 * Hedera Rust SDK
 * ​
 * Copyright (C) 2022 - 2023 Hedera Hashgraph, LLC
 * ​
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ‍
 */

use crate::{
    AccountId,
    Client,
    TransactionHash,
    TransactionId,
    TransactionReceipt,
    TransactionReceiptQuery,
    TransactionRecord,
    TransactionRecordQuery,
};

/// Response from [`Transaction::execute`][crate::Transaction::execute].
///
/// When the client sends a node a transaction of any kind, the node replies with this, which
/// simply says that the transaction passed the pre-check (so the node will submit it to
/// the network).
///
/// To learn the consensus result, the client should later obtain a
/// receipt (free), or can buy a more detailed record (not free).
///
#[derive(Debug)]
pub struct TransactionResponse {
    /// The account ID of the node that the transaction was submitted to.
    pub node_account_id: AccountId,

    /// The client-generated transaction ID of the transaction that was submitted.
    ///
    /// This can be used to lookup the transaction in an explorer.
    pub transaction_id: TransactionId,

    /// The client-generated SHA-384 hash of the transaction that was submitted.
    ///
    /// This can be used to lookup the transaction in an explorer.
    pub transaction_hash: TransactionHash,

    /// Whether the receipt/record status should be validated.
    pub validate_status: bool,
}

impl TransactionResponse {
    /// Whether the receipt/record status should be validated.
    pub fn validate_status(&mut self, validate: bool) -> &mut Self {
        self.validate_status = validate;
        self
    }

    /// Create a query that will get the receipt for this transaction.
    #[must_use]
    pub fn get_receipt_query(&self) -> TransactionReceiptQuery {
        let mut query = TransactionReceiptQuery::new();

        query.transaction_id(self.transaction_id).validate_status(self.validate_status);

        query
    }

    /// Create a query that will get the record for this transaction.
    #[must_use]
    pub fn get_record_query(&self) -> TransactionRecordQuery {
        let mut query = TransactionRecordQuery::new();

        query.transaction_id(self.transaction_id).validate_status(self.validate_status);

        query
    }

    /// Get the receipt for this transaction.
    /// Will wait for consensus.
    ///
    /// # Errors
    /// - if [`validate_status`](Self.validate_status) is `true`:
    ///   [`Error::ReceiptStatus`](crate::Error::ReceiptStatus) for a failing receipt.
    ///
    /// fixme: is that it? Surely there are more situations.
    pub async fn get_receipt(&self, client: &Client) -> crate::Result<TransactionReceipt> {
        self.get_receipt_query().execute(client).await
    }

    /// Get the receipt for this transaction.
    /// Will wait for consensus.
    ///
    /// # Errors
    /// - if [`validate_status`](Self.validate_status) is `true`:
    ///   [`Error::ReceiptStatus`](crate::Error::ReceiptStatus) for a failing receipt.
    pub async fn get_receipt_with_timeout(
        &self,
        client: &Client,
        timeout: std::time::Duration,
    ) -> crate::Result<TransactionReceipt> {
        self.get_receipt_query().execute_with_timeout(client, timeout).await
    }

    /// Get the record for this transaction.
    /// Will wait for consensus.
    ///
    /// # Errors
    /// - if [`validate_status`](Self.validate_status) is `true`:
    ///   [`Error::ReceiptStatus`](crate::Error::ReceiptStatus) for a failing receipt in the record.
    pub async fn get_record(&self, client: &Client) -> crate::Result<TransactionRecord> {
        self.get_record_query().execute(client).await
    }

    /// Get the record for this transaction.
    /// Will wait for consensus.
    ///
    /// # Errors
    /// - if [`validate_status`](Self.validate_status) is `true`:
    ///   [`Error::ReceiptStatus`](crate::Error::ReceiptStatus) for a failing receipt in the record.
    pub async fn get_record_with_timeout(
        &self,
        client: &Client,
        timeout: std::time::Duration,
    ) -> crate::Result<TransactionRecord> {
        self.get_record_query().execute_with_timeout(client, timeout).await
    }
}