github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/transaction_receipt_query.go (about)

     1  package hedera
     2  
     3  /*-
     4   *
     5   * Hedera Go SDK
     6   *
     7   * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC
     8   *
     9   * Licensed under the Apache License, Version 2.0 (the "License");
    10   * you may not use this file except in compliance with the License.
    11   * You may obtain a copy of the License at
    12   *
    13   *      http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing, software
    16   * distributed under the License is distributed on an "AS IS" BASIS,
    17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    18   * See the License for the specific language governing permissions and
    19   * limitations under the License.
    20   *
    21   */
    22  
    23  import (
    24  	"time"
    25  
    26  	"github.com/hashgraph/hedera-protobufs-go/services"
    27  )
    28  
    29  // TransactionReceiptQuery
    30  // Get the receipt of a transaction, given its transaction ID. Once a transaction reaches consensus,
    31  // then information about whether it succeeded or failed will be available until the end of the
    32  // receipt period.  Before and after the receipt period, and for a transaction that was never
    33  // submitted, the receipt is unknown.  This query is free (the payment field is left empty). No
    34  // State proof is available for this response
    35  type TransactionReceiptQuery struct {
    36  	Query
    37  	transactionID *TransactionID
    38  	childReceipts *bool
    39  	duplicates    *bool
    40  }
    41  
    42  // NewTransactionReceiptQuery creates TransactionReceiptQuery which
    43  // gets the receipt of a transaction, given its transaction ID. Once a transaction reaches consensus,
    44  // then information about whether it succeeded or failed will be available until the end of the
    45  // receipt period.  Before and after the receipt period, and for a transaction that was never
    46  // submitted, the receipt is unknown.  This query is free (the payment field is left empty). No
    47  // State proof is available for this response
    48  func NewTransactionReceiptQuery() *TransactionReceiptQuery {
    49  	header := services.QueryHeader{}
    50  	return &TransactionReceiptQuery{
    51  		Query: _NewQuery(false, &header),
    52  	}
    53  }
    54  
    55  // When execution is attempted, a single attempt will timeout when this deadline is reached. (The SDK may subsequently retry the execution.)
    56  func (q *TransactionReceiptQuery) SetGrpcDeadline(deadline *time.Duration) *TransactionReceiptQuery {
    57  	q.Query.SetGrpcDeadline(deadline)
    58  	return q
    59  }
    60  
    61  // SetIncludeChildren Sets whether the response should include the receipts of any child transactions spawned by the
    62  // top-level transaction with the given transactionID.
    63  func (q *TransactionReceiptQuery) SetIncludeChildren(includeChildReceipts bool) *TransactionReceiptQuery {
    64  	q.childReceipts = &includeChildReceipts
    65  	return q
    66  }
    67  
    68  // GetIncludeChildren returns whether the response should include the receipts of any child transactions spawned by the
    69  // top-level transaction with the given transactionID.
    70  func (q *TransactionReceiptQuery) GetIncludeChildren() bool {
    71  	if q.childReceipts != nil {
    72  		return *q.childReceipts
    73  	}
    74  
    75  	return false
    76  }
    77  
    78  // SetIncludeDuplicates Sets whether receipts of processing duplicate transactions should be returned along with the
    79  // receipt of processing the first consensus transaction with the given id whose status was
    80  // neither INVALID_NODE_ACCOUNT nor INVALID_PAYER_SIGNATURE; or, if no
    81  // such receipt exists, the receipt of processing the first transaction to reach consensus with
    82  // the given transaction id.
    83  func (q *TransactionReceiptQuery) SetIncludeDuplicates(includeDuplicates bool) *TransactionReceiptQuery {
    84  	q.duplicates = &includeDuplicates
    85  	return q
    86  }
    87  
    88  // GetIncludeDuplicates returns whether receipts of processing duplicate transactions should be returned along with the
    89  // receipt of processing the first consensus transaction with the given id
    90  func (q *TransactionReceiptQuery) GetIncludeDuplicates() bool {
    91  	if q.duplicates != nil {
    92  		return *q.duplicates
    93  	}
    94  
    95  	return false
    96  }
    97  
    98  func (q *TransactionReceiptQuery) GetCost(client *Client) (Hbar, error) {
    99  	return q.Query.getCost(client, q)
   100  }
   101  
   102  // Execute executes the Query with the provided client
   103  func (q *TransactionReceiptQuery) Execute(client *Client) (TransactionReceipt, error) {
   104  	resp, err := q.Query.execute(client, q)
   105  
   106  	if err, ok := err.(ErrHederaPreCheckStatus); ok {
   107  		if resp.GetTransactionGetReceipt() != nil {
   108  			return _TransactionReceiptFromProtobuf(resp.GetTransactionGetReceipt(), q.transactionID), err
   109  		}
   110  		// Manually add the receipt status, because an empty receipt has no status and no status defaults to 0, which means success
   111  		return TransactionReceipt{Status: err.Status}, err
   112  	}
   113  
   114  	return _TransactionReceiptFromProtobuf(resp.GetTransactionGetReceipt(), q.transactionID), nil
   115  }
   116  
   117  // SetTransactionID sets the TransactionID for which the receipt is being requested.
   118  func (q *TransactionReceiptQuery) SetTransactionID(transactionID TransactionID) *TransactionReceiptQuery {
   119  	q.transactionID = &transactionID
   120  	return q
   121  }
   122  
   123  // GetTransactionID returns the TransactionID for which the receipt is being requested.
   124  func (q *TransactionReceiptQuery) GetTransactionID() TransactionID {
   125  	if q.transactionID == nil {
   126  		return TransactionID{}
   127  	}
   128  
   129  	return *q.transactionID
   130  }
   131  
   132  // SetNodeAccountIDs sets the _Node AccountID for this TransactionReceiptQuery.
   133  func (q *TransactionReceiptQuery) SetNodeAccountIDs(accountID []AccountID) *TransactionReceiptQuery {
   134  	q.Query.SetNodeAccountIDs(accountID)
   135  	return q
   136  }
   137  
   138  // SetQueryPayment sets the Hbar payment to pay the _Node a fee for handling this query
   139  func (q *TransactionReceiptQuery) SetQueryPayment(queryPayment Hbar) *TransactionReceiptQuery {
   140  	q.Query.SetQueryPayment(queryPayment)
   141  	return q
   142  }
   143  
   144  // SetMaxQueryPayment sets the maximum payment allowed for this Query.
   145  func (q *TransactionReceiptQuery) SetMaxQueryPayment(queryMaxPayment Hbar) *TransactionReceiptQuery {
   146  	q.Query.SetMaxQueryPayment(queryMaxPayment)
   147  	return q
   148  }
   149  
   150  // SetMaxRetry sets the max number of errors before execution will fail.
   151  func (q *TransactionReceiptQuery) SetMaxRetry(count int) *TransactionReceiptQuery {
   152  	q.Query.SetMaxRetry(count)
   153  	return q
   154  }
   155  
   156  // SetMaxBackoff The maximum amount of time to wait between retries.
   157  // Every retry attempt will increase the wait time exponentially until it reaches this time.
   158  func (q *TransactionReceiptQuery) SetMaxBackoff(max time.Duration) *TransactionReceiptQuery {
   159  	q.Query.SetMaxBackoff(max)
   160  	return q
   161  }
   162  
   163  // SetMinBackoff sets the minimum amount of time to wait between retries.
   164  func (q *TransactionReceiptQuery) SetMinBackoff(min time.Duration) *TransactionReceiptQuery {
   165  	q.Query.SetMinBackoff(min)
   166  	return q
   167  }
   168  
   169  // SetPaymentTransactionID assigns the payment transaction id.
   170  func (q *TransactionReceiptQuery) SetPaymentTransactionID(transactionID TransactionID) *TransactionReceiptQuery {
   171  	q.Query.SetPaymentTransactionID(transactionID)
   172  	return q
   173  }
   174  
   175  func (q *TransactionReceiptQuery) SetLogLevel(level LogLevel) *TransactionReceiptQuery {
   176  	q.Query.SetLogLevel(level)
   177  	return q
   178  }
   179  
   180  // ---------- Parent functions specific implementation ----------
   181  
   182  func (q *TransactionReceiptQuery) getMethod(channel *_Channel) _Method {
   183  	return _Method{
   184  		query: channel._GetCrypto().GetTransactionReceipts,
   185  	}
   186  }
   187  
   188  func (q *TransactionReceiptQuery) mapStatusError(_ Executable, response interface{}) error {
   189  	status := Status(response.(*services.Response).GetTransactionGetReceipt().GetHeader().GetNodeTransactionPrecheckCode())
   190  	switch status {
   191  	case StatusPlatformTransactionNotCreated, StatusBusy, StatusUnknown, StatusOk:
   192  		break
   193  	default:
   194  		return ErrHederaPreCheckStatus{
   195  			Status: status,
   196  		}
   197  	}
   198  
   199  	return ErrHederaPreCheckStatus{
   200  		Status: Status(response.(*services.Response).GetTransactionGetReceipt().GetReceipt().GetStatus()),
   201  	}
   202  }
   203  
   204  func (q *TransactionReceiptQuery) getName() string {
   205  	return "TransactionReceiptQuery"
   206  }
   207  
   208  func (q *TransactionReceiptQuery) buildQuery() *services.Query {
   209  	body := &services.TransactionGetReceiptQuery{
   210  		Header: q.pbHeader,
   211  	}
   212  
   213  	if q.transactionID.AccountID != nil {
   214  		body.TransactionID = q.transactionID._ToProtobuf()
   215  	}
   216  
   217  	if q.duplicates != nil {
   218  		body.IncludeDuplicates = *q.duplicates
   219  	}
   220  
   221  	if q.childReceipts != nil {
   222  		body.IncludeChildReceipts = q.GetIncludeChildren()
   223  	}
   224  
   225  	return &services.Query{
   226  		Query: &services.Query_TransactionGetReceipt{
   227  			TransactionGetReceipt: body,
   228  		},
   229  	}
   230  }
   231  
   232  func (q *TransactionReceiptQuery) validateNetworkOnIDs(client *Client) error {
   233  	if client == nil || !client.autoValidateChecksums {
   234  		return nil
   235  	}
   236  
   237  	if err := q.transactionID.AccountID.ValidateChecksum(client); err != nil {
   238  		return err
   239  	}
   240  
   241  	return nil
   242  }
   243  
   244  func (q *TransactionReceiptQuery) shouldRetry(_ Executable, response interface{}) _ExecutionState {
   245  	status := Status(response.(*services.Response).GetTransactionGetReceipt().GetHeader().GetNodeTransactionPrecheckCode())
   246  
   247  	switch status {
   248  	case StatusPlatformTransactionNotCreated, StatusBusy, StatusUnknown, StatusReceiptNotFound, StatusRecordNotFound, StatusPlatformNotActive:
   249  		return executionStateRetry
   250  	case StatusOk:
   251  		break
   252  	default:
   253  		return executionStateError
   254  	}
   255  
   256  	status = Status(response.(*services.Response).GetTransactionGetReceipt().GetReceipt().GetStatus())
   257  
   258  	switch status {
   259  	case StatusBusy, StatusUnknown, StatusOk, StatusReceiptNotFound, StatusRecordNotFound, StatusPlatformNotActive:
   260  		return executionStateRetry
   261  	default:
   262  		return executionStateFinished
   263  	}
   264  }
   265  
   266  func (q *TransactionReceiptQuery) getQueryResponse(response *services.Response) queryResponse {
   267  	return response.GetTransactionGetReceipt()
   268  }