code.vegaprotocol.io/vega@v0.79.0/datanode/entities/entities.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 entities
    17  
    18  import "google.golang.org/protobuf/proto"
    19  
    20  type Entities interface {
    21  	Market | Party | Trade | Order | MarketData | Reward | Candle | Deposit |
    22  		Withdrawal | Asset | OracleSpec | OracleData | Position | LiquidityProvision | Vote |
    23  		AccountBalance | Proposal | Delegation | Node | NetworkParameter | Checkpoint |
    24  		StakeLinking | NodeSignature | KeyRotation | ERC20MultiSigSignerAddedEvent |
    25  		ERC20MultiSigSignerRemovedEvent | EthereumKeyRotation | AggregatedBalance | AggregatedLedgerEntry |
    26  		ProtocolUpgradeProposal | CoreSnapshotData | EpochRewardSummary | SuccessorMarket | StopOrder |
    27  		LiquidityProvider | FundingPeriod | FundingPeriodDataPoint | ReferralSet | ReferralSetRefereeStats |
    28  		FlattenReferralSetStats | Team | TeamMember | TeamMemberHistory | FundingPayment | FlattenVolumeDiscountStats |
    29  		PaidLiquidityFeesStats | CurrentAndPreviousLiquidityProvisions | TransferDetails | Game | TeamsStatistics | TeamMembersStatistics |
    30  		PartyMarginMode | PartyProfile | GamePartyScore | GameTeamScore | AMMPool | FlattenVolumeRebateStats
    31  }
    32  
    33  type PagedEntity[T proto.Message] interface {
    34  	Entities | Transfer | MarginLevels
    35  
    36  	// ToProtoEdge may need some optional arguments in order to generate the proto, for example margin levels
    37  	// requires an account source. This is not ideal, but we can come back to this later if a better solution can be found.
    38  	ToProtoEdge(...any) (T, error)
    39  	Cursor() *Cursor
    40  }
    41  
    42  type ProtoEntity[T proto.Message] interface {
    43  	Entities | Account | NodeBasic
    44  	ToProto() T
    45  }
    46  
    47  func PageEntities[T proto.Message, U PagedEntity[T]](items []U, pagination CursorPagination) ([]U, PageInfo) {
    48  	var pagedItems []U
    49  	var limit int
    50  	var pageInfo PageInfo
    51  
    52  	if len(items) == 0 {
    53  		return pagedItems, pageInfo
    54  	}
    55  
    56  	if pagination.HasForward() && pagination.Forward.Limit != nil {
    57  		limit = int(*pagination.Forward.Limit)
    58  		switch len(items) {
    59  		case limit + 2:
    60  			pagedItems = items[1 : limit+1]
    61  			pageInfo.HasNextPage = true
    62  			pageInfo.HasPreviousPage = true
    63  		case limit + 1:
    64  			if !pagination.Forward.HasCursor() {
    65  				pagedItems = items[0:limit]
    66  				pageInfo.HasNextPage = true
    67  				pageInfo.HasPreviousPage = false
    68  			} else {
    69  				pagedItems = items[1:]
    70  				pageInfo.HasNextPage = false
    71  				pageInfo.HasPreviousPage = true
    72  			}
    73  		default:
    74  			// if the pagination for the first item is the same as the after pagination, then we have a previous page, and we shouldn't include it
    75  			if pagination.HasForward() && pagination.Forward.HasCursor() && pagination.Forward.Cursor.Value() == items[0].Cursor().Value() {
    76  				pagedItems = items[1:]
    77  				pageInfo.HasNextPage = false
    78  				pageInfo.HasPreviousPage = true
    79  			} else {
    80  				pagedItems = items
    81  				pageInfo.HasNextPage = false
    82  				pageInfo.HasPreviousPage = false
    83  			}
    84  		}
    85  	} else if pagination.HasBackward() && pagination.Backward.Limit != nil {
    86  		limit = int(*pagination.Backward.Limit)
    87  		switch len(items) {
    88  		case limit + 2:
    89  			pagedItems = ReverseSlice(items[1 : limit+1])
    90  			pageInfo.HasNextPage = true
    91  			pageInfo.HasPreviousPage = true
    92  		case limit + 1:
    93  			if !pagination.Backward.HasCursor() {
    94  				pagedItems = ReverseSlice(items[0:limit])
    95  				pageInfo.HasNextPage = false
    96  				pageInfo.HasPreviousPage = true
    97  			} else {
    98  				pagedItems = ReverseSlice(items[1:])
    99  				pageInfo.HasNextPage = true
   100  				pageInfo.HasPreviousPage = false
   101  			}
   102  		default:
   103  			if pagination.HasBackward() && pagination.Backward.HasCursor() && pagination.Backward.Cursor.Value() == items[0].Cursor().Value() {
   104  				pagedItems = ReverseSlice(items[1:])
   105  				pageInfo.HasNextPage = true
   106  				pageInfo.HasPreviousPage = false
   107  			} else {
   108  				pagedItems = ReverseSlice(items)
   109  				pageInfo.HasNextPage = false
   110  				pageInfo.HasPreviousPage = false
   111  			}
   112  		}
   113  	} else {
   114  		pagedItems = items
   115  		pageInfo.HasNextPage = false
   116  		pageInfo.HasPreviousPage = false
   117  	}
   118  
   119  	if len(pagedItems) > 0 {
   120  		startCursor := pagedItems[0].Cursor()
   121  		endCursor := pagedItems[len(pagedItems)-1].Cursor()
   122  		pageInfo.StartCursor = startCursor.Encode()
   123  		pageInfo.EndCursor = endCursor.Encode()
   124  	}
   125  
   126  	return pagedItems, pageInfo
   127  }
   128  
   129  func ReverseSlice[T any](input []T) (reversed []T) {
   130  	reversed = make([]T, len(input))
   131  	copy(reversed, input)
   132  	for i, j := 0, len(input)-1; i < j; i, j = i+1, j-1 {
   133  		reversed[i], reversed[j] = input[j], input[i]
   134  	}
   135  	return
   136  }