code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/transfers_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 sqlstore_test
    17  
    18  import (
    19  	"testing"
    20  	"time"
    21  
    22  	"code.vegaprotocol.io/vega/datanode/entities"
    23  	"code.vegaprotocol.io/vega/datanode/sqlstore"
    24  	"code.vegaprotocol.io/vega/libs/ptr"
    25  	vegapb "code.vegaprotocol.io/vega/protos/vega"
    26  	eventspb "code.vegaprotocol.io/vega/protos/vega/events/v1"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  	"github.com/stretchr/testify/require"
    30  )
    31  
    32  func TestGetTransferByID(t *testing.T) {
    33  	ctx := tempTransaction(t)
    34  
    35  	blocksStore := sqlstore.NewBlocks(connectionSource)
    36  	assetsStore := sqlstore.NewAssets(connectionSource)
    37  	accountsStore := sqlstore.NewAccounts(connectionSource)
    38  	transfersStore := sqlstore.NewTransfers(connectionSource)
    39  
    40  	block := addTestBlockForTime(t, ctx, blocksStore, time.Now())
    41  
    42  	asset := CreateAsset(t, ctx, assetsStore, block)
    43  
    44  	account1 := CreateAccount(t, ctx, accountsStore, block,
    45  		AccountForAsset(asset),
    46  	)
    47  	account2 := CreateAccount(t, ctx, accountsStore, block,
    48  		AccountWithType(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
    49  		AccountForAsset(asset),
    50  	)
    51  
    52  	transfer := NewTransfer(t, ctx, accountsStore, block,
    53  		TransferWithAsset(asset),
    54  		TransferFromToAccounts(account1, account2),
    55  		TransferAsRecurring(&eventspb.RecurringTransfer{
    56  			StartEpoch: 10,
    57  			EndEpoch:   nil,
    58  			Factor:     "0.1",
    59  		}),
    60  	)
    61  
    62  	transferUpdateFromSameTx := NewTransfer(t, ctx, accountsStore, block,
    63  		TransferWithID(transfer.ID),
    64  		TransferWithAsset(asset),
    65  		TransferFromToAccounts(account1, account2),
    66  		TransferAsRecurring(&eventspb.RecurringTransfer{
    67  			StartEpoch: 15,
    68  			EndEpoch:   nil,
    69  			Factor:     "0.15",
    70  		}),
    71  	)
    72  	transferUpdateFromSameTx.TxHash = transfer.TxHash
    73  
    74  	transferUpdateFromDifferentTx := NewTransfer(t, ctx, accountsStore, block,
    75  		TransferWithID(transfer.ID),
    76  		TransferWithAsset(asset),
    77  		TransferFromToAccounts(account1, account2),
    78  		TransferAsRecurring(&eventspb.RecurringTransfer{
    79  			StartEpoch: 20,
    80  			EndEpoch:   ptr.From(uint64(25)),
    81  			Factor:     "0.2",
    82  		}),
    83  	)
    84  
    85  	// Ensure we have different transfers so the test is meaningful.
    86  	RequireAllDifferent(t, transfer, transferUpdateFromSameTx, transferUpdateFromDifferentTx)
    87  
    88  	t.Run("Save transfers", func(t *testing.T) {
    89  		require.NoError(t, transfersStore.Upsert(ctx, transfer))
    90  		require.NoError(t, transfersStore.Upsert(ctx, transferUpdateFromSameTx))
    91  		require.NoError(t, transfersStore.Upsert(ctx, transferUpdateFromDifferentTx))
    92  	})
    93  
    94  	t.Run("Retrieve the transfer by ID returns the latest version", func(t *testing.T) {
    95  		retrieved, err := transfersStore.GetByID(ctx, transfer.ID.String())
    96  		require.NoError(t, err)
    97  		assert.Equal(t, *transferUpdateFromDifferentTx, retrieved.Transfer)
    98  	})
    99  }
   100  
   101  func TestGetTransfersByHash(t *testing.T) {
   102  	ctx := tempTransaction(t)
   103  
   104  	blocksStore := sqlstore.NewBlocks(connectionSource)
   105  	assetsStore := sqlstore.NewAssets(connectionSource)
   106  	accountsStore := sqlstore.NewAccounts(connectionSource)
   107  	transfersStore := sqlstore.NewTransfers(connectionSource)
   108  
   109  	block1 := addTestBlockForTime(t, ctx, blocksStore, time.Now().Add(-2*time.Minute))
   110  	block2 := addTestBlockForTime(t, ctx, blocksStore, time.Now().Add(-1*time.Minute))
   111  
   112  	asset := CreateAsset(t, ctx, assetsStore, block1)
   113  
   114  	account1 := CreateAccount(t, ctx, accountsStore, block1,
   115  		AccountForAsset(asset),
   116  	)
   117  	account2 := CreateAccount(t, ctx, accountsStore, block1,
   118  		AccountWithType(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   119  		AccountForAsset(asset),
   120  	)
   121  
   122  	transfer1 := NewTransfer(t, ctx, accountsStore, block1,
   123  		TransferWithAsset(asset),
   124  		TransferFromToAccounts(account1, account2),
   125  		TransferAsRecurring(&eventspb.RecurringTransfer{
   126  			StartEpoch: 10,
   127  			EndEpoch:   nil,
   128  			Factor:     "0.1",
   129  		}),
   130  	)
   131  
   132  	transfer2 := NewTransfer(t, ctx, accountsStore, block1,
   133  		TransferWithAsset(asset),
   134  		TransferFromToAccounts(account1, account2),
   135  		TransferAsRecurring(&eventspb.RecurringTransfer{
   136  			StartEpoch: 10,
   137  			EndEpoch:   nil,
   138  			Factor:     "0.1",
   139  		}),
   140  	)
   141  	transfer2.TxHash = transfer1.TxHash
   142  
   143  	transfer1UpdateFromSameTx := NewTransfer(t, ctx, accountsStore, block1,
   144  		TransferWithID(transfer1.ID),
   145  		TransferWithAsset(asset),
   146  		TransferFromToAccounts(account1, account2),
   147  		TransferAsRecurring(&eventspb.RecurringTransfer{
   148  			StartEpoch: 15,
   149  			EndEpoch:   nil,
   150  			Factor:     "0.15",
   151  		}),
   152  	)
   153  	transfer1UpdateFromSameTx.TxHash = transfer1.TxHash
   154  
   155  	transfer1UpdateFromDifferentTx := NewTransfer(t, ctx, accountsStore, block2,
   156  		TransferWithID(transfer1.ID),
   157  		TransferWithAsset(asset),
   158  		TransferFromToAccounts(account1, account2),
   159  		TransferAsRecurring(&eventspb.RecurringTransfer{
   160  			StartEpoch: 20,
   161  			EndEpoch:   ptr.From(uint64(25)),
   162  			Factor:     "0.2",
   163  		}),
   164  	)
   165  
   166  	// Ensure we have different transfers so the test is meaningful.
   167  	RequireAllDifferent(t, transfer1, transfer2, transfer1UpdateFromSameTx, transfer1UpdateFromDifferentTx)
   168  
   169  	t.Run("Save transfers", func(t *testing.T) {
   170  		require.NoError(t, transfersStore.Upsert(ctx, transfer1))
   171  		require.NoError(t, transfersStore.Upsert(ctx, transfer2))
   172  		require.NoError(t, transfersStore.Upsert(ctx, transfer1UpdateFromSameTx))
   173  		require.NoError(t, transfersStore.Upsert(ctx, transfer1UpdateFromDifferentTx))
   174  	})
   175  
   176  	t.Run("Retrieve the transfer by hash returns all matching the hash", func(t *testing.T) {
   177  		retrieved, err := transfersStore.GetByTxHash(ctx, transfer1.TxHash)
   178  		require.NoError(t, err)
   179  		assert.ElementsMatch(t,
   180  			[]entities.Transfer{*transfer2, *transfer1UpdateFromSameTx},
   181  			retrieved,
   182  		)
   183  	})
   184  }
   185  
   186  func TestGetTransfersToOrFromParty(t *testing.T) {
   187  	ctx := tempTransaction(t)
   188  
   189  	blocksStore := sqlstore.NewBlocks(connectionSource)
   190  	assetsStore := sqlstore.NewAssets(connectionSource)
   191  	accountsStore := sqlstore.NewAccounts(connectionSource)
   192  	transfersStore := sqlstore.NewTransfers(connectionSource)
   193  
   194  	block := addTestBlockForTime(t, ctx, blocksStore, time.Now())
   195  
   196  	asset := CreateAsset(t, ctx, assetsStore, block)
   197  
   198  	account1 := CreateAccount(t, ctx, accountsStore, block,
   199  		AccountForAsset(asset),
   200  	)
   201  	account2 := CreateAccount(t, ctx, accountsStore, block,
   202  		AccountWithType(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   203  		AccountForAsset(asset),
   204  	)
   205  	account3 := CreateAccount(t, ctx, accountsStore, block,
   206  		AccountForAsset(asset),
   207  	)
   208  
   209  	transfer1 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   210  		TransferWithAsset(asset),
   211  		TransferFromToAccounts(account2, account1),
   212  		TransferAsRecurring(&eventspb.RecurringTransfer{
   213  			StartEpoch: 5,
   214  			EndEpoch:   ptr.From(uint64(15)),
   215  			Factor:     "0.1",
   216  			DispatchStrategy: &vegapb.DispatchStrategy{
   217  				AssetForMetric: "deadd0d0",
   218  				Markets:        []string{"beefdead", "feebaad"},
   219  				Metric:         vegapb.DispatchMetric_DISPATCH_METRIC_MARKET_VALUE,
   220  			},
   221  		}),
   222  	)
   223  	transfer2 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   224  		TransferWithAsset(asset),
   225  		TransferFromToAccounts(account1, account2),
   226  		TransferAsRecurring(&eventspb.RecurringTransfer{
   227  			StartEpoch: 10,
   228  			EndEpoch:   ptr.From(uint64(20)),
   229  			Factor:     "0.1",
   230  		}),
   231  	)
   232  	transfer3 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   233  		TransferWithAsset(asset),
   234  		TransferFromToAccounts(account1, account3),
   235  		TransferAsRecurring(&eventspb.RecurringTransfer{
   236  			StartEpoch: 25,
   237  			EndEpoch:   nil,
   238  			Factor:     "0.1",
   239  		}),
   240  	)
   241  	transfer4 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   242  		TransferWithAsset(asset),
   243  		TransferFromToAccounts(account3, account2),
   244  		TransferAsRecurring(&eventspb.RecurringTransfer{
   245  			StartEpoch: 15,
   246  			EndEpoch:   ptr.From(uint64(20)),
   247  			Factor:     "0.1",
   248  		}),
   249  	)
   250  
   251  	t.Run("Retrieve all transfers from/to party", func(t *testing.T) {
   252  		retrieved, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), sqlstore.ListTransfersFilters{}, account2.PartyID)
   253  		require.NoError(t, err)
   254  		assert.ElementsMatch(t,
   255  			[]entities.Transfer{*transfer1, *transfer2, *transfer4},
   256  			TransferDetailsAsTransfers(t, retrieved),
   257  		)
   258  	})
   259  
   260  	t.Run("Retrieve transfers from/to party with epoch range", func(t *testing.T) {
   261  		filters := sqlstore.ListTransfersFilters{
   262  			FromEpoch: ptr.From(uint64(16)),
   263  			ToEpoch:   ptr.From(uint64(20)),
   264  		}
   265  
   266  		retrievedFromAccount1, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   267  		require.NoError(t, err)
   268  		assert.ElementsMatch(t,
   269  			[]entities.Transfer{*transfer2},
   270  			TransferDetailsAsTransfers(t, retrievedFromAccount1),
   271  		)
   272  
   273  		retrievedFromAccount3, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), filters, account3.PartyID)
   274  		require.NoError(t, err)
   275  		assert.ElementsMatch(t,
   276  			[]entities.Transfer{*transfer4},
   277  			TransferDetailsAsTransfers(t, retrievedFromAccount3),
   278  		)
   279  	})
   280  
   281  	t.Run("Retrieve transfers from/to party from epoch", func(t *testing.T) {
   282  		filters := sqlstore.ListTransfersFilters{
   283  			FromEpoch: ptr.From(uint64(20)),
   284  		}
   285  
   286  		retrievedFromAccount1, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   287  		require.NoError(t, err)
   288  		assert.ElementsMatch(t,
   289  			[]entities.Transfer{*transfer2, *transfer3},
   290  			TransferDetailsAsTransfers(t, retrievedFromAccount1),
   291  		)
   292  
   293  		retrievedFromAccount3, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), filters, account3.PartyID)
   294  		require.NoError(t, err)
   295  		assert.ElementsMatch(t,
   296  			[]entities.Transfer{*transfer3, *transfer4},
   297  			TransferDetailsAsTransfers(t, retrievedFromAccount3),
   298  		)
   299  	})
   300  
   301  	t.Run("Retrieve transfers from/to party to epoch", func(t *testing.T) {
   302  		filters := sqlstore.ListTransfersFilters{
   303  			ToEpoch: ptr.From(uint64(10)),
   304  		}
   305  
   306  		retrievedFromAccount1, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   307  		require.NoError(t, err)
   308  		assert.ElementsMatch(t,
   309  			[]entities.Transfer{*transfer1, *transfer2},
   310  			TransferDetailsAsTransfers(t, retrievedFromAccount1),
   311  		)
   312  
   313  		retrievedFromAccount3, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), filters, account3.PartyID)
   314  		require.NoError(t, err)
   315  		assert.Empty(t, retrievedFromAccount3)
   316  	})
   317  
   318  	t.Run("Retrieve transfers from/to party by from account type", func(t *testing.T) {
   319  		filters := sqlstore.ListTransfersFilters{
   320  			FromAccountType: ptr.From(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   321  		}
   322  
   323  		retrieved, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), filters, account2.PartyID)
   324  		require.NoError(t, err)
   325  		assert.ElementsMatch(t,
   326  			[]entities.Transfer{*transfer1},
   327  			TransferDetailsAsTransfers(t, retrieved),
   328  		)
   329  	})
   330  
   331  	t.Run("Retrieve transfers from/to party by to account type", func(t *testing.T) {
   332  		filters := sqlstore.ListTransfersFilters{
   333  			ToAccountType: ptr.From(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   334  		}
   335  
   336  		retrieved, _, err := transfersStore.GetTransfersToOrFromParty(ctx, entities.DefaultCursorPagination(true), filters, account2.PartyID)
   337  		require.NoError(t, err)
   338  		assert.ElementsMatch(t,
   339  			[]entities.Transfer{*transfer2, *transfer4},
   340  			TransferDetailsAsTransfers(t, retrieved),
   341  		)
   342  	})
   343  }
   344  
   345  func TestGetTransfersByParty(t *testing.T) {
   346  	ctx := tempTransaction(t)
   347  
   348  	blocksStore := sqlstore.NewBlocks(connectionSource)
   349  	assetsStore := sqlstore.NewAssets(connectionSource)
   350  	accountsStore := sqlstore.NewAccounts(connectionSource)
   351  	transfersStore := sqlstore.NewTransfers(connectionSource)
   352  
   353  	block := addTestBlockForTime(t, ctx, blocksStore, time.Now())
   354  
   355  	asset := CreateAsset(t, ctx, assetsStore, block)
   356  
   357  	account1 := CreateAccount(t, ctx, accountsStore, block,
   358  		AccountForAsset(asset),
   359  	)
   360  	account2 := CreateAccount(t, ctx, accountsStore, block,
   361  		AccountWithType(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   362  		AccountForAsset(asset),
   363  	)
   364  
   365  	transfer1 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   366  		TransferWithAsset(asset),
   367  		TransferFromToAccounts(account1, account2),
   368  		TransferAsRecurring(&eventspb.RecurringTransfer{
   369  			StartEpoch: 5,
   370  			EndEpoch:   ptr.From(uint64(15)),
   371  			Factor:     "0.1",
   372  		}),
   373  	)
   374  	transfer2 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   375  		TransferWithAsset(asset),
   376  		TransferFromToAccounts(account2, account1),
   377  		TransferAsRecurring(&eventspb.RecurringTransfer{
   378  			StartEpoch: 10,
   379  			EndEpoch:   ptr.From(uint64(17)),
   380  			Factor:     "0.1",
   381  		}),
   382  	)
   383  	transfer3 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   384  		TransferWithAsset(asset),
   385  		TransferFromToAccounts(account2, account1),
   386  		TransferAsRecurring(&eventspb.RecurringTransfer{
   387  			StartEpoch: 15,
   388  			EndEpoch:   ptr.From(uint64(20)),
   389  			Factor:     "0.1",
   390  		}),
   391  	)
   392  	transfer4 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   393  		TransferWithAsset(asset),
   394  		TransferFromToAccounts(account1, account2),
   395  		TransferAsRecurring(&eventspb.RecurringTransfer{
   396  			StartEpoch: 15,
   397  			EndEpoch:   ptr.From(uint64(20)),
   398  			Factor:     "0.1",
   399  		}),
   400  	)
   401  
   402  	t.Run("Retrieve transfers from party", func(t *testing.T) {
   403  		retrieved, _, err := transfersStore.GetTransfersFromParty(ctx, entities.DefaultCursorPagination(true), sqlstore.ListTransfersFilters{}, account1.PartyID)
   404  
   405  		require.NoError(t, err)
   406  		assert.ElementsMatch(t,
   407  			[]entities.Transfer{*transfer1, *transfer4},
   408  			TransferDetailsAsTransfers(t, retrieved),
   409  		)
   410  	})
   411  
   412  	t.Run("Retrieve transfers from party with epoch range", func(t *testing.T) {
   413  		filters := sqlstore.ListTransfersFilters{
   414  			FromEpoch: ptr.From(uint64(5)),
   415  			ToEpoch:   ptr.From(uint64(10)),
   416  		}
   417  
   418  		retrieved, _, err := transfersStore.GetTransfersFromParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   419  
   420  		require.NoError(t, err)
   421  		assert.ElementsMatch(t,
   422  			[]entities.Transfer{*transfer1},
   423  			TransferDetailsAsTransfers(t, retrieved),
   424  		)
   425  	})
   426  
   427  	t.Run("Retrieve transfers from party from epoch", func(t *testing.T) {
   428  		filters := sqlstore.ListTransfersFilters{
   429  			FromEpoch: ptr.From(uint64(17)),
   430  		}
   431  
   432  		retrieved, _, err := transfersStore.GetTransfersFromParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   433  		require.NoError(t, err)
   434  
   435  		assert.ElementsMatch(t,
   436  			[]entities.Transfer{*transfer4},
   437  			TransferDetailsAsTransfers(t, retrieved),
   438  		)
   439  	})
   440  
   441  	t.Run("Retrieve transfers from party to epoch", func(t *testing.T) {
   442  		filters := sqlstore.ListTransfersFilters{
   443  			ToEpoch: ptr.From(uint64(13)),
   444  		}
   445  
   446  		retrieved, _, err := transfersStore.GetTransfersFromParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   447  		require.NoError(t, err)
   448  
   449  		assert.ElementsMatch(t,
   450  			[]entities.Transfer{*transfer1},
   451  			TransferDetailsAsTransfers(t, retrieved),
   452  		)
   453  	})
   454  
   455  	t.Run("Retrieve transfers to party", func(t *testing.T) {
   456  		retrieved, _, err := transfersStore.GetTransfersToParty(ctx, entities.DefaultCursorPagination(true), sqlstore.ListTransfersFilters{}, account1.PartyID)
   457  
   458  		require.NoError(t, err)
   459  		assert.ElementsMatch(t,
   460  			[]entities.Transfer{*transfer2, *transfer3},
   461  			TransferDetailsAsTransfers(t, retrieved),
   462  		)
   463  	})
   464  
   465  	t.Run("Retrieve transfers to party with epoch range", func(t *testing.T) {
   466  		filters := sqlstore.ListTransfersFilters{
   467  			FromEpoch: ptr.From(uint64(5)),
   468  			ToEpoch:   ptr.From(uint64(10)),
   469  		}
   470  
   471  		retrieved, _, err := transfersStore.GetTransfersToParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   472  
   473  		require.NoError(t, err)
   474  		assert.ElementsMatch(t,
   475  			[]entities.Transfer{*transfer2},
   476  			TransferDetailsAsTransfers(t, retrieved),
   477  		)
   478  	})
   479  
   480  	t.Run("Retrieve transfers to party from epoch", func(t *testing.T) {
   481  		filters := sqlstore.ListTransfersFilters{
   482  			FromEpoch: ptr.From(uint64(18)),
   483  		}
   484  
   485  		retrieved, _, err := transfersStore.GetTransfersToParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   486  		require.NoError(t, err)
   487  
   488  		assert.ElementsMatch(t,
   489  			[]entities.Transfer{*transfer3},
   490  			TransferDetailsAsTransfers(t, retrieved),
   491  		)
   492  	})
   493  
   494  	t.Run("Retrieve transfers to party to epoch", func(t *testing.T) {
   495  		filters := sqlstore.ListTransfersFilters{
   496  			ToEpoch: ptr.From(uint64(13)),
   497  		}
   498  
   499  		retrieved, _, err := transfersStore.GetTransfersToParty(ctx, entities.DefaultCursorPagination(true), filters, account1.PartyID)
   500  		require.NoError(t, err)
   501  
   502  		assert.ElementsMatch(t,
   503  			[]entities.Transfer{*transfer2},
   504  			TransferDetailsAsTransfers(t, retrieved),
   505  		)
   506  	})
   507  
   508  	t.Run("Retrieve transfers from party by from account type", func(t *testing.T) {
   509  		filters := sqlstore.ListTransfersFilters{
   510  			FromAccountType: ptr.From(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   511  		}
   512  
   513  		retrieved, _, err := transfersStore.GetTransfersFromParty(ctx, entities.DefaultCursorPagination(true), filters, account2.PartyID)
   514  		require.NoError(t, err)
   515  
   516  		assert.ElementsMatch(t,
   517  			[]entities.Transfer{*transfer2, *transfer3},
   518  			TransferDetailsAsTransfers(t, retrieved),
   519  		)
   520  	})
   521  	t.Run("Retrieve transfers to party by from account type", func(t *testing.T) {
   522  		filters := sqlstore.ListTransfersFilters{
   523  			ToAccountType: ptr.From(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   524  		}
   525  
   526  		retrieved, _, err := transfersStore.GetTransfersToParty(ctx, entities.DefaultCursorPagination(true), filters, account2.PartyID)
   527  		require.NoError(t, err)
   528  
   529  		assert.ElementsMatch(t,
   530  			[]entities.Transfer{*transfer1, *transfer4},
   531  			TransferDetailsAsTransfers(t, retrieved),
   532  		)
   533  	})
   534  }
   535  
   536  func TestGetAllTransfers(t *testing.T) {
   537  	ctx := tempTransaction(t)
   538  
   539  	blocksStore := sqlstore.NewBlocks(connectionSource)
   540  	assetsStore := sqlstore.NewAssets(connectionSource)
   541  	accountsStore := sqlstore.NewAccounts(connectionSource)
   542  	transfersStore := sqlstore.NewTransfers(connectionSource)
   543  
   544  	block := addTestBlockForTime(t, ctx, blocksStore, time.Now())
   545  
   546  	asset := CreateAsset(t, ctx, assetsStore, block)
   547  
   548  	account1 := CreateAccount(t, ctx, accountsStore, block,
   549  		AccountForAsset(asset),
   550  	)
   551  	account2 := CreateAccount(t, ctx, accountsStore, block,
   552  		AccountWithType(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   553  		AccountForAsset(asset),
   554  	)
   555  	account3 := CreateAccount(t, ctx, accountsStore, block,
   556  		AccountForAsset(asset),
   557  	)
   558  
   559  	transfer1 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   560  		TransferWithAsset(asset),
   561  		TransferFromToAccounts(account2, account1),
   562  		TransferAsRecurring(&eventspb.RecurringTransfer{
   563  			StartEpoch: 5,
   564  			EndEpoch:   ptr.From(uint64(15)),
   565  			Factor:     "0.1",
   566  			DispatchStrategy: &vegapb.DispatchStrategy{
   567  				AssetForMetric:  "deadd0d0",
   568  				Metric:          vegapb.DispatchMetric_DISPATCH_METRIC_MARKET_VALUE,
   569  				Markets:         []string{"beefdead", "feebaad"},
   570  				IndividualScope: vegapb.IndividualScope_INDIVIDUAL_SCOPE_IN_TEAM,
   571  			},
   572  		}),
   573  	)
   574  	transfer2 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   575  		TransferWithAsset(asset),
   576  		TransferFromToAccounts(account1, account2),
   577  		TransferWithStatus(entities.TransferStatusDone),
   578  		TransferAsRecurring(&eventspb.RecurringTransfer{
   579  			StartEpoch: 10,
   580  			EndEpoch:   ptr.From(uint64(20)),
   581  			Factor:     "0.1",
   582  		}),
   583  	)
   584  	transfer3 := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   585  		TransferWithAsset(asset),
   586  		TransferFromToAccounts(account1, account3),
   587  		TransferWithStatus(entities.TransferStatusCancelled),
   588  		TransferAsRecurring(&eventspb.RecurringTransfer{
   589  			StartEpoch: 25,
   590  			EndEpoch:   nil,
   591  			Factor:     "0.1",
   592  			DispatchStrategy: &vegapb.DispatchStrategy{
   593  				TeamScope: []string{
   594  					"beefdeadfeebaad",
   595  				},
   596  			},
   597  		}),
   598  		TransferWithGameID(ptr.From("c001d00d")),
   599  	)
   600  
   601  	t.Run("Retrieve all transfers", func(t *testing.T) {
   602  		retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), sqlstore.ListTransfersFilters{})
   603  		require.NoError(t, err)
   604  		assert.ElementsMatch(t,
   605  			[]entities.Transfer{*transfer1, *transfer2, *transfer3},
   606  			TransferDetailsAsTransfers(t, retrieved),
   607  		)
   608  	})
   609  
   610  	t.Run("Retrieve transfers with epoch range", func(t *testing.T) {
   611  		filters := sqlstore.ListTransfersFilters{
   612  			FromEpoch: ptr.From(uint64(16)),
   613  			ToEpoch:   ptr.From(uint64(28)),
   614  		}
   615  
   616  		retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), filters)
   617  		require.NoError(t, err)
   618  
   619  		assert.ElementsMatch(t,
   620  			[]entities.Transfer{*transfer2, *transfer3},
   621  			TransferDetailsAsTransfers(t, retrieved),
   622  		)
   623  	})
   624  
   625  	t.Run("Retrieve all transfers from epoch", func(t *testing.T) {
   626  		filters := sqlstore.ListTransfersFilters{
   627  			FromEpoch: ptr.From(uint64(20)),
   628  		}
   629  
   630  		retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), filters)
   631  		require.NoError(t, err)
   632  
   633  		assert.ElementsMatch(t,
   634  			[]entities.Transfer{*transfer2, *transfer3},
   635  			TransferDetailsAsTransfers(t, retrieved),
   636  		)
   637  	})
   638  
   639  	t.Run("Retrieve transfers to epoch", func(t *testing.T) {
   640  		filters := sqlstore.ListTransfersFilters{
   641  			ToEpoch: ptr.From(uint64(10)),
   642  		}
   643  
   644  		retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), filters)
   645  		require.NoError(t, err)
   646  
   647  		assert.ElementsMatch(t,
   648  			[]entities.Transfer{*transfer1, *transfer2},
   649  			TransferDetailsAsTransfers(t, retrieved),
   650  		)
   651  	})
   652  
   653  	t.Run("Retrieve transfers by status", func(t *testing.T) {
   654  		matrix := map[entities.TransferStatus][]entities.Transfer{
   655  			entities.TransferStatusPending:   {*transfer1},
   656  			entities.TransferStatusCancelled: {*transfer3},
   657  			entities.TransferStatusRejected:  {},
   658  		}
   659  
   660  		for status, expected := range matrix {
   661  			filters := sqlstore.ListTransfersFilters{
   662  				Status: ptr.From(status),
   663  			}
   664  
   665  			retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), filters)
   666  			require.NoError(t, err)
   667  			assert.Equal(t, expected, TransferDetailsAsTransfers(t, retrieved))
   668  		}
   669  	})
   670  
   671  	t.Run("Retrieve transfers by scope", func(t *testing.T) {
   672  		matrix := map[entities.TransferScope][]entities.Transfer{
   673  			entities.TransferScopeIndividual: {*transfer1},
   674  			entities.TransferScopeTeam:       {*transfer3},
   675  		}
   676  
   677  		for scope, expected := range matrix {
   678  			filters := sqlstore.ListTransfersFilters{
   679  				Scope: ptr.From(scope),
   680  			}
   681  
   682  			retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), filters)
   683  			require.NoError(t, err)
   684  			assert.Equal(t, expected, TransferDetailsAsTransfers(t, retrieved))
   685  		}
   686  	})
   687  
   688  	t.Run("Retrieve transfers by game ID", func(t *testing.T) {
   689  		filters := sqlstore.ListTransfersFilters{
   690  			GameID: ptr.From(entities.GameID("c001d00d")),
   691  		}
   692  		retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), filters)
   693  		require.NoError(t, err)
   694  		assert.Equal(t, []entities.Transfer{*transfer3}, TransferDetailsAsTransfers(t, retrieved))
   695  	})
   696  
   697  	t.Run("Retrieve transfers by From account type", func(t *testing.T) {
   698  		filters := sqlstore.ListTransfersFilters{
   699  			FromAccountType: ptr.From(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   700  		}
   701  
   702  		retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), filters)
   703  		require.NoError(t, err)
   704  		assert.Equal(t, []entities.Transfer{*transfer1}, TransferDetailsAsTransfers(t, retrieved))
   705  	})
   706  
   707  	t.Run("Retrieve transfers by To account type", func(t *testing.T) {
   708  		filters := sqlstore.ListTransfersFilters{
   709  			ToAccountType: ptr.From(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   710  		}
   711  
   712  		retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(true), filters)
   713  		require.NoError(t, err)
   714  		assert.Equal(t, []entities.Transfer{*transfer2}, TransferDetailsAsTransfers(t, retrieved))
   715  	})
   716  }
   717  
   718  func TestGetAllTransfersWithPagination(t *testing.T) {
   719  	ctx := tempTransaction(t)
   720  
   721  	blocksStore := sqlstore.NewBlocks(connectionSource)
   722  	assetsStore := sqlstore.NewAssets(connectionSource)
   723  	accountsStore := sqlstore.NewAccounts(connectionSource)
   724  	transfersStore := sqlstore.NewTransfers(connectionSource)
   725  
   726  	block := addTestBlockForTime(t, ctx, blocksStore, time.Now())
   727  
   728  	asset := CreateAsset(t, ctx, assetsStore, block)
   729  
   730  	account1 := CreateAccount(t, ctx, accountsStore, block,
   731  		AccountForAsset(asset),
   732  	)
   733  	account2 := CreateAccount(t, ctx, accountsStore, block,
   734  		AccountWithType(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   735  		AccountForAsset(asset),
   736  	)
   737  
   738  	transfers := make([]entities.Transfer, 0, 10)
   739  	for i := 0; i < 10; i++ {
   740  		block := addTestBlockForTime(t, ctx, blocksStore, time.Now().Add(time.Duration(i)*time.Second))
   741  		transfer := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   742  			TransferWithAsset(asset),
   743  			TransferFromToAccounts(account1, account2),
   744  			TransferAsRecurring(&eventspb.RecurringTransfer{
   745  				StartEpoch: 5,
   746  				EndEpoch:   ptr.From(uint64(15)),
   747  				Factor:     "0.1",
   748  			}),
   749  		)
   750  		transfers = append(transfers, *transfer)
   751  	}
   752  
   753  	noFilters := sqlstore.ListTransfersFilters{}
   754  
   755  	t.Run("Paginate with oldest first", func(t *testing.T) {
   756  		pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, false)
   757  		require.NoError(t, err)
   758  
   759  		retrieved, pageInfo, err := transfersStore.GetAll(ctx, pagination, noFilters)
   760  		require.NoError(t, err)
   761  		assert.Equal(t, transfers, TransferDetailsAsTransfers(t, retrieved))
   762  		assert.Equal(t, entities.PageInfo{
   763  			HasNextPage:     false,
   764  			HasPreviousPage: false,
   765  			StartCursor:     transfers[0].Cursor().Encode(),
   766  			EndCursor:       transfers[9].Cursor().Encode(),
   767  		}, pageInfo)
   768  	})
   769  
   770  	t.Run("Paginate first 3 transfers", func(t *testing.T) {
   771  		first := int32(3)
   772  		pagination, err := entities.NewCursorPagination(&first, nil, nil, nil, false)
   773  		require.NoError(t, err)
   774  
   775  		retrieved, pageInfo, err := transfersStore.GetAll(ctx, pagination, noFilters)
   776  		require.NoError(t, err)
   777  		assert.Equal(t, transfers[:3], TransferDetailsAsTransfers(t, retrieved))
   778  		assert.Equal(t, entities.PageInfo{
   779  			HasNextPage:     true,
   780  			HasPreviousPage: false,
   781  			StartCursor:     transfers[0].Cursor().Encode(),
   782  			EndCursor:       transfers[2].Cursor().Encode(),
   783  		}, pageInfo)
   784  	})
   785  
   786  	t.Run("Paginate last 3 transfers", func(t *testing.T) {
   787  		last := int32(3)
   788  		pagination, err := entities.NewCursorPagination(nil, nil, &last, nil, false)
   789  		require.NoError(t, err)
   790  
   791  		retrieved, pageInfo, err := transfersStore.GetAll(ctx, pagination, noFilters)
   792  		require.NoError(t, err)
   793  		assert.Equal(t, transfers[7:], TransferDetailsAsTransfers(t, retrieved))
   794  		assert.Equal(t, entities.PageInfo{
   795  			HasNextPage:     false,
   796  			HasPreviousPage: true,
   797  			StartCursor:     transfers[7].Cursor().Encode(),
   798  			EndCursor:       transfers[9].Cursor().Encode(),
   799  		}, pageInfo)
   800  	})
   801  
   802  	t.Run("Paginate first 3 transfers after third one", func(t *testing.T) {
   803  		first := int32(3)
   804  		after := transfers[2].Cursor().Encode()
   805  		pagination, err := entities.NewCursorPagination(&first, &after, nil, nil, false)
   806  		require.NoError(t, err)
   807  
   808  		retrieved, pageInfo, err := transfersStore.GetAll(ctx, pagination, noFilters)
   809  		require.NoError(t, err)
   810  		assert.Equal(t, transfers[3:6], TransferDetailsAsTransfers(t, retrieved))
   811  		assert.Equal(t, entities.PageInfo{
   812  			HasNextPage:     true,
   813  			HasPreviousPage: true,
   814  			StartCursor:     transfers[3].Cursor().Encode(),
   815  			EndCursor:       transfers[5].Cursor().Encode(),
   816  		}, pageInfo)
   817  	})
   818  
   819  	t.Run("Paginate last 3 transfers before seventh one", func(t *testing.T) {
   820  		last := int32(3)
   821  		before := transfers[7].Cursor().Encode()
   822  		pagination, err := entities.NewCursorPagination(nil, nil, &last, &before, false)
   823  		require.NoError(t, err)
   824  
   825  		retrieved, pageInfo, err := transfersStore.GetAll(ctx, pagination, noFilters)
   826  		require.NoError(t, err)
   827  		assert.Equal(t, transfers[4:7], TransferDetailsAsTransfers(t, retrieved))
   828  		assert.Equal(t, entities.PageInfo{
   829  			HasNextPage:     true,
   830  			HasPreviousPage: true,
   831  			StartCursor:     transfers[4].Cursor().Encode(),
   832  			EndCursor:       transfers[6].Cursor().Encode(),
   833  		}, pageInfo)
   834  	})
   835  }
   836  
   837  func TestGetAllRewardTransfers(t *testing.T) {
   838  	ctx := tempTransaction(t)
   839  
   840  	blocksStore := sqlstore.NewBlocks(connectionSource)
   841  	assetsStore := sqlstore.NewAssets(connectionSource)
   842  	accountsStore := sqlstore.NewAccounts(connectionSource)
   843  	transfersStore := sqlstore.NewTransfers(connectionSource)
   844  
   845  	vegaTime := time.Now().Truncate(time.Microsecond)
   846  
   847  	block := addTestBlockForTime(t, ctx, blocksStore, vegaTime)
   848  
   849  	asset := CreateAsset(t, ctx, assetsStore, block)
   850  
   851  	account1 := CreateAccount(t, ctx, accountsStore, block,
   852  		AccountForAsset(asset),
   853  	)
   854  	account2 := CreateAccount(t, ctx, accountsStore, block,
   855  		AccountWithType(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   856  		AccountForAsset(asset),
   857  	)
   858  
   859  	allTransfers := make([]entities.Transfer, 0, 20)
   860  	for i := 0; i < 10; i++ {
   861  		vegaTime = vegaTime.Add(time.Second)
   862  		block := addTestBlockForTime(t, ctx, blocksStore, vegaTime)
   863  
   864  		transfer := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   865  			TransferWithAsset(asset),
   866  			TransferFromToAccounts(account1, account2),
   867  			TransferAsOneOff(eventspb.OneOffTransfer{
   868  				DeliverOn: vegaTime.UnixNano(),
   869  			}),
   870  		)
   871  		allTransfers = append(allTransfers, *transfer)
   872  	}
   873  
   874  	rewardTransfers := make([]entities.Transfer, 0, 10)
   875  	for i := 0; i < 10; i++ {
   876  		vegaTime = vegaTime.Add(time.Second)
   877  		block := addTestBlockForTime(t, ctx, blocksStore, vegaTime)
   878  
   879  		var kindOption TransferOption
   880  		var statusOption TransferOption
   881  		if i%2 == 0 {
   882  			kindOption = TransferAsRecurringGovernance(eventspb.RecurringGovernanceTransfer{
   883  				StartEpoch: 15,
   884  				EndEpoch:   nil,
   885  				DispatchStrategy: &vegapb.DispatchStrategy{
   886  					Metric:          vegapb.DispatchMetric_DISPATCH_METRIC_RELATIVE_RETURN,
   887  					LockPeriod:      uint64((i % 7) + 1),
   888  					IndividualScope: vegapb.IndividualScope_INDIVIDUAL_SCOPE_ALL,
   889  				},
   890  			})
   891  			statusOption = TransferWithStatus(entities.TransferStatusDone)
   892  		} else {
   893  			kindOption = TransferAsRecurring(&eventspb.RecurringTransfer{
   894  				StartEpoch: 15,
   895  				EndEpoch:   nil,
   896  				Factor:     "0.15",
   897  				DispatchStrategy: &vegapb.DispatchStrategy{
   898  					Metric:     vegapb.DispatchMetric_DISPATCH_METRIC_VALIDATOR_RANKING,
   899  					LockPeriod: uint64((i % 7) + 1),
   900  					TeamScope:  []string{"deadfbeefc0ffeed00d"},
   901  				},
   902  			})
   903  
   904  			statusOption = TransferWithStatus(entities.TransferStatusPending)
   905  		}
   906  
   907  		transfer := CreateTransfer(t, ctx, transfersStore, accountsStore, block,
   908  			TransferWithAsset(asset),
   909  			TransferFromToAccounts(account1, account2),
   910  			kindOption,
   911  			statusOption,
   912  		)
   913  		rewardTransfers = append(rewardTransfers, *transfer)
   914  		allTransfers = append(allTransfers, *transfer)
   915  	}
   916  
   917  	noFilters := sqlstore.ListTransfersFilters{}
   918  
   919  	t.Run("Get all transfers", func(t *testing.T) {
   920  		retrieved, _, err := transfersStore.GetAll(ctx, entities.DefaultCursorPagination(false), noFilters)
   921  		require.NoError(t, err)
   922  		assert.Equal(t, allTransfers, TransferDetailsAsTransfers(t, retrieved))
   923  	})
   924  
   925  	t.Run("Get only reward transfers", func(t *testing.T) {
   926  		retrieved, _, err := transfersStore.GetAllRewards(ctx, entities.DefaultCursorPagination(false), noFilters)
   927  		require.NoError(t, err)
   928  		assert.Equal(t, rewardTransfers, TransferDetailsAsTransfers(t, retrieved))
   929  	})
   930  
   931  	t.Run("Retrieve transfers by status pending", func(t *testing.T) {
   932  		filters := sqlstore.ListTransfersFilters{
   933  			Status: ptr.From(entities.TransferStatusDone),
   934  		}
   935  
   936  		retrieved, _, err := transfersStore.GetAllRewards(ctx, entities.DefaultCursorPagination(false), filters)
   937  		require.NoError(t, err)
   938  		assert.Equal(t,
   939  			[]entities.Transfer{rewardTransfers[0], rewardTransfers[2], rewardTransfers[4], rewardTransfers[6], rewardTransfers[8]},
   940  			TransferDetailsAsTransfers(t, retrieved))
   941  	})
   942  
   943  	t.Run("Retrieve transfers by scope", func(t *testing.T) {
   944  		matrix := map[entities.TransferScope][]entities.Transfer{
   945  			entities.TransferScopeIndividual: {rewardTransfers[0], rewardTransfers[2], rewardTransfers[4], rewardTransfers[6], rewardTransfers[8]},
   946  			entities.TransferScopeTeam:       {rewardTransfers[1], rewardTransfers[3], rewardTransfers[5], rewardTransfers[7], rewardTransfers[9]},
   947  		}
   948  
   949  		for scope, expected := range matrix {
   950  			filters := sqlstore.ListTransfersFilters{
   951  				Scope: ptr.From(scope),
   952  			}
   953  
   954  			retrieved, _, err := transfersStore.GetAllRewards(ctx, entities.DefaultCursorPagination(false), filters)
   955  			require.NoError(t, err)
   956  			assert.Equal(t, expected, TransferDetailsAsTransfers(t, retrieved))
   957  		}
   958  	})
   959  }
   960  
   961  func TestTransferTypeEnums(t *testing.T) {
   962  	t.Run("Should be able to save and retrieve transfers with all states", testTransferStateEnum)
   963  }
   964  
   965  func testTransferStateEnum(t *testing.T) {
   966  	var transferStatus eventspb.Transfer_Status
   967  	states := getEnums(t, transferStatus)
   968  	assert.Len(t, states, 6)
   969  	for s, state := range states {
   970  		t.Run(state, func(t *testing.T) {
   971  			ctx := tempTransaction(t)
   972  
   973  			blocksStore := sqlstore.NewBlocks(connectionSource)
   974  			assetsStore := sqlstore.NewAssets(connectionSource)
   975  			accountsStore := sqlstore.NewAccounts(connectionSource)
   976  			transfersStore := sqlstore.NewTransfers(connectionSource)
   977  
   978  			block := addTestBlockForTime(t, ctx, blocksStore, time.Now())
   979  
   980  			asset := CreateAsset(t, ctx, assetsStore, block)
   981  
   982  			account1 := CreateAccount(t, ctx, accountsStore, block,
   983  				AccountForAsset(asset),
   984  			)
   985  			account2 := CreateAccount(t, ctx, accountsStore, block,
   986  				AccountWithType(vegapb.AccountType_ACCOUNT_TYPE_GLOBAL_REWARD),
   987  				AccountForAsset(asset),
   988  			)
   989  
   990  			transfer := NewTransfer(t, ctx, accountsStore, block,
   991  				TransferWithAsset(asset),
   992  				TransferFromToAccounts(account1, account2),
   993  				TransferAsRecurring(&eventspb.RecurringTransfer{
   994  					StartEpoch: 10,
   995  					EndEpoch:   nil,
   996  					Factor:     "0.1",
   997  				}),
   998  				TransferWithStatus(entities.TransferStatus(s)),
   999  			)
  1000  
  1001  			require.NoError(t, transfersStore.Upsert(ctx, transfer))
  1002  			retrieved, err := transfersStore.GetByID(ctx, transfer.ID.String())
  1003  			require.NoError(t, err)
  1004  			assert.Equal(t, transfer.Status, retrieved.Status)
  1005  		})
  1006  	}
  1007  }