github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/transaction_record_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  // TransactionRecordQuery
    30  // Get the record for a transaction. If the transaction requested a record, then the record lasts
    31  // for one hour, and a state proof is available for it. If the transaction created an account, file,
    32  // or smart contract instance, then the record will contain the ID for what it created. If the
    33  // transaction called a smart contract function, then the record contains the result of that call.
    34  // If the transaction was a cryptocurrency transfer, then the record includes the TransferList which
    35  // gives the details of that transfer. If the transaction didn't return anything that should be in
    36  // the record, then the results field will be set to nothing.
    37  type TransactionRecordQuery struct {
    38  	Query
    39  	transactionID       *TransactionID
    40  	includeChildRecords *bool
    41  	duplicates          *bool
    42  }
    43  
    44  // NewTransactionRecordQuery creates TransactionRecordQuery which
    45  // gets the record for a transaction. If the transaction requested a record, then the record lasts
    46  // for one hour, and a state proof is available for it. If the transaction created an account, file,
    47  // or smart contract instance, then the record will contain the ID for what it created. If the
    48  // transaction called a smart contract function, then the record contains the result of that call.
    49  // If the transaction was a cryptocurrency transfer, then the record includes the TransferList which
    50  // gives the details of that transfer. If the transaction didn't return anything that should be in
    51  // the record, then the results field will be set to nothing.
    52  func NewTransactionRecordQuery() *TransactionRecordQuery {
    53  	header := services.QueryHeader{}
    54  	return &TransactionRecordQuery{
    55  		Query: _NewQuery(true, &header),
    56  	}
    57  }
    58  
    59  // When execution is attempted, a single attempt will timeout when this deadline is reached. (The SDK may subsequently retry the execution.)
    60  func (q *TransactionRecordQuery) SetGrpcDeadline(deadline *time.Duration) *TransactionRecordQuery {
    61  	q.Query.SetGrpcDeadline(deadline)
    62  	return q
    63  }
    64  
    65  // SetIncludeChildren Sets whether the response should include the records of any child transactions spawned by the
    66  // top-level transaction with the given transactionID.
    67  func (q *TransactionRecordQuery) SetIncludeChildren(includeChildRecords bool) *TransactionRecordQuery {
    68  	q.includeChildRecords = &includeChildRecords
    69  	return q
    70  }
    71  
    72  // GetIncludeChildren returns whether the response should include the records of any child transactions spawned by the
    73  // top-level transaction with the given transactionID.
    74  func (q *TransactionRecordQuery) GetIncludeChildren() bool {
    75  	if q.includeChildRecords != nil {
    76  		return *q.includeChildRecords
    77  	}
    78  
    79  	return false
    80  }
    81  
    82  // SetIncludeDuplicates Sets whether records of processing duplicate transactions should be returned along with the record
    83  // of processing the first consensus transaction with the given id whose status was neither
    84  // INVALID_NODE_ACCOUNT nor <tt>INVALID_PAYER_SIGNATURE; or, if no such
    85  // record exists, the record of processing the first transaction to reach consensus with the
    86  // given transaction id..
    87  func (q *TransactionRecordQuery) SetIncludeDuplicates(includeDuplicates bool) *TransactionRecordQuery {
    88  	q.duplicates = &includeDuplicates
    89  	return q
    90  }
    91  
    92  // GetIncludeDuplicates returns whether records of processing duplicate transactions should be returned along with the record
    93  // of processing the first consensus transaction with the given id.
    94  func (q *TransactionRecordQuery) GetIncludeDuplicates() bool {
    95  	if q.duplicates != nil {
    96  		return *q.duplicates
    97  	}
    98  
    99  	return false
   100  }
   101  
   102  func (q *TransactionRecordQuery) GetCost(client *Client) (Hbar, error) {
   103  	return q.Query.getCost(client, q)
   104  }
   105  
   106  // Execute executes the Query with the provided client
   107  func (q *TransactionRecordQuery) Execute(client *Client) (TransactionRecord, error) {
   108  	resp, err := q.Query.execute(client, q)
   109  
   110  	if err != nil {
   111  		if precheckErr, ok := err.(ErrHederaPreCheckStatus); ok {
   112  			return TransactionRecord{}, _NewErrHederaReceiptStatus(precheckErr.TxID, precheckErr.Status)
   113  		}
   114  		return TransactionRecord{}, err
   115  	}
   116  
   117  	return _TransactionRecordFromProtobuf(resp.GetTransactionGetRecord(), q.transactionID), nil
   118  }
   119  
   120  // SetTransactionID sets the TransactionID for this TransactionRecordQuery.
   121  func (q *TransactionRecordQuery) SetTransactionID(transactionID TransactionID) *TransactionRecordQuery {
   122  	q.transactionID = &transactionID
   123  	return q
   124  }
   125  
   126  // GetTransactionID returns the TransactionID for which the receipt is being requested.
   127  func (q *TransactionRecordQuery) GetTransactionID() TransactionID {
   128  	if q.transactionID == nil {
   129  		return TransactionID{}
   130  	}
   131  
   132  	return *q.transactionID
   133  }
   134  
   135  // SetNodeAccountIDs sets the _Node AccountID for this TransactionRecordQuery.
   136  func (q *TransactionRecordQuery) SetNodeAccountIDs(accountID []AccountID) *TransactionRecordQuery {
   137  	q.Query.SetNodeAccountIDs(accountID)
   138  	return q
   139  }
   140  
   141  // SetQueryPayment sets the Hbar payment to pay the _Node a fee for handling this query
   142  func (q *TransactionRecordQuery) SetQueryPayment(queryPayment Hbar) *TransactionRecordQuery {
   143  	q.Query.SetQueryPayment(queryPayment)
   144  	return q
   145  }
   146  
   147  // SetMaxQueryPayment sets the maximum payment allowed for this Query.
   148  func (q *TransactionRecordQuery) SetMaxQueryPayment(queryMaxPayment Hbar) *TransactionRecordQuery {
   149  	q.Query.SetMaxQueryPayment(queryMaxPayment)
   150  	return q
   151  }
   152  
   153  // SetMaxRetry sets the max number of errors before execution will fail.
   154  func (q *TransactionRecordQuery) SetMaxRetry(count int) *TransactionRecordQuery {
   155  	q.Query.SetMaxRetry(count)
   156  	return q
   157  }
   158  
   159  // SetMaxBackoff The maximum amount of time to wait between retries.
   160  // Every retry attempt will increase the wait time exponentially until it reaches this time.
   161  func (q *TransactionRecordQuery) SetMaxBackoff(max time.Duration) *TransactionRecordQuery {
   162  	q.Query.SetMaxBackoff(max)
   163  	return q
   164  }
   165  
   166  // SetMinBackoff sets the minimum amount of time to wait between retries.
   167  func (q *TransactionRecordQuery) SetMinBackoff(min time.Duration) *TransactionRecordQuery {
   168  	q.Query.SetMinBackoff(min)
   169  	return q
   170  }
   171  
   172  // SetPaymentTransactionID assigns the payment transaction id.
   173  func (q *TransactionRecordQuery) SetPaymentTransactionID(transactionID TransactionID) *TransactionRecordQuery {
   174  	q.paymentTransactionIDs._Clear()._Push(transactionID)._SetLocked(true)
   175  	return q
   176  }
   177  
   178  func (q *TransactionRecordQuery) SetLogLevel(level LogLevel) *TransactionRecordQuery {
   179  	q.Query.SetLogLevel(level)
   180  	return q
   181  }
   182  
   183  // ---------- Parent functions specific implementation ----------
   184  
   185  func (q *TransactionRecordQuery) getMethod(channel *_Channel) _Method {
   186  	return _Method{
   187  		query: channel._GetCrypto().GetTxRecordByTxID,
   188  	}
   189  }
   190  
   191  func (q *TransactionRecordQuery) mapStatusError(_ Executable, response interface{}) error {
   192  	query := response.(*services.Response)
   193  	switch Status(query.GetTransactionGetRecord().GetHeader().GetNodeTransactionPrecheckCode()) {
   194  	case StatusPlatformTransactionNotCreated, StatusBusy, StatusUnknown, StatusReceiptNotFound, StatusRecordNotFound, StatusOk:
   195  		break
   196  	default:
   197  		return ErrHederaPreCheckStatus{
   198  			Status: Status(query.GetTransactionGetRecord().GetHeader().GetNodeTransactionPrecheckCode()),
   199  		}
   200  	}
   201  
   202  	return ErrHederaReceiptStatus{
   203  		Status: Status(query.GetTransactionGetRecord().GetTransactionRecord().GetReceipt().GetStatus()),
   204  		// TxID:    _TransactionIDFromProtobuf(_Request.Query.pb.GetTransactionGetRecord().TransactionID, networkName),
   205  		Receipt: _TransactionReceiptFromProtobuf(query.GetTransactionGetReceipt(), nil),
   206  	}
   207  }
   208  
   209  func (q *TransactionRecordQuery) getName() string {
   210  	return "TransactionRecordQuery"
   211  }
   212  
   213  func (q *TransactionRecordQuery) buildQuery() *services.Query {
   214  	body := &services.TransactionGetRecordQuery{
   215  		Header: q.pbHeader,
   216  	}
   217  
   218  	if q.includeChildRecords != nil {
   219  		body.IncludeChildRecords = q.GetIncludeChildren()
   220  	}
   221  
   222  	if q.duplicates != nil {
   223  		body.IncludeDuplicates = q.GetIncludeDuplicates()
   224  	}
   225  
   226  	if q.transactionID.AccountID != nil {
   227  		body.TransactionID = q.transactionID._ToProtobuf()
   228  	}
   229  
   230  	return &services.Query{
   231  		Query: &services.Query_TransactionGetRecord{
   232  			TransactionGetRecord: body,
   233  		},
   234  	}
   235  }
   236  
   237  func (q *TransactionRecordQuery) validateNetworkOnIDs(client *Client) error {
   238  	if client == nil || !client.autoValidateChecksums {
   239  		return nil
   240  	}
   241  
   242  	if err := q.transactionID.AccountID.ValidateChecksum(client); err != nil {
   243  		return err
   244  	}
   245  
   246  	return nil
   247  }
   248  
   249  func (q *TransactionRecordQuery) shouldRetry(_ Executable, response interface{}) _ExecutionState {
   250  	status := Status(response.(*services.Response).GetTransactionGetRecord().GetHeader().GetNodeTransactionPrecheckCode())
   251  
   252  	switch status {
   253  	case StatusPlatformTransactionNotCreated, StatusBusy, StatusUnknown, StatusReceiptNotFound, StatusRecordNotFound, StatusPlatformNotActive:
   254  		return executionStateRetry
   255  	case StatusOk:
   256  		if response.(*services.Response).GetTransactionGetRecord().GetHeader().ResponseType == services.ResponseType_COST_ANSWER {
   257  			return executionStateFinished
   258  		}
   259  	default:
   260  		return executionStateError
   261  	}
   262  
   263  	status = Status(response.(*services.Response).GetTransactionGetRecord().GetTransactionRecord().GetReceipt().GetStatus())
   264  
   265  	switch status {
   266  	case StatusBusy, StatusUnknown, StatusOk, StatusReceiptNotFound, StatusRecordNotFound, StatusPlatformNotActive:
   267  		return executionStateRetry
   268  	case StatusSuccess:
   269  		return executionStateFinished
   270  	default:
   271  		return executionStateError
   272  	}
   273  }
   274  
   275  func (q *TransactionRecordQuery) getQueryResponse(response *services.Response) queryResponse {
   276  	return response.GetTransactionGetRecord()
   277  }