code.vegaprotocol.io/vega@v0.79.0/datanode/api/trading_test.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  package api_test
    17  
    18  import (
    19  	"context"
    20  	"fmt"
    21  	"net"
    22  	"testing"
    23  	"time"
    24  
    25  	"code.vegaprotocol.io/vega/datanode/api"
    26  	"code.vegaprotocol.io/vega/datanode/api/mocks"
    27  	"code.vegaprotocol.io/vega/datanode/broker"
    28  	"code.vegaprotocol.io/vega/datanode/candlesv2"
    29  	"code.vegaprotocol.io/vega/datanode/config"
    30  	vgtesting "code.vegaprotocol.io/vega/datanode/libs/testing"
    31  	"code.vegaprotocol.io/vega/datanode/service"
    32  	"code.vegaprotocol.io/vega/datanode/sqlstore"
    33  	"code.vegaprotocol.io/vega/datanode/sqlsubscribers"
    34  	"code.vegaprotocol.io/vega/libs/subscribers"
    35  	"code.vegaprotocol.io/vega/logging"
    36  	v2 "code.vegaprotocol.io/vega/protos/data-node/api/v2"
    37  	vegaprotoapi "code.vegaprotocol.io/vega/protos/vega/api/v1"
    38  	commandspb "code.vegaprotocol.io/vega/protos/vega/commands/v1"
    39  
    40  	"github.com/golang/mock/gomock"
    41  	"github.com/golang/protobuf/proto"
    42  	"github.com/pkg/errors"
    43  	"github.com/stretchr/testify/assert"
    44  	"google.golang.org/grpc"
    45  	"google.golang.org/grpc/test/bufconn"
    46  )
    47  
    48  const connBufSize = 1024 * 1024
    49  
    50  func waitForNode(ctx context.Context, t *testing.T, conn *grpc.ClientConn) {
    51  	t.Helper()
    52  	const maxSleep = 2000 // milliseconds
    53  
    54  	c := v2.NewTradingDataServiceClient(conn)
    55  
    56  	sleepTime := 10 // milliseconds
    57  	for sleepTime < maxSleep {
    58  		_, err := c.Ping(ctx, &v2.PingRequest{})
    59  		if err == nil {
    60  			return
    61  		}
    62  
    63  		time.Sleep(time.Duration(sleepTime) * time.Millisecond)
    64  		sleepTime *= 2
    65  	}
    66  	if sleepTime >= maxSleep {
    67  		t.Fatalf("Gave up waiting for gRPC server to respond properly.")
    68  	}
    69  }
    70  
    71  func getTestGRPCServer(t *testing.T, ctx context.Context) (tidy func(), conn *grpc.ClientConn, mockCoreServiceClient *mocks.MockCoreServiceClient, err error) {
    72  	t.Helper()
    73  	_, cleanupFn := vgtesting.NewVegaPaths()
    74  
    75  	conf := config.NewDefaultConfig()
    76  	conf.API.IP = "127.0.0.1"
    77  	conf.API.Port = 64201
    78  
    79  	// Mock BlockchainClient
    80  	mockCtrl := gomock.NewController(t)
    81  
    82  	mockCoreServiceClient = mocks.NewMockCoreServiceClient(mockCtrl)
    83  
    84  	mockNetworkHistoryService := mocks.NewMockNetworkHistoryService(mockCtrl)
    85  
    86  	rawEventSource, err := broker.NewEventReceiverSender(conf.Broker, logging.NewTestLogger(), "")
    87  	if err != nil {
    88  		t.Fatalf("failed to create raw event source: %v", err)
    89  	}
    90  
    91  	eventSource := broker.NewDeserializer(rawEventSource)
    92  	if err != nil {
    93  		t.Fatalf("failed to create event source: %v", err)
    94  	}
    95  
    96  	conf.CandlesV2.CandleStore.DefaultCandleIntervals = ""
    97  
    98  	sqlConn := &sqlstore.ConnectionSource{}
    99  	sqlConn.ToggleTest() // ensure calls to query and copyTo do not fail
   100  
   101  	bro, err := broker.New(ctx, logging.NewTestLogger(), conf.Broker, "", eventSource)
   102  	if err != nil {
   103  		err = errors.Wrap(err, "failed to create broker")
   104  		return
   105  	}
   106  
   107  	logger := logging.NewTestLogger()
   108  	eventService := subscribers.NewService(logger, bro, conf.Broker.EventBusClientBufferSize)
   109  	sqlOrderStore := sqlstore.NewOrders(sqlConn)
   110  	sqlOrderService := service.NewOrder(sqlOrderStore, logger)
   111  	sqlNetworkLimitsService := service.NewNetworkLimits(sqlstore.NewNetworkLimits(sqlConn))
   112  	sqlMarketDataService := service.NewMarketData(sqlstore.NewMarketData(sqlConn), logger)
   113  	sqlCandleStore := sqlstore.NewCandles(ctx, sqlConn, conf.CandlesV2.CandleStore)
   114  	sqlCandlesService := candlesv2.NewService(ctx, logger, conf.CandlesV2, sqlCandleStore)
   115  	sqlTradeService := service.NewTrade(sqlstore.NewTrades(sqlConn), logger)
   116  	sqlPositionService := service.NewPosition(sqlstore.NewPositions(sqlConn), logger)
   117  	sqlAssetService := service.NewAsset(sqlstore.NewAssets(sqlConn))
   118  	sqlAccountService := service.NewAccount(sqlstore.NewAccounts(sqlConn), sqlstore.NewBalances(sqlConn), logger)
   119  	sqlRewardsService := service.NewReward(sqlstore.NewRewards(ctx, sqlConn), logger)
   120  	sqlMarketsService := service.NewMarkets(sqlstore.NewMarkets(sqlConn))
   121  	sqlDelegationService := service.NewDelegation(sqlstore.NewDelegations(sqlConn), logger)
   122  	sqlEpochService := service.NewEpoch(sqlstore.NewEpochs(sqlConn))
   123  	sqlDepositService := service.NewDeposit(sqlstore.NewDeposits(sqlConn))
   124  	sqlWithdrawalService := service.NewWithdrawal(sqlstore.NewWithdrawals(sqlConn))
   125  	sqlGovernanceService := service.NewGovernance(sqlstore.NewProposals(sqlConn), sqlstore.NewVotes(sqlConn), logger)
   126  	sqlRiskFactorsService := service.NewRiskFactor(sqlstore.NewRiskFactors(sqlConn))
   127  	sqlMarginLevelsService := service.NewRisk(sqlstore.NewMarginLevels(sqlConn), sqlAccountService, logger)
   128  	sqlNetParamService := service.NewNetworkParameter(sqlstore.NewNetworkParameters(sqlConn))
   129  	sqlBlockService := service.NewBlock(sqlstore.NewBlocks(sqlConn))
   130  	sqlCheckpointService := service.NewCheckpoint(sqlstore.NewCheckpoints(sqlConn))
   131  	sqlPartyService := service.NewParty(sqlstore.NewParties(sqlConn))
   132  	sqlOracleSpecService := service.NewOracleSpec(sqlstore.NewOracleSpec(sqlConn))
   133  	sqlOracleDataService := service.NewOracleData(sqlstore.NewOracleData(sqlConn))
   134  	sqlLPDataService := service.NewLiquidityProvision(sqlstore.NewLiquidityProvision(sqlConn, logger))
   135  	sqlTransferService := service.NewTransfer(sqlstore.NewTransfers(sqlConn))
   136  	sqlStakeLinkingService := service.NewStakeLinking(sqlstore.NewStakeLinking(sqlConn))
   137  	sqlNotaryService := service.NewNotary(sqlstore.NewNotary(sqlConn))
   138  	sqlMultiSigService := service.NewMultiSig(sqlstore.NewERC20MultiSigSignerEvent(sqlConn))
   139  	sqlKeyRotationsService := service.NewKeyRotations(sqlstore.NewKeyRotations(sqlConn))
   140  	sqlEthereumKeyRotationService := service.NewEthereumKeyRotation(sqlstore.NewEthereumKeyRotations(sqlConn), logger)
   141  	sqlNodeService := service.NewNode(sqlstore.NewNode(sqlConn))
   142  	sqlLedgerService := service.NewLedger(sqlstore.NewLedger(sqlConn), logger)
   143  	sqlProtocolUpgradeService := service.NewProtocolUpgrade(sqlstore.NewProtocolUpgradeProposals(sqlConn), logger)
   144  	sqlCoreSnapshotService := service.NewSnapshotData(sqlstore.NewCoreSnapshotData(sqlConn))
   145  	stopOrderService := service.NewStopOrders(sqlstore.NewStopOrders(sqlConn))
   146  	fundingPeriodService := service.NewFundingPeriods(sqlstore.NewFundingPeriods(sqlConn))
   147  	partyActivityStreak := service.NewPartyActivityStreak(sqlstore.NewPartyActivityStreaks(sqlConn))
   148  	referralProgramService := service.NewReferralPrograms(sqlstore.NewReferralPrograms(sqlConn))
   149  	referralSetsService := service.NewReferralSets(sqlstore.NewReferralSets(sqlConn))
   150  	teamsService := service.NewTeams(sqlstore.NewTeams(sqlConn))
   151  	vestingStatsService := service.NewVestingStats(sqlstore.NewVestingStats(sqlConn))
   152  	FeesStatsService := service.NewFeesStats(sqlstore.NewFeesStats(sqlConn))
   153  	fundingPaymentService := service.NewFundingPayment(sqlstore.NewFundingPayments(sqlConn))
   154  	volumeDiscountStatsService := service.NewVolumeDiscountStats(sqlstore.NewVolumeDiscountStats(sqlConn))
   155  	volumeDiscountProgramService := service.NewVolumeDiscountPrograms(sqlstore.NewVolumeDiscountPrograms(sqlConn))
   156  	paidLiquidityFeesStatsService := service.NewPaidLiquidityFeesStats(sqlstore.NewPaidLiquidityFeesStats(sqlConn))
   157  	partyLockedBalances := service.NewPartyLockedBalances(sqlstore.NewPartyLockedBalances(sqlConn))
   158  	partyVestingBalances := service.NewPartyVestingBalances(sqlstore.NewPartyVestingBalances(sqlConn))
   159  	transactionResults := service.NewTransactionResults(sqlsubscribers.NewTransactionResults(logger))
   160  	gameService := service.NewGames(sqlstore.NewGames(sqlConn))
   161  	marginModesService := service.NewMarginModes(sqlstore.NewMarginModes(sqlConn))
   162  	timeWeightedNotionPositionService := service.NewTimeWeightedNotionalPosition(sqlstore.NewTimeWeightedNotionalPosition(sqlConn))
   163  	gameScoreService := service.NewGameScore(sqlstore.NewGameScores(sqlConn), logger)
   164  	ammPoolsService := service.NewAMMPools(sqlstore.NewAMMPools(sqlConn))
   165  	sqlMarketDepthService := service.NewMarketDepth(service.NewDefaultConfig().MarketDepth, sqlOrderService, ammPoolsService, nil, nil, nil, nil, logger)
   166  	volumeRebateStatsService := service.NewVolumeRebateStats(sqlstore.NewVolumeRebateStats(sqlConn))
   167  	volumeRebateProgramssService := service.NewVolumeRebatePrograms(sqlstore.NewVolumeRebatePrograms(sqlConn))
   168  
   169  	g := api.NewGRPCServer(
   170  		logger,
   171  		conf.API,
   172  		mockCoreServiceClient,
   173  		eventService,
   174  		sqlOrderService,
   175  		sqlNetworkLimitsService,
   176  		sqlMarketDataService,
   177  		sqlTradeService,
   178  		sqlAssetService,
   179  		sqlAccountService,
   180  		sqlRewardsService,
   181  		sqlMarketsService,
   182  		sqlDelegationService,
   183  		sqlEpochService,
   184  		sqlDepositService,
   185  		sqlWithdrawalService,
   186  		sqlGovernanceService,
   187  		sqlRiskFactorsService,
   188  		sqlMarginLevelsService,
   189  		sqlNetParamService,
   190  		sqlBlockService,
   191  		sqlCheckpointService,
   192  		sqlPartyService,
   193  		sqlCandlesService,
   194  		sqlOracleSpecService,
   195  		sqlOracleDataService,
   196  		sqlLPDataService,
   197  		sqlPositionService,
   198  		sqlTransferService,
   199  		sqlStakeLinkingService,
   200  		sqlNotaryService,
   201  		sqlMultiSigService,
   202  		sqlKeyRotationsService,
   203  		sqlEthereumKeyRotationService,
   204  		sqlNodeService,
   205  		sqlMarketDepthService,
   206  		sqlLedgerService,
   207  		sqlProtocolUpgradeService,
   208  		mockNetworkHistoryService,
   209  		sqlCoreSnapshotService,
   210  		stopOrderService,
   211  		fundingPeriodService,
   212  		partyActivityStreak,
   213  		referralProgramService,
   214  		referralSetsService,
   215  		teamsService,
   216  		vestingStatsService,
   217  		FeesStatsService,
   218  		fundingPaymentService,
   219  		volumeDiscountStatsService,
   220  		volumeDiscountProgramService,
   221  		paidLiquidityFeesStatsService,
   222  		partyLockedBalances,
   223  		partyVestingBalances,
   224  		transactionResults,
   225  		gameService,
   226  		marginModesService,
   227  		timeWeightedNotionPositionService,
   228  		gameScoreService,
   229  		ammPoolsService,
   230  		volumeRebateStatsService,
   231  		volumeRebateProgramssService,
   232  	)
   233  	if g == nil {
   234  		err = fmt.Errorf("failed to create gRPC server")
   235  		return
   236  	}
   237  
   238  	tidy = func() {
   239  		cleanupFn()
   240  	}
   241  
   242  	lis := bufconn.Listen(connBufSize)
   243  	ctxDialer := func(context.Context, string) (net.Conn, error) { return lis.Dial() }
   244  
   245  	// Start the gRPC server, then wait for it to be ready.
   246  	go func() {
   247  		_ = g.Start(ctx, lis)
   248  	}()
   249  
   250  	conn, err = grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(ctxDialer), grpc.WithInsecure())
   251  	if err != nil {
   252  		t.Fatalf("Failed to create connection to gRPC server")
   253  	}
   254  
   255  	waitForNode(ctx, t, conn)
   256  
   257  	return tidy, conn, mockCoreServiceClient, err
   258  }
   259  
   260  func TestSubmitTransaction(t *testing.T) {
   261  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   262  	defer cancel()
   263  
   264  	t.Run("proxy call is successful", func(t *testing.T) {
   265  		tidy, conn, mockTradingServiceClient, err := getTestGRPCServer(t, ctx)
   266  		if err != nil {
   267  			t.Fatalf("Failed to get test gRPC server: %s", err.Error())
   268  		}
   269  		defer tidy()
   270  
   271  		req := &vegaprotoapi.SubmitTransactionRequest{
   272  			Type: vegaprotoapi.SubmitTransactionRequest_TYPE_UNSPECIFIED,
   273  			Tx: &commandspb.Transaction{
   274  				InputData: []byte("input data"),
   275  				Signature: &commandspb.Signature{
   276  					Value:   "value",
   277  					Algo:    "algo",
   278  					Version: 1,
   279  				},
   280  			},
   281  		}
   282  
   283  		expectedRes := &vegaprotoapi.SubmitTransactionResponse{Success: true}
   284  
   285  		vegaReq := &vegaprotoapi.SubmitTransactionRequest{
   286  			Type: vegaprotoapi.SubmitTransactionRequest_TYPE_UNSPECIFIED,
   287  			Tx: &commandspb.Transaction{
   288  				InputData: []byte("input data"),
   289  				Signature: &commandspb.Signature{
   290  					Value:   "value",
   291  					Algo:    "algo",
   292  					Version: 1,
   293  				},
   294  			},
   295  		}
   296  
   297  		mockTradingServiceClient.EXPECT().
   298  			SubmitTransaction(gomock.Any(), vgtesting.ProtosEq(vegaReq)).
   299  			Return(&vegaprotoapi.SubmitTransactionResponse{Success: true}, nil).Times(1)
   300  
   301  		proxyClient := vegaprotoapi.NewCoreServiceClient(conn)
   302  		assert.NotNil(t, proxyClient)
   303  
   304  		actualResp, err := proxyClient.SubmitTransaction(ctx, req)
   305  		assert.NoError(t, err)
   306  		vgtesting.AssertProtoEqual(t, expectedRes, actualResp)
   307  	})
   308  
   309  	t.Run("proxy propagates an error", func(t *testing.T) {
   310  		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   311  		defer cancel()
   312  
   313  		tidy, conn, mockTradingServiceClient, err := getTestGRPCServer(t, ctx)
   314  		if err != nil {
   315  			t.Fatalf("Failed to get test gRPC server: %s", err.Error())
   316  		}
   317  		defer tidy()
   318  
   319  		req := &vegaprotoapi.SubmitTransactionRequest{
   320  			Type: vegaprotoapi.SubmitTransactionRequest_TYPE_COMMIT,
   321  			Tx: &commandspb.Transaction{
   322  				InputData: []byte("input data"),
   323  				Signature: &commandspb.Signature{
   324  					Value:   "value",
   325  					Algo:    "algo",
   326  					Version: 1,
   327  				},
   328  			},
   329  		}
   330  
   331  		vegaReq := &vegaprotoapi.SubmitTransactionRequest{
   332  			Type: vegaprotoapi.SubmitTransactionRequest_TYPE_COMMIT,
   333  			Tx: &commandspb.Transaction{
   334  				InputData: []byte("input data"),
   335  				Signature: &commandspb.Signature{
   336  					Value:   "value",
   337  					Algo:    "algo",
   338  					Version: 1,
   339  				},
   340  			},
   341  		}
   342  
   343  		mockTradingServiceClient.EXPECT().
   344  			SubmitTransaction(gomock.Any(), vgtesting.ProtosEq(vegaReq)).
   345  			Return(nil, errors.New("Critical error"))
   346  
   347  		proxyClient := vegaprotoapi.NewCoreServiceClient(conn)
   348  		assert.NotNil(t, proxyClient)
   349  
   350  		actualResp, err := proxyClient.SubmitTransaction(ctx, req)
   351  		assert.Error(t, err)
   352  		assert.Nil(t, actualResp)
   353  		assert.Contains(t, err.Error(), "Critical error")
   354  	})
   355  }
   356  
   357  func TestSubmitRawTransaction(t *testing.T) {
   358  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   359  	defer cancel()
   360  
   361  	t.Run("proxy call is successful", func(t *testing.T) {
   362  		tidy, conn, mockTradingServiceClient, err := getTestGRPCServer(t, ctx)
   363  		if err != nil {
   364  			t.Fatalf("Failed to get test gRPC server: %s", err.Error())
   365  		}
   366  		defer tidy()
   367  
   368  		tx := &commandspb.Transaction{
   369  			InputData: []byte("input data"),
   370  			Signature: &commandspb.Signature{
   371  				Value:   "value",
   372  				Algo:    "algo",
   373  				Version: 1,
   374  			},
   375  		}
   376  
   377  		bs, err := proto.Marshal(tx)
   378  		assert.NoError(t, err)
   379  
   380  		req := &vegaprotoapi.SubmitRawTransactionRequest{
   381  			Type: vegaprotoapi.SubmitRawTransactionRequest_TYPE_UNSPECIFIED,
   382  			Tx:   bs,
   383  		}
   384  
   385  		expectedRes := &vegaprotoapi.SubmitRawTransactionResponse{Success: true}
   386  
   387  		vegaReq := &vegaprotoapi.SubmitRawTransactionRequest{
   388  			Type: vegaprotoapi.SubmitRawTransactionRequest_TYPE_UNSPECIFIED,
   389  			Tx:   bs,
   390  		}
   391  
   392  		mockTradingServiceClient.EXPECT().
   393  			SubmitRawTransaction(gomock.Any(), vgtesting.ProtosEq(vegaReq)).
   394  			Return(&vegaprotoapi.SubmitRawTransactionResponse{Success: true}, nil).Times(1)
   395  
   396  		proxyClient := vegaprotoapi.NewCoreServiceClient(conn)
   397  		assert.NotNil(t, proxyClient)
   398  
   399  		actualResp, err := proxyClient.SubmitRawTransaction(ctx, req)
   400  		assert.NoError(t, err)
   401  		vgtesting.AssertProtoEqual(t, expectedRes, actualResp)
   402  	})
   403  
   404  	t.Run("proxy propagates an error", func(t *testing.T) {
   405  		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   406  		defer cancel()
   407  
   408  		tidy, conn, mockTradingServiceClient, err := getTestGRPCServer(t, ctx)
   409  		if err != nil {
   410  			t.Fatalf("Failed to get test gRPC server: %s", err.Error())
   411  		}
   412  		defer tidy()
   413  		tx := &commandspb.Transaction{
   414  			InputData: []byte("input data"),
   415  			Signature: &commandspb.Signature{
   416  				Value:   "value",
   417  				Algo:    "algo",
   418  				Version: 1,
   419  			},
   420  		}
   421  
   422  		bs, err := proto.Marshal(tx)
   423  		assert.NoError(t, err)
   424  
   425  		req := &vegaprotoapi.SubmitRawTransactionRequest{
   426  			Type: vegaprotoapi.SubmitRawTransactionRequest_TYPE_COMMIT,
   427  			Tx:   bs,
   428  		}
   429  
   430  		vegaReq := &vegaprotoapi.SubmitRawTransactionRequest{
   431  			Type: vegaprotoapi.SubmitRawTransactionRequest_TYPE_COMMIT,
   432  			Tx:   bs,
   433  		}
   434  
   435  		mockTradingServiceClient.EXPECT().
   436  			SubmitRawTransaction(gomock.Any(), vgtesting.ProtosEq(vegaReq)).
   437  			Return(nil, errors.New("Critical error"))
   438  
   439  		proxyClient := vegaprotoapi.NewCoreServiceClient(conn)
   440  		assert.NotNil(t, proxyClient)
   441  
   442  		actualResp, err := proxyClient.SubmitRawTransaction(ctx, req)
   443  		assert.Error(t, err)
   444  		assert.Nil(t, actualResp)
   445  		assert.Contains(t, err.Error(), "Critical error")
   446  	})
   447  }
   448  
   449  func TestLastBlockHeight(t *testing.T) {
   450  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
   451  	defer cancel()
   452  
   453  	t.Run("proxy call is successful", func(t *testing.T) {
   454  		tidy, conn, mockTradingServiceClient, err := getTestGRPCServer(t, ctx)
   455  		if err != nil {
   456  			t.Fatalf("Failed to get test gRPC server: %s", err.Error())
   457  		}
   458  		defer tidy()
   459  
   460  		req := &vegaprotoapi.LastBlockHeightRequest{}
   461  		expectedRes := &vegaprotoapi.LastBlockHeightResponse{Height: 20}
   462  
   463  		vegaReq := &vegaprotoapi.LastBlockHeightRequest{}
   464  
   465  		mockTradingServiceClient.EXPECT().
   466  			LastBlockHeight(gomock.Any(), vgtesting.ProtosEq(vegaReq)).
   467  			Return(&vegaprotoapi.LastBlockHeightResponse{Height: 20}, nil).Times(1)
   468  
   469  		proxyClient := vegaprotoapi.NewCoreServiceClient(conn)
   470  		assert.NotNil(t, proxyClient)
   471  
   472  		actualResp, err := proxyClient.LastBlockHeight(ctx, req)
   473  		assert.NoError(t, err)
   474  		vgtesting.AssertProtoEqual(t, expectedRes, actualResp)
   475  	})
   476  
   477  	t.Run("proxy propagates an error", func(t *testing.T) {
   478  		tidy, conn, mockTradingServiceClient, err := getTestGRPCServer(t, ctx)
   479  		if err != nil {
   480  			t.Fatalf("Failed to get test gRPC server: %s", err.Error())
   481  		}
   482  		defer tidy()
   483  
   484  		req := &vegaprotoapi.LastBlockHeightRequest{}
   485  		vegaReq := &vegaprotoapi.LastBlockHeightRequest{}
   486  
   487  		mockTradingServiceClient.EXPECT().
   488  			LastBlockHeight(gomock.Any(), vgtesting.ProtosEq(vegaReq)).
   489  			Return(nil, fmt.Errorf("Critical error")).Times(1)
   490  
   491  		proxyClient := vegaprotoapi.NewCoreServiceClient(conn)
   492  		assert.NotNil(t, proxyClient)
   493  
   494  		actualResp, err := proxyClient.LastBlockHeight(ctx, req)
   495  		assert.Error(t, err)
   496  		assert.Nil(t, actualResp)
   497  		assert.Contains(t, err.Error(), "Critical error")
   498  	})
   499  }
   500  
   501  func TestGetSpamStatistics(t *testing.T) {
   502  	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
   503  	defer cancel()
   504  
   505  	t.Run("proxy call is successful", func(t *testing.T) {
   506  		tidy, conn, mockTradingServiceClient, err := getTestGRPCServer(t, ctx)
   507  		if err != nil {
   508  			t.Fatalf("failed to get test gRPC server: %v", err)
   509  		}
   510  		defer tidy()
   511  
   512  		req := &vegaprotoapi.GetSpamStatisticsRequest{
   513  			PartyId: "DEADBEEF",
   514  		}
   515  
   516  		wantReq := &vegaprotoapi.GetSpamStatisticsRequest{
   517  			PartyId: "DEADBEEF",
   518  		}
   519  
   520  		wantResp := &vegaprotoapi.GetSpamStatisticsResponse{
   521  			Statistics: &vegaprotoapi.SpamStatistics{
   522  				Proposals:         nil,
   523  				Delegations:       nil,
   524  				Transfers:         nil,
   525  				NodeAnnouncements: nil,
   526  				Votes:             nil,
   527  			},
   528  		}
   529  
   530  		mockTradingServiceClient.EXPECT().
   531  			GetSpamStatistics(gomock.Any(), vgtesting.ProtosEq(wantReq)).
   532  			Return(&vegaprotoapi.GetSpamStatisticsResponse{
   533  				Statistics: &vegaprotoapi.SpamStatistics{
   534  					Proposals:         nil,
   535  					Delegations:       nil,
   536  					Transfers:         nil,
   537  					NodeAnnouncements: nil,
   538  					Votes:             nil,
   539  				},
   540  			}, nil).Times(1)
   541  
   542  		proxyClient := vegaprotoapi.NewCoreServiceClient(conn)
   543  		assert.NotNil(t, proxyClient)
   544  
   545  		resp, err := proxyClient.GetSpamStatistics(ctx, req)
   546  		assert.NoError(t, err)
   547  		vgtesting.AssertProtoEqual(t, wantResp, resp)
   548  	})
   549  
   550  	t.Run("proxy propagates an error", func(t *testing.T) {
   551  		tidy, conn, mockTradingServiceClient, err := getTestGRPCServer(t, ctx)
   552  		if err != nil {
   553  			t.Fatalf("failed to get test gRPC server: %v", err)
   554  		}
   555  		defer tidy()
   556  
   557  		req := &vegaprotoapi.GetSpamStatisticsRequest{
   558  			PartyId: "DEADBEEF",
   559  		}
   560  
   561  		wantReq := &vegaprotoapi.GetSpamStatisticsRequest{
   562  			PartyId: "DEADBEEF",
   563  		}
   564  
   565  		mockTradingServiceClient.EXPECT().
   566  			GetSpamStatistics(gomock.Any(), vgtesting.ProtosEq(wantReq)).
   567  			Return(nil, fmt.Errorf("Critical error")).Times(1)
   568  
   569  		proxyClient := vegaprotoapi.NewCoreServiceClient(conn)
   570  		assert.NotNil(t, proxyClient)
   571  
   572  		resp, err := proxyClient.GetSpamStatistics(ctx, req)
   573  		assert.Error(t, err)
   574  		assert.Nil(t, resp)
   575  		assert.Contains(t, err.Error(), "Critical error")
   576  	})
   577  }