github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/contract_call_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  // ContractCallQuery calls a function of the given smart contract instance, giving it ContractFunctionParameters as its
    30  // inputs. It will consume the entire given amount of gas.
    31  //
    32  // This is performed locally on the particular _Node that the client is communicating with. It cannot change the state of
    33  // the contract instance (and so, cannot spend anything from the instance's Hedera account). It will not have a
    34  // consensus timestamp. It cannot generate a record or a receipt. This is useful for calling getter functions, which
    35  // purely read the state and don't change it. It is faster and cheaper than a ContractExecuteTransaction, because it is
    36  // purely local to a single  _Node.
    37  type ContractCallQuery struct {
    38  	Query
    39  	contractID         *ContractID
    40  	gas                uint64
    41  	maxResultSize      uint64
    42  	functionParameters []byte
    43  	senderID           *AccountID
    44  }
    45  
    46  // NewContractCallQuery creates a ContractCallQuery query which can be used to construct and execute a
    47  // Contract Call Local Query.
    48  func NewContractCallQuery() *ContractCallQuery {
    49  	header := services.QueryHeader{}
    50  	query := _NewQuery(true, &header)
    51  
    52  	return &ContractCallQuery{
    53  		Query: query,
    54  	}
    55  }
    56  
    57  // When execution is attempted, a single attempt will timeout when this deadline is reached. (The SDK may subsequently retry the execution.)
    58  func (q *ContractCallQuery) SetGrpcDeadline(deadline *time.Duration) *ContractCallQuery {
    59  	q.Query.SetGrpcDeadline(deadline)
    60  	return q
    61  }
    62  
    63  // SetContractID sets the contract instance to call
    64  func (q *ContractCallQuery) SetContractID(contractID ContractID) *ContractCallQuery {
    65  	q.contractID = &contractID
    66  	return q
    67  }
    68  
    69  // GetContractID returns the contract instance to call
    70  func (q *ContractCallQuery) GetContractID() ContractID {
    71  	if q.contractID == nil {
    72  		return ContractID{}
    73  	}
    74  
    75  	return *q.contractID
    76  }
    77  
    78  // SetSenderID
    79  // The account that is the "sender." If not present it is the accountId from the transactionId.
    80  // Typically a different value than specified in the transactionId requires a valid signature
    81  // over either the hedera transaction or foreign transaction data.
    82  func (q *ContractCallQuery) SetSenderID(id AccountID) *ContractCallQuery {
    83  	q.senderID = &id
    84  	return q
    85  }
    86  
    87  // GetSenderID returns the AccountID that is the "sender."
    88  func (q *ContractCallQuery) GetSenderID() AccountID {
    89  	if q.senderID == nil {
    90  		return AccountID{}
    91  	}
    92  
    93  	return *q.senderID
    94  }
    95  
    96  // SetGas sets the amount of gas to use for the call. All of the gas offered will be charged for.
    97  func (q *ContractCallQuery) SetGas(gas uint64) *ContractCallQuery {
    98  	q.gas = gas
    99  	return q
   100  }
   101  
   102  // GetGas returns the amount of gas to use for the call.
   103  func (q *ContractCallQuery) GetGas() uint64 {
   104  	return q.gas
   105  }
   106  
   107  // Deprecated
   108  func (q *ContractCallQuery) SetMaxResultSize(size uint64) *ContractCallQuery {
   109  	q.maxResultSize = size
   110  	return q
   111  }
   112  
   113  // SetFunction sets which function to call, and the ContractFunctionParams to pass to the function
   114  func (q *ContractCallQuery) SetFunction(name string, params *ContractFunctionParameters) *ContractCallQuery {
   115  	if params == nil {
   116  		params = NewContractFunctionParameters()
   117  	}
   118  
   119  	q.functionParameters = params._Build(&name)
   120  	return q
   121  }
   122  
   123  // SetFunctionParameters sets the function parameters as their raw bytes.
   124  func (q *ContractCallQuery) SetFunctionParameters(byteArray []byte) *ContractCallQuery {
   125  	q.functionParameters = byteArray
   126  	return q
   127  }
   128  
   129  // GetFunctionParameters returns the function parameters as their raw bytes.
   130  func (q *ContractCallQuery) GetFunctionParameters() []byte {
   131  	return q.functionParameters
   132  }
   133  
   134  func (q *ContractCallQuery) GetCost(client *Client) (Hbar, error) {
   135  	return q.Query.getCost(client, q)
   136  }
   137  
   138  // Execute executes the Query with the provided client
   139  func (q *ContractCallQuery) Execute(client *Client) (ContractFunctionResult, error) {
   140  	resp, err := q.Query.execute(client, q)
   141  
   142  	if err != nil {
   143  		return ContractFunctionResult{}, err
   144  	}
   145  
   146  	return _ContractFunctionResultFromProtobuf(resp.GetContractCallLocal().FunctionResult), nil
   147  }
   148  
   149  // SetMaxQueryPayment sets the maximum payment allowed for this Query.
   150  func (q *ContractCallQuery) SetMaxQueryPayment(maxPayment Hbar) *ContractCallQuery {
   151  	q.Query.SetMaxQueryPayment(maxPayment)
   152  	return q
   153  }
   154  
   155  // SetQueryPayment sets the payment amount for this Query.
   156  func (q *ContractCallQuery) SetQueryPayment(paymentAmount Hbar) *ContractCallQuery {
   157  	q.Query.SetQueryPayment(paymentAmount)
   158  	return q
   159  }
   160  
   161  // SetNodeAccountIDs sets the _Node AccountID for this ContractCallQuery.
   162  func (q *ContractCallQuery) SetNodeAccountIDs(accountID []AccountID) *ContractCallQuery {
   163  	q.Query.SetNodeAccountIDs(accountID)
   164  	return q
   165  }
   166  
   167  // SetMaxRetry sets the max number of errors before execution will fail.
   168  func (q *ContractCallQuery) SetMaxRetry(count int) *ContractCallQuery {
   169  	q.Query.SetMaxRetry(count)
   170  	return q
   171  }
   172  
   173  // SetMaxBackoff The maximum amount of time to wait between retries.
   174  // Every retry attempt will increase the wait time exponentially until it reaches this time.
   175  func (q *ContractCallQuery) SetMaxBackoff(max time.Duration) *ContractCallQuery {
   176  	q.Query.SetMaxBackoff(max)
   177  	return q
   178  }
   179  
   180  // SetMinBackoff sets the minimum amount of time to wait between retries.
   181  func (q *ContractCallQuery) SetMinBackoff(min time.Duration) *ContractCallQuery {
   182  	q.Query.SetMinBackoff(min)
   183  	return q
   184  }
   185  
   186  // SetPaymentTransactionID assigns the payment transaction id.
   187  func (q *ContractCallQuery) SetPaymentTransactionID(transactionID TransactionID) *ContractCallQuery {
   188  	q.paymentTransactionIDs._Clear()._Push(transactionID)._SetLocked(true)
   189  	return q
   190  }
   191  
   192  func (q *ContractCallQuery) SetLogLevel(level LogLevel) *ContractCallQuery {
   193  	q.Query.SetLogLevel(level)
   194  	return q
   195  }
   196  
   197  // ---------- Parent functions specific implementation ----------
   198  
   199  func (q *ContractCallQuery) getMethod(channel *_Channel) _Method {
   200  	return _Method{
   201  		query: channel._GetContract().ContractCallLocalMethod,
   202  	}
   203  }
   204  
   205  func (q *ContractCallQuery) getName() string {
   206  	return "ContractCallQuery"
   207  }
   208  
   209  func (q *ContractCallQuery) buildQuery() *services.Query {
   210  	pb := services.Query_ContractCallLocal{
   211  		ContractCallLocal: &services.ContractCallLocalQuery{
   212  			Header: q.pbHeader,
   213  			Gas:    int64(q.gas),
   214  		},
   215  	}
   216  
   217  	if q.contractID != nil {
   218  		pb.ContractCallLocal.ContractID = q.contractID._ToProtobuf()
   219  	}
   220  
   221  	if q.senderID != nil {
   222  		pb.ContractCallLocal.SenderId = q.senderID._ToProtobuf()
   223  	}
   224  
   225  	if len(q.functionParameters) > 0 {
   226  		pb.ContractCallLocal.FunctionParameters = q.functionParameters
   227  	}
   228  
   229  	return &services.Query{
   230  		Query: &pb,
   231  	}
   232  }
   233  
   234  func (q *ContractCallQuery) validateNetworkOnIDs(client *Client) error {
   235  	if client == nil || !client.autoValidateChecksums {
   236  		return nil
   237  	}
   238  
   239  	if q.contractID != nil {
   240  		if err := q.contractID.ValidateChecksum(client); err != nil {
   241  			return err
   242  		}
   243  	}
   244  
   245  	if q.senderID != nil {
   246  		if err := q.senderID.ValidateChecksum(client); err != nil {
   247  			return err
   248  		}
   249  	}
   250  
   251  	return nil
   252  }
   253  
   254  func (q *ContractCallQuery) getQueryResponse(response *services.Response) queryResponse {
   255  	return response.GetContractCallLocal()
   256  }