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

     1  //go:build all || unit
     2  // +build all unit
     3  
     4  package hedera
     5  
     6  /*-
     7   *
     8   * Hedera Go SDK
     9   *
    10   * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC
    11   *
    12   * Licensed under the Apache License, Version 2.0 (the "License");
    13   * you may not use this file except in compliance with the License.
    14   * You may obtain a copy of the License at
    15   *
    16   *      http://www.apache.org/licenses/LICENSE-2.0
    17   *
    18   * Unless required by applicable law or agreed to in writing, software
    19   * distributed under the License is distributed on an "AS IS" BASIS,
    20   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    21   * See the License for the specific language governing permissions and
    22   * limitations under the License.
    23   *
    24   */
    25  
    26  import (
    27  	"context"
    28  	"net"
    29  	"testing"
    30  	"time"
    31  
    32  	"github.com/hashgraph/hedera-protobufs-go/mirror"
    33  	"google.golang.org/grpc/codes"
    34  	"google.golang.org/grpc/status"
    35  
    36  	"github.com/stretchr/testify/require"
    37  	protobuf "google.golang.org/protobuf/proto"
    38  
    39  	"github.com/hashgraph/hedera-protobufs-go/services"
    40  	"google.golang.org/grpc"
    41  )
    42  
    43  func TestUnitMockQuery(t *testing.T) {
    44  	t.Parallel()
    45  	responses := [][]interface{}{
    46  		{
    47  			&services.Response{
    48  				Response: &services.Response_CryptogetAccountBalance{
    49  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
    50  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY, ResponseType: services.ResponseType_ANSWER_ONLY},
    51  					},
    52  				},
    53  			},
    54  			&services.Response{
    55  				Response: &services.Response_CryptogetAccountBalance{
    56  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
    57  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY, ResponseType: services.ResponseType_ANSWER_ONLY},
    58  					},
    59  				},
    60  			},
    61  			&services.Response{
    62  				Response: &services.Response_CryptogetAccountBalance{
    63  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
    64  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY, ResponseType: services.ResponseType_ANSWER_ONLY},
    65  					},
    66  				},
    67  			},
    68  			&services.Response{
    69  				Response: &services.Response_CryptogetAccountBalance{
    70  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
    71  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY, ResponseType: services.ResponseType_ANSWER_ONLY},
    72  					},
    73  				},
    74  			},
    75  			&services.Response{
    76  				Response: &services.Response_CryptogetAccountBalance{
    77  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
    78  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY, ResponseType: services.ResponseType_ANSWER_ONLY},
    79  					},
    80  				},
    81  			},
    82  			&services.Response{
    83  				Response: &services.Response_CryptogetAccountBalance{
    84  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
    85  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY, ResponseType: services.ResponseType_ANSWER_ONLY},
    86  					},
    87  				},
    88  			},
    89  			&services.Response{
    90  				Response: &services.Response_CryptogetAccountBalance{
    91  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
    92  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY, ResponseType: services.ResponseType_ANSWER_ONLY},
    93  					},
    94  				},
    95  			},
    96  			&services.Response{
    97  				Response: &services.Response_CryptogetAccountBalance{
    98  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
    99  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK, ResponseType: services.ResponseType_COST_ANSWER, Cost: 0},
   100  						AccountID: &services.AccountID{ShardNum: 0, RealmNum: 0, Account: &services.AccountID_AccountNum{
   101  							AccountNum: 1800,
   102  						}},
   103  						Balance: 2000,
   104  					},
   105  				},
   106  			},
   107  			&services.Response{
   108  				Response: &services.Response_CryptogetAccountBalance{
   109  					CryptogetAccountBalance: &services.CryptoGetAccountBalanceResponse{
   110  						Header: &services.ResponseHeader{NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK, ResponseType: services.ResponseType_ANSWER_ONLY, Cost: 0},
   111  						AccountID: &services.AccountID{ShardNum: 0, RealmNum: 0, Account: &services.AccountID_AccountNum{
   112  							AccountNum: 1800,
   113  						}},
   114  						Balance: 2000,
   115  					},
   116  				},
   117  			},
   118  		},
   119  	}
   120  
   121  	client, server := NewMockClientAndServer(responses)
   122  	defer server.Close()
   123  
   124  	_, err := NewAccountBalanceQuery().
   125  		SetNodeAccountIDs([]AccountID{{Account: 3}}).
   126  		SetAccountID(AccountID{Account: 1800}).
   127  		Execute(client)
   128  	require.NoError(t, err)
   129  }
   130  
   131  func DisabledTestUnitMockBackoff(t *testing.T) {
   132  	responses := [][]interface{}{{
   133  		&services.TransactionResponse{
   134  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   135  		},
   136  		&services.TransactionResponse{
   137  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   138  		},
   139  		&services.TransactionResponse{
   140  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   141  		},
   142  		&services.TransactionResponse{
   143  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   144  		},
   145  	}, {
   146  		&services.TransactionResponse{
   147  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   148  		},
   149  		&services.TransactionResponse{
   150  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   151  		},
   152  		&services.TransactionResponse{
   153  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   154  		},
   155  		&services.TransactionResponse{
   156  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   157  		},
   158  		&services.TransactionResponse{
   159  			NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   160  		},
   161  	}}
   162  
   163  	client, server := NewMockClientAndServer(responses)
   164  	defer server.Close()
   165  
   166  	newKey, err := PrivateKeyGenerateEd25519()
   167  	require.NoError(t, err)
   168  
   169  	newBalance := NewHbar(2)
   170  
   171  	tran := TransactionIDGenerate(AccountID{Account: 3})
   172  
   173  	_, err = NewAccountCreateTransaction().
   174  		SetNodeAccountIDs([]AccountID{{Account: 3}, {Account: 4}}).
   175  		SetKey(newKey).
   176  		SetTransactionID(tran).
   177  		SetInitialBalance(newBalance).
   178  		SetMaxAutomaticTokenAssociations(100).
   179  		Execute(client)
   180  	require.NoError(t, err)
   181  }
   182  
   183  func TestUnitMockAddressBookQuery(t *testing.T) {
   184  	t.Parallel()
   185  	responses := [][]interface{}{{
   186  		&services.NodeAddress{
   187  			RSA_PubKey: "",
   188  			NodeId:     0,
   189  			NodeAccountId: &services.AccountID{
   190  				ShardNum: 0,
   191  				RealmNum: 0,
   192  				Account:  &services.AccountID_AccountNum{AccountNum: 3},
   193  			},
   194  			NodeCertHash: []byte{1},
   195  			ServiceEndpoint: []*services.ServiceEndpoint{
   196  				{
   197  					IpAddressV4: []byte{byte(uint(1)), byte(uint(2)), byte(uint(2)), byte(uint(3))},
   198  					Port:        50123,
   199  					DomainName:  "hedera.domain.name",
   200  				},
   201  				{
   202  					IpAddressV4: []byte{byte(uint(2)), byte(uint(1)), byte(uint(2)), byte(uint(3))},
   203  					Port:        50123,
   204  					DomainName:  "hedera.domain.name",
   205  				},
   206  			},
   207  			Description: "",
   208  			Stake:       0,
   209  		},
   210  		&services.NodeAddress{
   211  			RSA_PubKey: "",
   212  			NodeId:     0,
   213  			NodeAccountId: &services.AccountID{
   214  				ShardNum: 0,
   215  				RealmNum: 0,
   216  				Account:  &services.AccountID_AccountNum{AccountNum: 4},
   217  			},
   218  			NodeCertHash: []byte{1},
   219  			ServiceEndpoint: []*services.ServiceEndpoint{
   220  				{
   221  					IpAddressV4: []byte{byte(uint(1)), byte(uint(2)), byte(uint(2)), byte(uint(9))},
   222  					Port:        50123,
   223  					DomainName:  "hedera.domain.name2",
   224  				},
   225  				{
   226  					IpAddressV4: []byte{byte(uint(2)), byte(uint(1)), byte(uint(2)), byte(uint(9))},
   227  					Port:        50123,
   228  					DomainName:  "hedera.domain.name2",
   229  				},
   230  			},
   231  			Description: "",
   232  			Stake:       0,
   233  		},
   234  	},
   235  	}
   236  
   237  	client, server := NewMockClientAndServer(responses)
   238  	defer server.Close()
   239  
   240  	result, err := NewAddressBookQuery().
   241  		SetFileID(FileID{0, 0, 101, nil}).
   242  		Execute(client)
   243  	require.NoError(t, err)
   244  
   245  	require.Equal(t, len(result.NodeAddresses), 2)
   246  	require.Equal(t, result.NodeAddresses[0].AccountID.String(), "0.0.3")
   247  	require.Equal(t, result.NodeAddresses[0].Addresses[0].String(), "hedera.domain.name:50123")
   248  	require.Equal(t, result.NodeAddresses[0].Addresses[1].String(), "hedera.domain.name:50123")
   249  	require.Equal(t, result.NodeAddresses[1].AccountID.String(), "0.0.4")
   250  	require.Equal(t, result.NodeAddresses[1].Addresses[0].String(), "hedera.domain.name2:50123")
   251  	require.Equal(t, result.NodeAddresses[1].Addresses[1].String(), "hedera.domain.name2:50123")
   252  }
   253  
   254  func TestUnitMockGenerateTransactionIDsPerExecution(t *testing.T) {
   255  	t.Parallel()
   256  	count := 0
   257  	transactionIds := make(map[string]bool)
   258  
   259  	call := func(request *services.Transaction) *services.TransactionResponse {
   260  		var response *services.TransactionResponse
   261  		require.NotEmpty(t, request.SignedTransactionBytes)
   262  		signedTransaction := services.SignedTransaction{}
   263  		_ = protobuf.Unmarshal(request.SignedTransactionBytes, &signedTransaction)
   264  
   265  		require.NotEmpty(t, signedTransaction.BodyBytes)
   266  		transactionBody := services.TransactionBody{}
   267  		_ = protobuf.Unmarshal(signedTransaction.BodyBytes, &transactionBody)
   268  
   269  		require.NotNil(t, transactionBody.TransactionID)
   270  		transactionId := transactionBody.TransactionID.String()
   271  		require.NotEqual(t, "", transactionId)
   272  		if count < 2 {
   273  			require.False(t, transactionIds[transactionId])
   274  		}
   275  		transactionIds[transactionId] = true
   276  
   277  		sigMap := signedTransaction.GetSigMap()
   278  		require.NotNil(t, sigMap)
   279  		require.NotEqual(t, 0, len(sigMap.SigPair))
   280  
   281  		for _, sigPair := range sigMap.SigPair {
   282  			verified := false
   283  
   284  			switch k := sigPair.Signature.(type) {
   285  			case *services.SignaturePair_Ed25519:
   286  				pbTemp, _ := PublicKeyFromBytesEd25519(sigPair.PubKeyPrefix)
   287  				verified = pbTemp.Verify(signedTransaction.BodyBytes, k.Ed25519)
   288  			case *services.SignaturePair_ECDSASecp256K1:
   289  				pbTemp, _ := PublicKeyFromBytesECDSA(sigPair.PubKeyPrefix)
   290  				verified = pbTemp.Verify(signedTransaction.BodyBytes, k.ECDSASecp256K1)
   291  			}
   292  			require.True(t, verified)
   293  		}
   294  
   295  		if count < 2 {
   296  			response = &services.TransactionResponse{
   297  				NodeTransactionPrecheckCode: services.ResponseCodeEnum_TRANSACTION_EXPIRED,
   298  			}
   299  		} else {
   300  			response = &services.TransactionResponse{
   301  				NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK,
   302  			}
   303  		}
   304  
   305  		count += 1
   306  
   307  		return response
   308  	}
   309  	responses := [][]interface{}{{
   310  		call, call, call,
   311  	}}
   312  
   313  	client, server := NewMockClientAndServer(responses)
   314  	defer server.Close()
   315  
   316  	_, err := NewFileCreateTransaction().
   317  		SetNodeAccountIDs([]AccountID{{Account: 3}}).
   318  		SetContents([]byte("hello")).
   319  		Execute(client)
   320  	require.NoError(t, err)
   321  }
   322  
   323  func TestUnitMockSingleTransactionIDForExecutions(t *testing.T) {
   324  	t.Parallel()
   325  	count := 0
   326  	tran := TransactionIDGenerate(AccountID{Account: 1800})
   327  	transactionIds := make(map[string]bool)
   328  	transactionIds[tran._ToProtobuf().String()] = true
   329  
   330  	call := func(request *services.Transaction) *services.TransactionResponse {
   331  		var response *services.TransactionResponse
   332  
   333  		require.NotEmpty(t, request.SignedTransactionBytes)
   334  		signedTransaction := services.SignedTransaction{}
   335  		_ = protobuf.Unmarshal(request.SignedTransactionBytes, &signedTransaction)
   336  
   337  		require.NotEmpty(t, signedTransaction.BodyBytes)
   338  		transactionBody := services.TransactionBody{}
   339  		_ = protobuf.Unmarshal(signedTransaction.BodyBytes, &transactionBody)
   340  
   341  		require.NotNil(t, transactionBody.TransactionID)
   342  		transactionId := transactionBody.TransactionID.String()
   343  		require.NotEqual(t, "", transactionId)
   344  		require.True(t, transactionIds[transactionId])
   345  		transactionIds[transactionId] = true
   346  
   347  		sigMap := signedTransaction.GetSigMap()
   348  		require.NotNil(t, sigMap)
   349  		require.NotEqual(t, 0, len(sigMap.SigPair))
   350  
   351  		for _, sigPair := range sigMap.SigPair {
   352  			verified := false
   353  
   354  			switch k := sigPair.Signature.(type) {
   355  			case *services.SignaturePair_Ed25519:
   356  				pbTemp, _ := PublicKeyFromBytesEd25519(sigPair.PubKeyPrefix)
   357  				verified = pbTemp.Verify(signedTransaction.BodyBytes, k.Ed25519)
   358  			case *services.SignaturePair_ECDSASecp256K1:
   359  				pbTemp, _ := PublicKeyFromBytesECDSA(sigPair.PubKeyPrefix)
   360  				verified = pbTemp.Verify(signedTransaction.BodyBytes, k.ECDSASecp256K1)
   361  			}
   362  			require.True(t, verified)
   363  		}
   364  
   365  		if count < 2 {
   366  			response = &services.TransactionResponse{
   367  				NodeTransactionPrecheckCode: services.ResponseCodeEnum_BUSY,
   368  			}
   369  		} else {
   370  			response = &services.TransactionResponse{
   371  				NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK,
   372  			}
   373  		}
   374  
   375  		count += 1
   376  
   377  		return response
   378  	}
   379  	responses := [][]interface{}{{
   380  		call, call, call,
   381  	}}
   382  
   383  	client, server := NewMockClientAndServer(responses)
   384  	defer server.Close()
   385  
   386  	_, err := NewFileCreateTransaction().
   387  		SetNodeAccountIDs([]AccountID{{Account: 3}}).
   388  		SetTransactionID(tran).
   389  		SetContents([]byte("hello")).
   390  		Execute(client)
   391  	require.NoError(t, err)
   392  }
   393  
   394  func TestUnitMockSingleTransactionIDForExecutionsWithTimeout(t *testing.T) {
   395  	t.Parallel()
   396  	count := 0
   397  	tran := TransactionIDGenerate(AccountID{Account: 1800})
   398  	transactionIds := make(map[string]bool)
   399  	transactionIds[tran._ToProtobuf().String()] = true
   400  
   401  	call := func(request *services.Transaction) *services.TransactionResponse {
   402  		var response *services.TransactionResponse
   403  
   404  		require.NotEmpty(t, request.SignedTransactionBytes)
   405  		signedTransaction := services.SignedTransaction{}
   406  		_ = protobuf.Unmarshal(request.SignedTransactionBytes, &signedTransaction)
   407  
   408  		require.NotEmpty(t, signedTransaction.BodyBytes)
   409  		transactionBody := services.TransactionBody{}
   410  		_ = protobuf.Unmarshal(signedTransaction.BodyBytes, &transactionBody)
   411  
   412  		require.NotNil(t, transactionBody.TransactionID)
   413  		transactionId := transactionBody.TransactionID.String()
   414  		require.NotEqual(t, "", transactionId)
   415  		require.True(t, transactionIds[transactionId])
   416  		transactionIds[transactionId] = true
   417  
   418  		sigMap := signedTransaction.GetSigMap()
   419  		require.NotNil(t, sigMap)
   420  		require.NotEqual(t, 0, len(sigMap.SigPair))
   421  
   422  		for _, sigPair := range sigMap.SigPair {
   423  			verified := false
   424  
   425  			switch k := sigPair.Signature.(type) {
   426  			case *services.SignaturePair_Ed25519:
   427  				pbTemp, _ := PublicKeyFromBytesEd25519(sigPair.PubKeyPrefix)
   428  				verified = pbTemp.Verify(signedTransaction.BodyBytes, k.Ed25519)
   429  			case *services.SignaturePair_ECDSASecp256K1:
   430  				pbTemp, _ := PublicKeyFromBytesECDSA(sigPair.PubKeyPrefix)
   431  				verified = pbTemp.Verify(signedTransaction.BodyBytes, k.ECDSASecp256K1)
   432  			}
   433  			require.True(t, verified)
   434  		}
   435  
   436  		if count < 2 {
   437  			response = &services.TransactionResponse{
   438  				NodeTransactionPrecheckCode: services.ResponseCodeEnum_TRANSACTION_EXPIRED,
   439  			}
   440  		} else {
   441  			response = &services.TransactionResponse{
   442  				NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK,
   443  			}
   444  		}
   445  
   446  		count += 1
   447  
   448  		return response
   449  	}
   450  	responses := [][]interface{}{{
   451  		call, call, call,
   452  	}}
   453  
   454  	client, server := NewMockClientAndServer(responses)
   455  	defer server.Close()
   456  
   457  	_, err := NewFileCreateTransaction().
   458  		SetTransactionID(tran).
   459  		SetContents([]byte("hello")).
   460  		Execute(client)
   461  	require.Error(t, err)
   462  }
   463  
   464  type MockServers struct {
   465  	servers []*MockServer
   466  }
   467  
   468  func (servers *MockServers) Close() {
   469  	for _, server := range servers.servers {
   470  		if server != nil {
   471  			server.Close()
   472  		}
   473  	}
   474  }
   475  
   476  func NewMockClientAndServer(allNodeResponses [][]interface{}) (*Client, *MockServers) {
   477  	network := map[string]AccountID{}
   478  	mirrorNetwork := make([]string, len(allNodeResponses))
   479  	servers := make([]*MockServer, len(allNodeResponses))
   480  	ctx, cancel := context.WithCancel(context.Background())
   481  
   482  	logger := NewLogger("hedera client mock", LoggerLevelError)
   483  	var defaultLogger Logger = logger
   484  
   485  	client := &Client{
   486  		defaultMaxQueryPayment:          NewHbar(1),
   487  		network:                         _NewNetwork(),
   488  		mirrorNetwork:                   _NewMirrorNetwork(),
   489  		autoValidateChecksums:           false,
   490  		maxAttempts:                     nil,
   491  		minBackoff:                      250 * time.Millisecond,
   492  		maxBackoff:                      8 * time.Second,
   493  		defaultRegenerateTransactionIDs: true,
   494  		defaultNetworkUpdatePeriod:      24 * time.Hour,
   495  		networkUpdateContext:            ctx,
   496  		cancelNetworkUpdate:             cancel,
   497  		logger:                          defaultLogger,
   498  	}
   499  
   500  	for i, responses := range allNodeResponses {
   501  		responses := responses
   502  
   503  		serverReady := make(chan bool)
   504  		nodeAccountID := AccountID{Account: uint64(3 + i)}
   505  		go func() {
   506  			servers[i] = NewMockServer(responses)
   507  			serverReady <- true
   508  		}()
   509  
   510  		<-serverReady
   511  
   512  		network[servers[i].listener.Addr().String()] = nodeAccountID
   513  		mirrorNetwork[i] = servers[i].listener.Addr().String()
   514  	}
   515  
   516  	client.SetNetwork(network)
   517  	client.SetLedgerID(*NewLedgerIDMainnet())
   518  	client.SetMirrorNetwork(mirrorNetwork)
   519  
   520  	key, _ := PrivateKeyFromStringEd25519("302e020100300506032b657004220420d45e1557156908c967804615af59a000be88c7aa7058bfcbe0f46b16c28f887d")
   521  	client.SetOperator(AccountID{Account: 1800}, key)
   522  	client.SetMinBackoff(0)
   523  	client.SetMaxBackoff(0)
   524  	client.SetMinNodeReadmitTime(0)
   525  	client.SetMaxNodeReadmitTime(0)
   526  	client.SetNodeMinBackoff(0)
   527  	client.SetNodeMaxBackoff(0)
   528  
   529  	return client, &MockServers{servers}
   530  }
   531  
   532  func TestUnitMockAccountInfoQuery(t *testing.T) {
   533  	t.Skip("Skipping test as it is currently broken with the addition of generating new payment transactions for queries")
   534  	call := func(request *services.Query) *services.Response {
   535  		require.NotNil(t, request.Query)
   536  		accountInfoQuery := request.Query.(*services.Query_CryptoGetInfo).CryptoGetInfo
   537  
   538  		require.Equal(t, accountInfoQuery.AccountID.String(), AccountID{Account: 5}._ToProtobuf().String())
   539  
   540  		var payment services.TransactionBody
   541  		require.NotEmpty(t, accountInfoQuery.Header.Payment.BodyBytes)
   542  		err := protobuf.Unmarshal(accountInfoQuery.Header.Payment.BodyBytes, &payment)
   543  		require.NoError(t, err)
   544  
   545  		require.NotNil(t, payment.TransactionID)
   546  		require.Equal(t, payment.TransactionID.AccountID.String(), AccountID{Account: 1800}._ToProtobuf().String())
   547  		require.NotNil(t, payment.NodeAccountID)
   548  		require.Equal(t, payment.NodeAccountID.String(), AccountID{Account: 3}._ToProtobuf().String())
   549  
   550  		require.Equal(t, payment.Data, &services.TransactionBody_CryptoTransfer{
   551  			CryptoTransfer: &services.CryptoTransferTransactionBody{
   552  				Transfers: &services.TransferList{
   553  					AccountAmounts: []*services.AccountAmount{
   554  						{
   555  							AccountID: AccountID{Account: 3}._ToProtobuf(),
   556  							Amount:    HbarFromTinybar(35).AsTinybar(),
   557  						},
   558  						{
   559  							AccountID: AccountID{Account: 1800}._ToProtobuf(),
   560  							Amount:    -HbarFromTinybar(35).AsTinybar(),
   561  						},
   562  					},
   563  				},
   564  			},
   565  		})
   566  
   567  		key, _ := PrivateKeyFromStringEd25519(mockPrivateKey)
   568  
   569  		return &services.Response{
   570  			Response: &services.Response_CryptoGetInfo{
   571  				CryptoGetInfo: &services.CryptoGetInfoResponse{
   572  					Header: &services.ResponseHeader{
   573  						NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK,
   574  						ResponseType:                services.ResponseType_ANSWER_ONLY,
   575  						Cost:                        35,
   576  					},
   577  					AccountInfo: &services.CryptoGetInfoResponse_AccountInfo{
   578  						AccountID:         &services.AccountID{Account: &services.AccountID_AccountNum{5}},
   579  						ContractAccountID: "",
   580  						Deleted:           false,
   581  						ProxyAccountID:    &services.AccountID{Account: &services.AccountID_AccountNum{5}},
   582  						ProxyReceived:     0,
   583  						Key:               key._ToProtoKey(),
   584  						Balance:           0,
   585  					},
   586  				},
   587  			},
   588  		}
   589  	}
   590  
   591  	costCall := func(request *services.Query) *services.Response {
   592  		require.NotNil(t, request.Query)
   593  		accountInfoQuery := request.Query.(*services.Query_CryptoGetInfo).CryptoGetInfo
   594  
   595  		require.Equal(t, accountInfoQuery.Header.ResponseType, services.ResponseType_COST_ANSWER)
   596  
   597  		require.Equal(t, accountInfoQuery.AccountID.String(), AccountID{Account: 5}._ToProtobuf().String())
   598  
   599  		var payment services.TransactionBody
   600  		require.NotEmpty(t, accountInfoQuery.Header.Payment.BodyBytes)
   601  		err := protobuf.Unmarshal(accountInfoQuery.Header.Payment.BodyBytes, &payment)
   602  		require.NoError(t, err)
   603  
   604  		return &services.Response{
   605  			Response: &services.Response_CryptoGetInfo{
   606  				CryptoGetInfo: &services.CryptoGetInfoResponse{
   607  					Header: &services.ResponseHeader{
   608  						NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK,
   609  						ResponseType:                services.ResponseType_COST_ANSWER,
   610  						Cost:                        35,
   611  					},
   612  				},
   613  			},
   614  		}
   615  	}
   616  
   617  	responses := [][]interface{}{{
   618  		costCall, call,
   619  	}}
   620  
   621  	client, server := NewMockClientAndServer(responses)
   622  	defer server.Close()
   623  
   624  	_, err := NewAccountInfoQuery().
   625  		SetNodeAccountIDs([]AccountID{{Account: 3}}).
   626  		SetAccountID(AccountID{Account: 5}).
   627  		Execute(client)
   628  	require.NoError(t, err)
   629  }
   630  
   631  func TestUnitMockAccountInfoQueryNoNodeSet(t *testing.T) {
   632  	t.Skip("Skipping test as it is currently broken with the addition of generating new payment transactions for queries")
   633  	call := func(request *services.Query) *services.Response {
   634  		require.NotNil(t, request.Query)
   635  		accountInfoQuery := request.Query.(*services.Query_CryptoGetInfo).CryptoGetInfo
   636  
   637  		require.Equal(t, accountInfoQuery.AccountID.String(), AccountID{Account: 5}._ToProtobuf().String())
   638  
   639  		var payment services.TransactionBody
   640  		require.NotEmpty(t, accountInfoQuery.Header.Payment.BodyBytes)
   641  		err := protobuf.Unmarshal(accountInfoQuery.Header.Payment.BodyBytes, &payment)
   642  		require.NoError(t, err)
   643  
   644  		require.NotNil(t, payment.TransactionID)
   645  		require.Equal(t, payment.TransactionID.AccountID.String(), AccountID{Account: 1800}._ToProtobuf().String())
   646  		require.NotNil(t, payment.NodeAccountID)
   647  		require.Equal(t, payment.NodeAccountID.String(), AccountID{Account: 3}._ToProtobuf().String())
   648  
   649  		require.Equal(t, payment.Data, &services.TransactionBody_CryptoTransfer{
   650  			CryptoTransfer: &services.CryptoTransferTransactionBody{
   651  				Transfers: &services.TransferList{
   652  					AccountAmounts: []*services.AccountAmount{
   653  						{
   654  							AccountID: AccountID{Account: 3}._ToProtobuf(),
   655  							Amount:    HbarFromTinybar(35).AsTinybar(),
   656  						},
   657  						{
   658  							AccountID: AccountID{Account: 1800}._ToProtobuf(),
   659  							Amount:    -HbarFromTinybar(35).AsTinybar(),
   660  						},
   661  					},
   662  				},
   663  			},
   664  		})
   665  
   666  		key, _ := PrivateKeyFromStringEd25519(mockPrivateKey)
   667  
   668  		return &services.Response{
   669  			Response: &services.Response_CryptoGetInfo{
   670  				CryptoGetInfo: &services.CryptoGetInfoResponse{
   671  					Header: &services.ResponseHeader{
   672  						NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK,
   673  						ResponseType:                services.ResponseType_ANSWER_ONLY,
   674  						Cost:                        35,
   675  					},
   676  					AccountInfo: &services.CryptoGetInfoResponse_AccountInfo{
   677  						AccountID:         &services.AccountID{Account: &services.AccountID_AccountNum{5}},
   678  						ContractAccountID: "",
   679  						Deleted:           false,
   680  						ProxyAccountID:    &services.AccountID{Account: &services.AccountID_AccountNum{5}},
   681  						ProxyReceived:     0,
   682  						Key:               key._ToProtoKey(),
   683  						Balance:           0,
   684  					},
   685  				},
   686  			},
   687  		}
   688  	}
   689  
   690  	costCall := func(request *services.Query) *services.Response {
   691  		require.NotNil(t, request.Query)
   692  		accountInfoQuery := request.Query.(*services.Query_CryptoGetInfo).CryptoGetInfo
   693  
   694  		require.Equal(t, accountInfoQuery.Header.ResponseType, services.ResponseType_COST_ANSWER)
   695  
   696  		require.Equal(t, accountInfoQuery.AccountID.String(), AccountID{Account: 5}._ToProtobuf().String())
   697  
   698  		var payment services.TransactionBody
   699  		require.NotEmpty(t, accountInfoQuery.Header.Payment.BodyBytes)
   700  		err := protobuf.Unmarshal(accountInfoQuery.Header.Payment.BodyBytes, &payment)
   701  		require.NoError(t, err)
   702  
   703  		return &services.Response{
   704  			Response: &services.Response_CryptoGetInfo{
   705  				CryptoGetInfo: &services.CryptoGetInfoResponse{
   706  					Header: &services.ResponseHeader{
   707  						NodeTransactionPrecheckCode: services.ResponseCodeEnum_OK,
   708  						ResponseType:                services.ResponseType_COST_ANSWER,
   709  						Cost:                        35,
   710  					},
   711  				},
   712  			},
   713  		}
   714  	}
   715  
   716  	responses := [][]interface{}{{
   717  		costCall, call,
   718  	}}
   719  
   720  	client, server := NewMockClientAndServer(responses)
   721  	defer server.Close()
   722  
   723  	_, err := NewAccountInfoQuery().
   724  		SetAccountID(AccountID{Account: 5}).
   725  		Execute(client)
   726  	require.NoError(t, err)
   727  }
   728  
   729  func NewMockHandler(responses []interface{}) func(interface{}, context.Context, func(interface{}) error, grpc.UnaryServerInterceptor) (interface{}, error) {
   730  	index := 0
   731  	return func(_srv interface{}, _ctx context.Context, dec func(interface{}) error, _interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
   732  		if index >= len(responses) {
   733  			return nil, status.New(codes.Aborted, "No response found").Err()
   734  		}
   735  		response := responses[index]
   736  		index = index + 1
   737  
   738  		switch response := response.(type) {
   739  		case error:
   740  			return nil, response
   741  		case *services.TransactionResponse:
   742  			return response, nil
   743  		case *services.Response:
   744  			return response, nil
   745  		case *services.NodeAddress:
   746  			return response, nil
   747  		case func(request *services.Transaction) *services.TransactionResponse:
   748  			request := new(services.Transaction)
   749  			if err := dec(request); err != nil {
   750  				return nil, err
   751  			}
   752  			return response(request), nil
   753  		case func(request *services.Query) *services.Response:
   754  			request := new(services.Query)
   755  			if err := dec(request); err != nil {
   756  				return nil, err
   757  			}
   758  			return response(request), nil
   759  		case func(request *services.Query) *services.NodeAddress:
   760  			request := new(services.Query)
   761  			if err := dec(request); err != nil {
   762  				return nil, err
   763  			}
   764  			return response(request), nil
   765  		default:
   766  			return response, nil
   767  		}
   768  	}
   769  }
   770  
   771  func NewMockStreamHandler(responses []interface{}) func(interface{}, grpc.ServerStream) error {
   772  	return func(_ interface{}, stream grpc.ServerStream) error {
   773  		for _, resp := range responses {
   774  			err := stream.SendMsg(resp)
   775  			if err != nil {
   776  				return err
   777  			}
   778  		}
   779  
   780  		return nil
   781  	}
   782  }
   783  
   784  type MockServer struct {
   785  	listener net.Listener
   786  	server   *grpc.Server
   787  }
   788  
   789  func NewMockServer(responses []interface{}) (server *MockServer) {
   790  	var err error
   791  	server = &MockServer{
   792  		server: grpc.NewServer(),
   793  	}
   794  	handler := NewMockHandler(responses)
   795  	streamHandler := NewMockStreamHandler(responses)
   796  
   797  	server.server.RegisterService(NewServiceDescription(handler, &services.CryptoService_ServiceDesc), nil)
   798  	server.server.RegisterService(NewServiceDescription(handler, &services.FileService_ServiceDesc), nil)
   799  	server.server.RegisterService(NewServiceDescription(handler, &services.SmartContractService_ServiceDesc), nil)
   800  	server.server.RegisterService(NewServiceDescription(handler, &services.ConsensusService_ServiceDesc), nil)
   801  	server.server.RegisterService(NewServiceDescription(handler, &services.TokenService_ServiceDesc), nil)
   802  	server.server.RegisterService(NewServiceDescription(handler, &services.ScheduleService_ServiceDesc), nil)
   803  	server.server.RegisterService(NewServiceDescription(handler, &services.FreezeService_ServiceDesc), nil)
   804  	server.server.RegisterService(NewServiceDescription(handler, &services.NetworkService_ServiceDesc), nil)
   805  	server.server.RegisterService(NewServiceDescription(handler, &services.AddressBookService_ServiceDesc), nil)
   806  	server.server.RegisterService(NewMirrorServiceDescription(streamHandler, &mirror.NetworkService_ServiceDesc), nil)
   807  
   808  	server.listener, err = net.Listen("tcp", "localhost:0")
   809  	if err != nil {
   810  		panic(err)
   811  	}
   812  
   813  	go func() {
   814  		if err = server.server.Serve(server.listener); err != nil {
   815  			panic(err)
   816  		}
   817  	}()
   818  
   819  	return server
   820  }
   821  
   822  func (server *MockServer) Close() {
   823  	if server.server != nil {
   824  		server.server.GracefulStop()
   825  	}
   826  }
   827  
   828  func NewServiceDescription(handler func(interface{}, context.Context, func(interface{}) error, grpc.UnaryServerInterceptor) (interface{}, error), service *grpc.ServiceDesc) *grpc.ServiceDesc {
   829  	var methods []grpc.MethodDesc
   830  	for _, desc := range service.Methods {
   831  		methods = append(methods, grpc.MethodDesc{
   832  			MethodName: desc.MethodName,
   833  			Handler:    handler,
   834  		})
   835  	}
   836  
   837  	return &grpc.ServiceDesc{
   838  		ServiceName: service.ServiceName,
   839  		HandlerType: service.HandlerType,
   840  		Methods:     methods,
   841  		Streams:     []grpc.StreamDesc{},
   842  		Metadata:    service.Metadata,
   843  	}
   844  }
   845  
   846  func NewMirrorServiceDescription(handler func(interface{}, grpc.ServerStream) error, service *grpc.ServiceDesc) *grpc.ServiceDesc {
   847  	var streams []grpc.StreamDesc
   848  	for _, stream := range service.Streams {
   849  		streams = append(streams, grpc.StreamDesc{
   850  			StreamName:    stream.StreamName,
   851  			Handler:       handler,
   852  			ServerStreams: stream.ServerStreams,
   853  			ClientStreams: stream.ClientStreams,
   854  		})
   855  	}
   856  
   857  	return &grpc.ServiceDesc{
   858  		ServiceName: service.ServiceName,
   859  		HandlerType: service.HandlerType,
   860  		Methods:     []grpc.MethodDesc{},
   861  		Streams:     streams,
   862  		Metadata:    service.Metadata,
   863  	}
   864  }