code.vegaprotocol.io/vega@v0.79.0/datanode/sqlstore/positions_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 "context" 20 "fmt" 21 "testing" 22 "time" 23 24 "code.vegaprotocol.io/vega/datanode/entities" 25 "code.vegaprotocol.io/vega/datanode/sqlstore" 26 vegapb "code.vegaprotocol.io/vega/protos/vega" 27 28 "github.com/google/go-cmp/cmp" 29 "github.com/google/go-cmp/cmp/cmpopts" 30 "github.com/shopspring/decimal" 31 "github.com/stretchr/testify/assert" 32 "github.com/stretchr/testify/require" 33 ) 34 35 func addTestPosition(t *testing.T, 36 ctx context.Context, 37 ps *sqlstore.Positions, 38 market entities.Market, 39 party entities.Party, 40 volume int64, 41 block entities.Block, 42 txHash entities.TxHash, 43 ) entities.Position { 44 t.Helper() 45 pos := entities.NewEmptyPosition(market.ID, party.ID) 46 pos.OpenVolume = volume 47 pos.PendingOpenVolume = volume 48 pos.VegaTime = block.VegaTime 49 pos.RealisedPnl = decimal.New(0, 0) 50 pos.PendingRealisedPnl = decimal.New(0, 0) 51 pos.UnrealisedPnl = decimal.New(0, 0) 52 pos.PendingUnrealisedPnl = decimal.New(0, 0) 53 pos.AverageEntryPrice = decimal.New(0, 0) 54 pos.PendingAverageEntryPrice = decimal.New(0, 0) 55 pos.AverageEntryMarketPrice = decimal.New(0, 0) 56 pos.PendingAverageEntryMarketPrice = decimal.New(0, 0) 57 pos.Adjustment = decimal.New(0, 0) 58 pos.Loss = decimal.New(0, 0) 59 pos.TxHash = txHash 60 err := ps.Add(ctx, pos) 61 require.NoError(t, err) 62 return pos 63 } 64 65 func positionLessThan(x, y entities.Position) bool { 66 if x.MarketID != y.MarketID { 67 return x.MarketID.String() < y.MarketID.String() 68 } 69 return x.PartyID.String() < y.PartyID.String() 70 } 71 72 func assertPositionsMatch(t *testing.T, expected, actual []entities.Position) { 73 t.Helper() 74 sortPositions := cmpopts.SortSlices(positionLessThan) 75 assert.Empty(t, cmp.Diff(actual, expected, sortPositions)) 76 } 77 78 func TestPosition(t *testing.T) { 79 ctx := tempTransaction(t) 80 81 ps := sqlstore.NewPositions(connectionSource) 82 qs := sqlstore.NewParties(connectionSource) 83 bs := sqlstore.NewBlocks(connectionSource) 84 85 block1 := addTestBlockForTime(t, ctx, bs, time.Now().Add((-26*time.Hour)-(2*time.Second))) 86 block2 := addTestBlockForTime(t, ctx, bs, time.Now().Add((-26*time.Hour)-(1*time.Second))) 87 block3 := addTestBlockForTime(t, ctx, bs, time.Now().Add(-26*time.Hour)) 88 89 market1 := entities.Market{ID: entities.MarketID("dead")} 90 market2 := entities.Market{ID: entities.MarketID("beef")} 91 party1 := addTestParty(t, ctx, qs, block1) 92 party2 := addTestParty(t, ctx, qs, block1) 93 94 pos1a := addTestPosition(t, ctx, ps, market1, party1, 100, block1, txHashFromString("pos_1a")) 95 pos1b := addTestPosition(t, ctx, ps, market1, party1, 200, block1, txHashFromString("pos_1b")) 96 97 pos2 := addTestPosition(t, ctx, ps, market1, party2, 300, block2, txHashFromString("pos_2")) 98 pos3 := addTestPosition(t, ctx, ps, market2, party1, 400, block2, txHashFromString("pos_3")) 99 100 _, err := ps.Flush(ctx) 101 require.NoError(t, err) 102 103 _, _ = pos1a, pos1b 104 105 assert.NoError(t, err) 106 107 // Add some new positions 108 pos1c := addTestPosition(t, ctx, ps, market1, party1, 200, block3, txHashFromString("pos_1c")) 109 pos4 := addTestPosition(t, ctx, ps, market2, party2, 500, block3, txHashFromString("pos_4")) 110 ps.Flush(ctx) 111 112 t.Run("GetAll", func(t *testing.T) { 113 expected := []entities.Position{pos1c, pos2, pos3, pos4} 114 actual, err := ps.GetAll(ctx) 115 require.NoError(t, err) 116 assertPositionsMatch(t, expected, actual) 117 }) 118 119 t.Run("GetByParty", func(t *testing.T) { 120 expected := []entities.Position{pos1c, pos3} 121 actual, err := ps.GetByParty(ctx, party1.ID.String()) 122 require.NoError(t, err) 123 assertPositionsMatch(t, expected, actual) 124 }) 125 126 t.Run("GetByMarket", func(t *testing.T) { 127 expected := []entities.Position{pos1c, pos2} 128 actual, err := ps.GetByMarket(ctx, market1.ID.String()) 129 require.NoError(t, err) 130 assertPositionsMatch(t, expected, actual) 131 }) 132 133 t.Run("GetByMarketAndParty", func(t *testing.T) { 134 expected := pos4 135 actual, err := ps.GetByMarketAndParty(ctx, market2.ID.String(), party2.ID.String()) 136 require.NoError(t, err) 137 assert.True(t, expected.Equal(actual)) 138 }) 139 140 t.Run("GetByTxHash", func(t *testing.T) { 141 expected := pos4 142 actual, err := ps.GetByTxHash(ctx, expected.TxHash) 143 require.NoError(t, err) 144 assert.True(t, expected.Equal(actual[0])) 145 }) 146 147 t.Run("GetBadMarketAndParty", func(t *testing.T) { 148 _, err := ps.GetByMarketAndParty(ctx, market2.ID.String(), "ffff") 149 assert.ErrorIs(t, err, entities.ErrNotFound) 150 }) 151 } 152 153 func setupPositionPaginationData(t *testing.T, ctx context.Context, bs *sqlstore.Blocks, ps *sqlstore.Positions, pts *sqlstore.Parties) []entities.Position { 154 t.Helper() 155 positions := make([]entities.Position, 0, 10) 156 blockTime := time.Now() 157 for i := 0; i < 10; i++ { 158 market := entities.Market{ID: entities.MarketID(fmt.Sprintf("deadbeef%02d", i))} 159 for j := 0; j < 10; j++ { 160 block := addTestBlockForTime(t, ctx, bs, blockTime) 161 party := entities.Party{ID: entities.PartyID(fmt.Sprintf("deadbeef%02d", j)), VegaTime: &block.VegaTime} 162 err := pts.Add(ctx, party) 163 require.NoError(t, err) 164 position := addTestPosition(t, ctx, ps, market, party, int64(i), block, defaultTxHash) 165 positions = append(positions, position) 166 blockTime = blockTime.Add(time.Minute) 167 } 168 blockTime = blockTime.Add(time.Hour) 169 } 170 _, err := ps.Flush(ctx) 171 require.NoError(t, err) 172 173 return positions 174 } 175 176 func TestPositions_CursorPagination(t *testing.T) { 177 t.Run("should return all positions for party when no cursor is provided", testPositionCursorPaginationPartyNoCursor) 178 t.Run("should return first page of positions for party when first is provided", testPositionCursorPaginationPartyFirstCursor) 179 t.Run("should return last page of positions for party when last is provided", testPositionCursorPaginationPartyLastCursor) 180 t.Run("should return requested page of positions for party when first and after is provided", testPositionCursorPaginationPartyFirstAfterCursor) 181 t.Run("should return requested page of positions for party when last and before is provided", testPositionCursorPaginationPartyLastBeforeCursor) 182 t.Run("should return all positions for party and market when no cursor is provided", testPositionCursorPaginationPartyMarketNoCursor) 183 184 t.Run("should return all positions for party when no cursor is provided - newest first", testPositionCursorPaginationPartyNoCursorNewestFirst) 185 t.Run("should return first page of positions for party when first is provided - newest first", testPositionCursorPaginationPartyFirstCursorNewestFirst) 186 t.Run("should return last page of positions for party when last is provided - newest first", testPositionCursorPaginationPartyLastCursorNewestFirst) 187 t.Run("should return requested page of positions for party when first and after is provided - newest first", testPositionCursorPaginationPartyFirstAfterCursorNewestFirst) 188 t.Run("should return requested page of positions for party when last and before is provided - newest first", testPositionCursorPaginationPartyLastBeforeCursorNewestFirst) 189 t.Run("should return all positions for party and market when no cursor is provided - newest first", testPositionCursorPaginationPartyMarketNoCursorNewestFirst) 190 } 191 192 func testPositionCursorPaginationPartyNoCursor(t *testing.T) { 193 ctx := tempTransaction(t) 194 195 ps := sqlstore.NewPositions(connectionSource) 196 pts := sqlstore.NewParties(connectionSource) 197 bs := sqlstore.NewBlocks(connectionSource) 198 199 emptyMarketID := entities.MarketID("") 200 201 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 202 203 pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, false) 204 require.NoError(t, err) 205 206 party := entities.Party{ID: entities.PartyID("deadbeef00")} 207 want := []entities.Position{ 208 positions[0], 209 positions[10], 210 positions[20], 211 positions[30], 212 positions[40], 213 positions[50], 214 positions[60], 215 positions[70], 216 positions[80], 217 positions[90], 218 } 219 220 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 221 require.NoError(t, err) 222 for i, g := range got { 223 assert.True(t, want[i].Equal(g)) 224 } 225 // assert.Equal(t, want, got) 226 assert.Equal(t, entities.PageInfo{ 227 HasNextPage: false, 228 HasPreviousPage: false, 229 StartCursor: want[0].Cursor().Encode(), 230 EndCursor: want[9].Cursor().Encode(), 231 }, pageInfo) 232 } 233 234 func testPositionCursorPaginationPartyFirstCursor(t *testing.T) { 235 ctx := tempTransaction(t) 236 237 ps := sqlstore.NewPositions(connectionSource) 238 pts := sqlstore.NewParties(connectionSource) 239 bs := sqlstore.NewBlocks(connectionSource) 240 241 emptyMarketID := entities.MarketID("") 242 243 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 244 first := int32(3) 245 246 pagination, err := entities.NewCursorPagination(&first, nil, nil, nil, false) 247 require.NoError(t, err) 248 249 party := entities.Party{ID: entities.PartyID("deadbeef00")} 250 want := []entities.Position{ 251 positions[0], 252 positions[10], 253 positions[20], 254 } 255 256 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 257 require.NoError(t, err) 258 for i, g := range got { 259 assert.True(t, want[i].Equal(g)) 260 } 261 // assert.Equal(t, want, got) 262 assert.Equal(t, entities.PageInfo{ 263 HasNextPage: true, 264 HasPreviousPage: false, 265 StartCursor: want[0].Cursor().Encode(), 266 EndCursor: want[2].Cursor().Encode(), 267 }, pageInfo) 268 } 269 270 func testPositionCursorPaginationPartyLastCursor(t *testing.T) { 271 ctx := tempTransaction(t) 272 273 ps := sqlstore.NewPositions(connectionSource) 274 pts := sqlstore.NewParties(connectionSource) 275 bs := sqlstore.NewBlocks(connectionSource) 276 277 emptyMarketID := entities.MarketID("") 278 279 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 280 281 last := int32(3) 282 pagination, err := entities.NewCursorPagination(nil, nil, &last, nil, false) 283 require.NoError(t, err) 284 285 party := entities.Party{ID: entities.PartyID("deadbeef00")} 286 want := []entities.Position{ 287 positions[70], 288 positions[80], 289 positions[90], 290 } 291 292 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 293 require.NoError(t, err) 294 for i, g := range got { 295 assert.True(t, want[i].Equal(g)) 296 } 297 // assert.Equal(t, want, got) 298 assert.Equal(t, entities.PageInfo{ 299 HasNextPage: false, 300 HasPreviousPage: true, 301 StartCursor: want[0].Cursor().Encode(), 302 EndCursor: want[2].Cursor().Encode(), 303 }, pageInfo) 304 } 305 306 func testPositionCursorPaginationPartyFirstAfterCursor(t *testing.T) { 307 ctx := tempTransaction(t) 308 309 ps := sqlstore.NewPositions(connectionSource) 310 pts := sqlstore.NewParties(connectionSource) 311 bs := sqlstore.NewBlocks(connectionSource) 312 313 emptyMarketID := entities.MarketID("") 314 315 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 316 317 first := int32(3) 318 after := positions[20].Cursor().Encode() 319 pagination, err := entities.NewCursorPagination(&first, &after, nil, nil, false) 320 require.NoError(t, err) 321 322 party := entities.Party{ID: entities.PartyID("deadbeef00")} 323 want := []entities.Position{ 324 positions[30], 325 positions[40], 326 positions[50], 327 } 328 329 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 330 require.NoError(t, err) 331 for i, g := range got { 332 assert.True(t, want[i].Equal(g)) 333 } 334 // assert.Equal(t, want, got) 335 assert.Equal(t, entities.PageInfo{ 336 HasNextPage: true, 337 HasPreviousPage: true, 338 StartCursor: want[0].Cursor().Encode(), 339 EndCursor: want[2].Cursor().Encode(), 340 }, pageInfo) 341 } 342 343 func testPositionCursorPaginationPartyLastBeforeCursor(t *testing.T) { 344 ctx := tempTransaction(t) 345 346 ps := sqlstore.NewPositions(connectionSource) 347 pts := sqlstore.NewParties(connectionSource) 348 bs := sqlstore.NewBlocks(connectionSource) 349 350 emptyMarketID := entities.MarketID("") 351 352 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 353 354 last := int32(3) 355 before := positions[70].Cursor().Encode() 356 pagination, err := entities.NewCursorPagination(nil, nil, &last, &before, false) 357 require.NoError(t, err) 358 359 party := entities.Party{ID: entities.PartyID("deadbeef00")} 360 want := []entities.Position{ 361 positions[40], 362 positions[50], 363 positions[60], 364 } 365 366 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 367 require.NoError(t, err) 368 for i, g := range got { 369 assert.True(t, want[i].Equal(g)) 370 } 371 // assert.Equal(t, want, got) 372 assert.Equal(t, entities.PageInfo{ 373 HasNextPage: true, 374 HasPreviousPage: true, 375 StartCursor: want[0].Cursor().Encode(), 376 EndCursor: want[2].Cursor().Encode(), 377 }, pageInfo) 378 } 379 380 func testPositionCursorPaginationPartyMarketNoCursor(t *testing.T) { 381 ctx := tempTransaction(t) 382 383 ps := sqlstore.NewPositions(connectionSource) 384 pts := sqlstore.NewParties(connectionSource) 385 bs := sqlstore.NewBlocks(connectionSource) 386 387 emptyMarketID := entities.MarketID("deadbeef00") 388 389 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 390 391 pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, false) 392 require.NoError(t, err) 393 394 party := entities.Party{ID: entities.PartyID("deadbeef00")} 395 want := []entities.Position{ 396 positions[0], 397 } 398 399 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 400 require.NoError(t, err) 401 for i, g := range got { 402 assert.True(t, want[i].Equal(g)) 403 } 404 // assert.Equal(t, want, got) 405 assert.Equal(t, entities.PageInfo{ 406 HasNextPage: false, 407 HasPreviousPage: false, 408 StartCursor: want[0].Cursor().Encode(), 409 EndCursor: want[0].Cursor().Encode(), 410 }, pageInfo) 411 } 412 413 func testPositionCursorPaginationPartyNoCursorNewestFirst(t *testing.T) { 414 ctx := tempTransaction(t) 415 416 ps := sqlstore.NewPositions(connectionSource) 417 pts := sqlstore.NewParties(connectionSource) 418 bs := sqlstore.NewBlocks(connectionSource) 419 420 emptyMarketID := entities.MarketID("") 421 422 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 423 424 pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, true) 425 require.NoError(t, err) 426 427 party := entities.Party{ID: entities.PartyID("deadbeef00")} 428 want := []entities.Position{ 429 positions[0], 430 positions[10], 431 positions[20], 432 positions[30], 433 positions[40], 434 positions[50], 435 positions[60], 436 positions[70], 437 positions[80], 438 positions[90], 439 } 440 441 want = entities.ReverseSlice(want) 442 443 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 444 require.NoError(t, err) 445 for i, g := range got { 446 assert.True(t, g.Equal(want[i])) 447 } 448 // assert.Equal(t, want, got) 449 assert.Equal(t, entities.PageInfo{ 450 HasNextPage: false, 451 HasPreviousPage: false, 452 StartCursor: want[0].Cursor().Encode(), 453 EndCursor: want[9].Cursor().Encode(), 454 }, pageInfo) 455 } 456 457 func testPositionCursorPaginationPartyFirstCursorNewestFirst(t *testing.T) { 458 ctx := tempTransaction(t) 459 460 ps := sqlstore.NewPositions(connectionSource) 461 pts := sqlstore.NewParties(connectionSource) 462 bs := sqlstore.NewBlocks(connectionSource) 463 464 emptyMarketID := entities.MarketID("") 465 466 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 467 first := int32(3) 468 469 pagination, err := entities.NewCursorPagination(&first, nil, nil, nil, true) 470 require.NoError(t, err) 471 472 party := entities.Party{ID: entities.PartyID("deadbeef00")} 473 want := []entities.Position{ 474 positions[90], 475 positions[80], 476 positions[70], 477 } 478 479 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 480 require.NoError(t, err) 481 for i, g := range got { 482 assert.True(t, g.Equal(want[i])) 483 } 484 // assert.Equal(t, want, got) 485 assert.Equal(t, entities.PageInfo{ 486 HasNextPage: true, 487 HasPreviousPage: false, 488 StartCursor: want[0].Cursor().Encode(), 489 EndCursor: want[2].Cursor().Encode(), 490 }, pageInfo) 491 } 492 493 func testPositionCursorPaginationPartyLastCursorNewestFirst(t *testing.T) { 494 ctx := tempTransaction(t) 495 496 ps := sqlstore.NewPositions(connectionSource) 497 pts := sqlstore.NewParties(connectionSource) 498 bs := sqlstore.NewBlocks(connectionSource) 499 500 emptyMarketID := entities.MarketID("") 501 502 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 503 504 last := int32(3) 505 pagination, err := entities.NewCursorPagination(nil, nil, &last, nil, true) 506 require.NoError(t, err) 507 508 party := entities.Party{ID: entities.PartyID("deadbeef00")} 509 want := []entities.Position{ 510 positions[20], 511 positions[10], 512 positions[0], 513 } 514 515 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 516 require.NoError(t, err) 517 for i, g := range got { 518 assert.True(t, g.Equal(want[i])) 519 } 520 // assert.Equal(t, want, got) 521 assert.Equal(t, entities.PageInfo{ 522 HasNextPage: false, 523 HasPreviousPage: true, 524 StartCursor: want[0].Cursor().Encode(), 525 EndCursor: want[2].Cursor().Encode(), 526 }, pageInfo) 527 } 528 529 func testPositionCursorPaginationPartyFirstAfterCursorNewestFirst(t *testing.T) { 530 ctx := tempTransaction(t) 531 532 ps := sqlstore.NewPositions(connectionSource) 533 pts := sqlstore.NewParties(connectionSource) 534 bs := sqlstore.NewBlocks(connectionSource) 535 536 emptyMarketID := entities.MarketID("") 537 538 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 539 540 first := int32(3) 541 after := positions[70].Cursor().Encode() 542 pagination, err := entities.NewCursorPagination(&first, &after, nil, nil, true) 543 require.NoError(t, err) 544 545 party := entities.Party{ID: entities.PartyID("deadbeef00")} 546 want := []entities.Position{ 547 positions[60], 548 positions[50], 549 positions[40], 550 } 551 552 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 553 require.NoError(t, err) 554 for i, g := range got { 555 assert.True(t, g.Equal(want[i])) 556 } 557 // assert.Equal(t, want, got) 558 assert.Equal(t, entities.PageInfo{ 559 HasNextPage: true, 560 HasPreviousPage: true, 561 StartCursor: want[0].Cursor().Encode(), 562 EndCursor: want[2].Cursor().Encode(), 563 }, pageInfo) 564 } 565 566 func testPositionCursorPaginationPartyLastBeforeCursorNewestFirst(t *testing.T) { 567 ctx := tempTransaction(t) 568 569 ps := sqlstore.NewPositions(connectionSource) 570 pts := sqlstore.NewParties(connectionSource) 571 bs := sqlstore.NewBlocks(connectionSource) 572 573 emptyMarketID := entities.MarketID("") 574 575 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 576 577 last := int32(3) 578 before := positions[20].Cursor().Encode() 579 pagination, err := entities.NewCursorPagination(nil, nil, &last, &before, true) 580 require.NoError(t, err) 581 582 party := entities.Party{ID: entities.PartyID("deadbeef00")} 583 want := []entities.Position{ 584 positions[50], 585 positions[40], 586 positions[30], 587 } 588 589 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 590 require.NoError(t, err) 591 for i, g := range got { 592 assert.True(t, g.Equal(want[i])) 593 } 594 // assert.Equal(t, want, got) 595 assert.Equal(t, entities.PageInfo{ 596 HasNextPage: true, 597 HasPreviousPage: true, 598 StartCursor: want[0].Cursor().Encode(), 599 EndCursor: want[2].Cursor().Encode(), 600 }, pageInfo) 601 } 602 603 func testPositionCursorPaginationPartyMarketNoCursorNewestFirst(t *testing.T) { 604 ctx := tempTransaction(t) 605 606 ps := sqlstore.NewPositions(connectionSource) 607 pts := sqlstore.NewParties(connectionSource) 608 bs := sqlstore.NewBlocks(connectionSource) 609 610 emptyMarketID := entities.MarketID("deadbeef00") 611 612 positions := setupPositionPaginationData(t, ctx, bs, ps, pts) 613 614 pagination, err := entities.NewCursorPagination(nil, nil, nil, nil, true) 615 require.NoError(t, err) 616 617 party := entities.Party{ID: entities.PartyID("deadbeef00")} 618 want := []entities.Position{ 619 positions[0], 620 } 621 622 got, pageInfo, err := ps.GetByPartyConnection(ctx, []string{party.ID.String()}, []string{emptyMarketID.String()}, pagination) 623 require.NoError(t, err) 624 for i, g := range got { 625 assert.True(t, g.Equal(want[i])) 626 } 627 // assert.Equal(t, want, got) 628 assert.Equal(t, entities.PageInfo{ 629 HasNextPage: false, 630 HasPreviousPage: false, 631 StartCursor: want[0].Cursor().Encode(), 632 EndCursor: want[0].Cursor().Encode(), 633 }, pageInfo) 634 } 635 636 func TestPositionStatusEnum(t *testing.T) { 637 var positionStatus vegapb.PositionStatus 638 states := getEnums(t, positionStatus) 639 for s, state := range states { 640 t.Run(state, func(t *testing.T) { 641 ctx := tempTransaction(t) 642 643 ps := sqlstore.NewPositions(connectionSource) 644 qs := sqlstore.NewParties(connectionSource) 645 bs := sqlstore.NewBlocks(connectionSource) 646 647 block := addTestBlockForTime(t, ctx, bs, time.Now().Add((-26*time.Hour)-(2*time.Second))) 648 649 market := entities.Market{ID: entities.MarketID("dead")} 650 party := addTestParty(t, ctx, qs, block) 651 pos := entities.NewEmptyPosition(market.ID, party.ID) 652 volume := int64(100) 653 pos.OpenVolume = volume 654 pos.PendingOpenVolume = volume 655 pos.VegaTime = block.VegaTime 656 pos.RealisedPnl = decimal.New(0, 0) 657 pos.PendingRealisedPnl = decimal.New(0, 0) 658 pos.UnrealisedPnl = decimal.New(0, 0) 659 pos.PendingUnrealisedPnl = decimal.New(0, 0) 660 pos.AverageEntryPrice = decimal.New(0, 0) 661 pos.PendingAverageEntryPrice = decimal.New(0, 0) 662 pos.AverageEntryMarketPrice = decimal.New(0, 0) 663 pos.PendingAverageEntryMarketPrice = decimal.New(0, 0) 664 pos.Adjustment = decimal.New(0, 0) 665 pos.Loss = decimal.New(0, 0) 666 pos.TxHash = generateTxHash() 667 pos.DistressedStatus = entities.PositionStatus(s) 668 require.NoError(t, ps.Add(ctx, pos)) 669 _, err := ps.Flush(ctx) 670 require.NoError(t, err) 671 672 got, err := ps.GetByTxHash(ctx, pos.TxHash) 673 require.NoError(t, err) 674 assert.Len(t, got, 1) 675 assert.Equal(t, pos.DistressedStatus, got[0].DistressedStatus) 676 }) 677 } 678 }