diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/liquidations.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/liquidations.ts index 7d76bd2b9d..ec85cd5d7c 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/liquidations.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/liquidations.ts @@ -83,6 +83,30 @@ export interface SubaccountLiquidationInfoSDKType { quantums_insurance_lost: Long; } +/** SubaccountOpenPositionInfo holds information about open positions for a perpetual. */ + +export interface SubaccountOpenPositionInfo { + /** The id of the perpetual. */ + perpetualId: number; + /** The ids of the subaccounts with long positions. */ + + subaccountsWithLongPosition: SubaccountId[]; + /** The ids of the subaccounts with short positions. */ + + subaccountsWithShortPosition: SubaccountId[]; +} +/** SubaccountOpenPositionInfo holds information about open positions for a perpetual. */ + +export interface SubaccountOpenPositionInfoSDKType { + /** The id of the perpetual. */ + perpetual_id: number; + /** The ids of the subaccounts with long positions. */ + + subaccounts_with_long_position: SubaccountIdSDKType[]; + /** The ids of the subaccounts with short positions. */ + + subaccounts_with_short_position: SubaccountIdSDKType[]; +} function createBasePerpetualLiquidationInfo(): PerpetualLiquidationInfo { return { @@ -215,4 +239,69 @@ export const SubaccountLiquidationInfo = { return message; } +}; + +function createBaseSubaccountOpenPositionInfo(): SubaccountOpenPositionInfo { + return { + perpetualId: 0, + subaccountsWithLongPosition: [], + subaccountsWithShortPosition: [] + }; +} + +export const SubaccountOpenPositionInfo = { + encode(message: SubaccountOpenPositionInfo, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.perpetualId !== 0) { + writer.uint32(8).uint32(message.perpetualId); + } + + for (const v of message.subaccountsWithLongPosition) { + SubaccountId.encode(v!, writer.uint32(18).fork()).ldelim(); + } + + for (const v of message.subaccountsWithShortPosition) { + SubaccountId.encode(v!, writer.uint32(26).fork()).ldelim(); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): SubaccountOpenPositionInfo { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseSubaccountOpenPositionInfo(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.perpetualId = reader.uint32(); + break; + + case 2: + message.subaccountsWithLongPosition.push(SubaccountId.decode(reader, reader.uint32())); + break; + + case 3: + message.subaccountsWithShortPosition.push(SubaccountId.decode(reader, reader.uint32())); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): SubaccountOpenPositionInfo { + const message = createBaseSubaccountOpenPositionInfo(); + message.perpetualId = object.perpetualId ?? 0; + message.subaccountsWithLongPosition = object.subaccountsWithLongPosition?.map(e => SubaccountId.fromPartial(e)) || []; + message.subaccountsWithShortPosition = object.subaccountsWithShortPosition?.map(e => SubaccountId.fromPartial(e)) || []; + return message; + } + }; \ No newline at end of file diff --git a/proto/dydxprotocol/clob/liquidations.proto b/proto/dydxprotocol/clob/liquidations.proto index c607c99027..0e7a8aa6db 100644 --- a/proto/dydxprotocol/clob/liquidations.proto +++ b/proto/dydxprotocol/clob/liquidations.proto @@ -32,3 +32,15 @@ message SubaccountLiquidationInfo { // covering this subaccount. uint64 quantums_insurance_lost = 3; } + +// SubaccountOpenPositionInfo holds information about open positions for a perpetual. +message SubaccountOpenPositionInfo { + // The id of the perpetual. + uint32 perpetual_id = 1; + // The ids of the subaccounts with long positions. + repeated dydxprotocol.subaccounts.SubaccountId subaccounts_with_long_position = 2 + [ (gogoproto.nullable) = false ]; + // The ids of the subaccounts with short positions. + repeated dydxprotocol.subaccounts.SubaccountId subaccounts_with_short_position = 3 + [ (gogoproto.nullable) = false ]; +} diff --git a/protocol/app/app.go b/protocol/app/app.go index 6a6b04fb61..85c138aa61 100644 --- a/protocol/app/app.go +++ b/protocol/app/app.go @@ -583,8 +583,8 @@ func New( // potentially liquidatable subaccounts and then encode them into an in-memory slice shared by // the liquidations module. // The in-memory data structure is shared by the x/clob module and liquidations daemon. - liquidatableSubaccountIds := liquidationtypes.NewLiquidatableSubaccountIds() - app.Server.WithLiquidatableSubaccountIds(liquidatableSubaccountIds) + daemonLiquidationInfo := liquidationtypes.NewDaemonLiquidationInfo() + app.Server.WithDaemonLiquidationInfo(daemonLiquidationInfo) // Setup server for bridge messages. // The in-memory data structure is shared by the x/bridge module and bridge daemon. @@ -868,7 +868,7 @@ func New( app.AccountKeeper, app.BankKeeper, app.SubaccountsKeeper, - liquidatableSubaccountIds, + daemonLiquidationInfo, ) app.PerpetualsKeeper.SetClobKeeper(app.ClobKeeper) diff --git a/protocol/daemons/server/liquidation.go b/protocol/daemons/server/liquidation.go index 4cb44acfa1..86f1231dcf 100644 --- a/protocol/daemons/server/liquidation.go +++ b/protocol/daemons/server/liquidation.go @@ -2,6 +2,7 @@ package server import ( "context" + "github.com/cosmos/cosmos-sdk/telemetry" "github.com/dydxprotocol/v4-chain/protocol/daemons/liquidation/api" "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types" @@ -11,16 +12,16 @@ import ( // LiquidationServer defines the fields required for liquidation updates. type LiquidationServer struct { - liquidatableSubaccountIds *liquidationtypes.LiquidatableSubaccountIds + daemonLiquidationInfo *liquidationtypes.DaemonLiquidationInfo } -// WithLiquidatableSubaccountIds sets the `liquidatableSubaccountIds` field. +// WithDaemonLiquidationInfo sets the `daemonLiquidationInfo` field. // This is updated by the liquidation service with a list of potentially liquidatable // subaccount ids to be processed by the `PerpetualLiquidationsKeeper`. -func (server *Server) WithLiquidatableSubaccountIds( - liquidatableSubaccountIds *liquidationtypes.LiquidatableSubaccountIds, +func (server *Server) WithDaemonLiquidationInfo( + daemonLiquidationInfo *liquidationtypes.DaemonLiquidationInfo, ) *Server { - server.liquidatableSubaccountIds = liquidatableSubaccountIds + server.daemonLiquidationInfo = daemonLiquidationInfo return server } @@ -41,7 +42,7 @@ func (s *Server) LiquidateSubaccounts( metrics.Count, ) - s.liquidatableSubaccountIds.UpdateSubaccountIds(req.SubaccountIds) + s.daemonLiquidationInfo.UpdateLiquidatableSubaccountIds(req.SubaccountIds) // Capture valid responses in metrics. s.reportValidResponse(types.LiquidationsDaemonServiceName) diff --git a/protocol/daemons/server/liquidation_test.go b/protocol/daemons/server/liquidation_test.go index a34a1e6009..ee85eeef47 100644 --- a/protocol/daemons/server/liquidation_test.go +++ b/protocol/daemons/server/liquidation_test.go @@ -15,33 +15,33 @@ import ( func TestLiquidateSubaccounts_Empty_Update(t *testing.T) { mockGrpcServer := &mocks.GrpcServer{} mockFileHandler := &mocks.FileHandler{} - liquidatableSubaccountIds := liquidationtypes.NewLiquidatableSubaccountIds() + daemonLiquidationInfo := liquidationtypes.NewDaemonLiquidationInfo() s := createServerWithMocks( t, mockGrpcServer, mockFileHandler, - ).WithLiquidatableSubaccountIds( - liquidatableSubaccountIds, + ).WithDaemonLiquidationInfo( + daemonLiquidationInfo, ) _, err := s.LiquidateSubaccounts(grpc.Ctx, &api.LiquidateSubaccountsRequest{ SubaccountIds: []satypes.SubaccountId{}, }) require.NoError(t, err) - require.Empty(t, liquidatableSubaccountIds.GetSubaccountIds()) + require.Empty(t, daemonLiquidationInfo.GetLiquidatableSubaccountIds()) } func TestLiquidateSubaccounts_Multiple_Subaccount_Ids(t *testing.T) { mockGrpcServer := &mocks.GrpcServer{} mockFileHandler := &mocks.FileHandler{} - liquidatableSubaccountIds := liquidationtypes.NewLiquidatableSubaccountIds() + daemonLiquidationInfo := liquidationtypes.NewDaemonLiquidationInfo() s := createServerWithMocks( t, mockGrpcServer, mockFileHandler, - ).WithLiquidatableSubaccountIds( - liquidatableSubaccountIds, + ).WithDaemonLiquidationInfo( + daemonLiquidationInfo, ) expectedSubaccountIds := []satypes.SubaccountId{ @@ -54,6 +54,6 @@ func TestLiquidateSubaccounts_Multiple_Subaccount_Ids(t *testing.T) { }) require.NoError(t, err) - actualSubaccountIds := liquidatableSubaccountIds.GetSubaccountIds() + actualSubaccountIds := daemonLiquidationInfo.GetLiquidatableSubaccountIds() require.Equal(t, expectedSubaccountIds, actualSubaccountIds) } diff --git a/protocol/daemons/server/types/liquidations/daemon_liquidation_info.go b/protocol/daemons/server/types/liquidations/daemon_liquidation_info.go new file mode 100644 index 0000000000..7ed80e3985 --- /dev/null +++ b/protocol/daemons/server/types/liquidations/daemon_liquidation_info.go @@ -0,0 +1,117 @@ +package types + +import ( + "sync" + + clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" + satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" +) + +// DaemonLiquidationInfo maintains the list of subaccount ids to be liquidated +// in the next block. Methods are goroutine safe. +type DaemonLiquidationInfo struct { + sync.Mutex // lock + blockHeight uint32 // block height of the last update + liquidatableSubaccountIds []satypes.SubaccountId // liquidatable subaccount ids + negativeTncSubaccountIds []satypes.SubaccountId // negative total net collateral subaccount ids + subaccountsWithPositions map[uint32]clobtypes.SubaccountOpenPositionInfo +} + +// NewDaemonLiquidationInfo creates a new `LiquidatableSubaccountIds` struct. +func NewDaemonLiquidationInfo() *DaemonLiquidationInfo { + return &DaemonLiquidationInfo{ + liquidatableSubaccountIds: make([]satypes.SubaccountId, 0), + negativeTncSubaccountIds: make([]satypes.SubaccountId, 0), + subaccountsWithPositions: make(map[uint32]clobtypes.SubaccountOpenPositionInfo), + } +} + +// UpdateBlockHeight updates the struct with the given block height. +func (ls *DaemonLiquidationInfo) UpdateBlockHeight(blockHeight uint32) { + ls.Lock() + defer ls.Unlock() + ls.blockHeight = blockHeight +} + +// GetBlockHeight returns the block height of the last update. +func (ls *DaemonLiquidationInfo) GetBlockHeight() uint32 { + ls.Lock() + defer ls.Unlock() + return ls.blockHeight +} + +// UpdateLiquidatableSubaccountIds updates the struct with the given a list of potentially +// liquidatable subaccount ids. +func (ls *DaemonLiquidationInfo) UpdateLiquidatableSubaccountIds(updates []satypes.SubaccountId) { + ls.Lock() + defer ls.Unlock() + ls.liquidatableSubaccountIds = make([]satypes.SubaccountId, len(updates)) + copy(ls.liquidatableSubaccountIds, updates) +} + +// GetLiquidatableSubaccountIds returns the list of potentially liquidatable subaccount ids +// reported by the liquidation daemon. +func (ls *DaemonLiquidationInfo) GetLiquidatableSubaccountIds() []satypes.SubaccountId { + ls.Lock() + defer ls.Unlock() + results := make([]satypes.SubaccountId, len(ls.liquidatableSubaccountIds)) + copy(results, ls.liquidatableSubaccountIds) + return results +} + +// UpdateNegativeTncSubaccountIds updates the struct with the given a list of subaccount ids +// with negative total net collateral. +func (ls *DaemonLiquidationInfo) UpdateNegativeTncSubaccountIds(updates []satypes.SubaccountId) { + ls.Lock() + defer ls.Unlock() + ls.negativeTncSubaccountIds = make([]satypes.SubaccountId, len(updates)) + copy(ls.negativeTncSubaccountIds, updates) +} + +// GetNegativeTncSubaccountIds returns the list of subaccount ids with negative total net collateral +// reported by the liquidation daemon. +func (ls *DaemonLiquidationInfo) GetNegativeTncSubaccountIds() []satypes.SubaccountId { + ls.Lock() + defer ls.Unlock() + results := make([]satypes.SubaccountId, len(ls.negativeTncSubaccountIds)) + copy(results, ls.negativeTncSubaccountIds) + return results +} + +// UpdateSubaccountsWithPositions updates the struct with the given a list of subaccount ids with open positions. +func (ls *DaemonLiquidationInfo) UpdateSubaccountsWithPositions( + subaccountsWithPositions map[uint32]clobtypes.SubaccountOpenPositionInfo, +) { + ls.Lock() + defer ls.Unlock() + ls.subaccountsWithPositions = make(map[uint32]clobtypes.SubaccountOpenPositionInfo) + for perpetualId, info := range subaccountsWithPositions { + clone := clobtypes.SubaccountOpenPositionInfo{ + PerpetualId: perpetualId, + SubaccountsWithLongPosition: make([]satypes.SubaccountId, len(info.SubaccountsWithLongPosition)), + SubaccountsWithShortPosition: make([]satypes.SubaccountId, len(info.SubaccountsWithShortPosition)), + } + copy(clone.SubaccountsWithLongPosition, info.SubaccountsWithLongPosition) + copy(clone.SubaccountsWithShortPosition, info.SubaccountsWithShortPosition) + ls.subaccountsWithPositions[perpetualId] = clone + } +} + +// GetSubaccountsWithPositions returns the list of subaccount ids with open positions. +func (ls *DaemonLiquidationInfo) GetSubaccountsWithPositions() map[uint32]clobtypes.SubaccountOpenPositionInfo { + ls.Lock() + defer ls.Unlock() + + result := make(map[uint32]clobtypes.SubaccountOpenPositionInfo) + for perpetualId, info := range ls.subaccountsWithPositions { + clone := clobtypes.SubaccountOpenPositionInfo{ + PerpetualId: perpetualId, + SubaccountsWithLongPosition: make([]satypes.SubaccountId, len(info.SubaccountsWithLongPosition)), + SubaccountsWithShortPosition: make([]satypes.SubaccountId, len(info.SubaccountsWithShortPosition)), + } + copy(clone.SubaccountsWithLongPosition, info.SubaccountsWithLongPosition) + copy(clone.SubaccountsWithShortPosition, info.SubaccountsWithShortPosition) + result[perpetualId] = clone + } + return result +} diff --git a/protocol/daemons/server/types/liquidations/daemon_liquidation_info_test.go b/protocol/daemons/server/types/liquidations/daemon_liquidation_info_test.go new file mode 100644 index 0000000000..9148c623b7 --- /dev/null +++ b/protocol/daemons/server/types/liquidations/daemon_liquidation_info_test.go @@ -0,0 +1,213 @@ +package types_test + +import ( + "testing" + + liquidationstypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/liquidations" + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" + clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" + satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" + "github.com/stretchr/testify/require" +) + +func TestNewDaemonLiquidationInfo(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetLiquidatableSubaccountIds()) + require.Empty(t, ls.GetNegativeTncSubaccountIds()) + require.Empty(t, ls.GetSubaccountsWithPositions()) +} + +func TestLiquidatableSubaccountIds_Multiple_Reads(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetLiquidatableSubaccountIds()) + + expectedSubaccountIds := []satypes.SubaccountId{ + constants.Alice_Num1, + constants.Bob_Num0, + } + ls.UpdateLiquidatableSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetLiquidatableSubaccountIds()) + require.Equal(t, expectedSubaccountIds, ls.GetLiquidatableSubaccountIds()) + require.Equal(t, expectedSubaccountIds, ls.GetLiquidatableSubaccountIds()) +} + +func TestNegativeTncSubaccounts_Multiple_Reads(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetNegativeTncSubaccountIds()) + + expectedSubaccountIds := []satypes.SubaccountId{ + constants.Alice_Num1, + constants.Bob_Num0, + } + ls.UpdateNegativeTncSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetNegativeTncSubaccountIds()) + require.Equal(t, expectedSubaccountIds, ls.GetNegativeTncSubaccountIds()) + require.Equal(t, expectedSubaccountIds, ls.GetNegativeTncSubaccountIds()) +} + +func TestSubaccountsWithOpenPositions_Multiple_Reads(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetNegativeTncSubaccountIds()) + + expected := map[uint32]clobtypes.SubaccountOpenPositionInfo{ + 0: { + PerpetualId: 0, + SubaccountsWithLongPosition: []satypes.SubaccountId{ + constants.Alice_Num1, + }, + SubaccountsWithShortPosition: []satypes.SubaccountId{ + constants.Bob_Num0, + }, + }, + } + ls.UpdateSubaccountsWithPositions(expected) + require.Equal(t, expected, ls.GetSubaccountsWithPositions()) + require.Equal(t, expected, ls.GetSubaccountsWithPositions()) + require.Equal(t, expected, ls.GetSubaccountsWithPositions()) +} + +func TestLiquidatableSubaccountIds_Multiple_Writes(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetLiquidatableSubaccountIds()) + + expectedSubaccountIds := []satypes.SubaccountId{ + constants.Alice_Num1, + } + ls.UpdateLiquidatableSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetLiquidatableSubaccountIds()) + + expectedSubaccountIds = []satypes.SubaccountId{ + constants.Bob_Num0, + } + ls.UpdateLiquidatableSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetLiquidatableSubaccountIds()) + + expectedSubaccountIds = []satypes.SubaccountId{ + constants.Carl_Num0, + } + ls.UpdateLiquidatableSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetLiquidatableSubaccountIds()) +} + +func TestNegativeTncSubaccounts_Multiple_Writes(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetNegativeTncSubaccountIds()) + + expectedSubaccountIds := []satypes.SubaccountId{ + constants.Alice_Num1, + } + ls.UpdateNegativeTncSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetNegativeTncSubaccountIds()) + + expectedSubaccountIds = []satypes.SubaccountId{ + constants.Bob_Num0, + } + ls.UpdateNegativeTncSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetNegativeTncSubaccountIds()) + + expectedSubaccountIds = []satypes.SubaccountId{ + constants.Carl_Num0, + } + ls.UpdateNegativeTncSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetNegativeTncSubaccountIds()) +} + +func TestSubaccountsWithOpenPositions_Multiple_Writes(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetSubaccountsWithPositions()) + + expected := map[uint32]clobtypes.SubaccountOpenPositionInfo{ + 0: { + PerpetualId: 0, + SubaccountsWithLongPosition: []satypes.SubaccountId{ + constants.Alice_Num1, + }, + SubaccountsWithShortPosition: []satypes.SubaccountId{ + constants.Bob_Num0, + }, + }, + } + ls.UpdateSubaccountsWithPositions(expected) + require.Equal(t, expected, ls.GetSubaccountsWithPositions()) + + expected = map[uint32]clobtypes.SubaccountOpenPositionInfo{ + 0: { + PerpetualId: 0, + SubaccountsWithLongPosition: []satypes.SubaccountId{ + constants.Carl_Num0, + }, + SubaccountsWithShortPosition: []satypes.SubaccountId{ + constants.Dave_Num0, + }, + }, + } + ls.UpdateSubaccountsWithPositions(expected) + require.Equal(t, expected, ls.GetSubaccountsWithPositions()) + + expected = map[uint32]clobtypes.SubaccountOpenPositionInfo{ + 0: { + PerpetualId: 0, + SubaccountsWithLongPosition: []satypes.SubaccountId{ + constants.Dave_Num1, + }, + SubaccountsWithShortPosition: []satypes.SubaccountId{ + constants.Alice_Num1, + }, + }, + } + ls.UpdateSubaccountsWithPositions(expected) + require.Equal(t, expected, ls.GetSubaccountsWithPositions()) +} + +func TestLiquidatableSubaccountIds_Empty_Update(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetLiquidatableSubaccountIds()) + + expectedSubaccountIds := []satypes.SubaccountId{ + constants.Alice_Num1, + } + ls.UpdateLiquidatableSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetLiquidatableSubaccountIds()) + + expectedSubaccountIds = []satypes.SubaccountId{} + ls.UpdateLiquidatableSubaccountIds(expectedSubaccountIds) + require.Empty(t, ls.GetLiquidatableSubaccountIds()) +} + +func TestNegativeTnc_Empty_Update(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetNegativeTncSubaccountIds()) + + expectedSubaccountIds := []satypes.SubaccountId{ + constants.Alice_Num1, + } + ls.UpdateNegativeTncSubaccountIds(expectedSubaccountIds) + require.Equal(t, expectedSubaccountIds, ls.GetNegativeTncSubaccountIds()) + + expectedSubaccountIds = []satypes.SubaccountId{} + ls.UpdateNegativeTncSubaccountIds(expectedSubaccountIds) + require.Empty(t, ls.GetNegativeTncSubaccountIds()) +} + +func TestSubaccountsWithOpenPosition_Empty_Update(t *testing.T) { + ls := liquidationstypes.NewDaemonLiquidationInfo() + require.Empty(t, ls.GetSubaccountsWithPositions()) + + expected := map[uint32]clobtypes.SubaccountOpenPositionInfo{ + 0: { + PerpetualId: 0, + SubaccountsWithLongPosition: []satypes.SubaccountId{ + constants.Alice_Num1, + }, + SubaccountsWithShortPosition: []satypes.SubaccountId{ + constants.Bob_Num0, + }, + }, + } + ls.UpdateSubaccountsWithPositions(expected) + require.Equal(t, expected, ls.GetSubaccountsWithPositions()) + + expected = map[uint32]clobtypes.SubaccountOpenPositionInfo{} + ls.UpdateSubaccountsWithPositions(expected) + require.Empty(t, ls.GetSubaccountsWithPositions()) +} diff --git a/protocol/daemons/server/types/liquidations/liquidatable_subaccount_ids.go b/protocol/daemons/server/types/liquidations/liquidatable_subaccount_ids.go deleted file mode 100644 index a3906d09c7..0000000000 --- a/protocol/daemons/server/types/liquidations/liquidatable_subaccount_ids.go +++ /dev/null @@ -1,39 +0,0 @@ -package types - -import ( - "sync" - - satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" -) - -// LiquidatableSubaccountIds maintains the list of subaccount ids to be liquidated -// in the next block. Methods are goroutine safe. -type LiquidatableSubaccountIds struct { - sync.Mutex // lock - subaccountIds []satypes.SubaccountId // liquidatable subaccount ids -} - -// NewLiquidatableSubaccountIds creates a new `LiquidatableSubaccountIds` struct. -func NewLiquidatableSubaccountIds() *LiquidatableSubaccountIds { - return &LiquidatableSubaccountIds{ - subaccountIds: make([]satypes.SubaccountId, 0), - } -} - -// UpdateSubaccountIds updates the struct with the given a list of potentially liquidatable subaccount ids. -func (ls *LiquidatableSubaccountIds) UpdateSubaccountIds(updates []satypes.SubaccountId) { - ls.Lock() - defer ls.Unlock() - ls.subaccountIds = make([]satypes.SubaccountId, len(updates)) - copy(ls.subaccountIds, updates) -} - -// GetSubaccountIds returns the list of potentially liquidatable subaccount ids -// reported by the liquidation daemon. -func (ls *LiquidatableSubaccountIds) GetSubaccountIds() []satypes.SubaccountId { - ls.Lock() - defer ls.Unlock() - results := make([]satypes.SubaccountId, len(ls.subaccountIds)) - copy(results, ls.subaccountIds) - return results -} diff --git a/protocol/daemons/server/types/liquidations/liquidatable_subaccount_ids_test.go b/protocol/daemons/server/types/liquidations/liquidatable_subaccount_ids_test.go deleted file mode 100644 index 5f268e9ef0..0000000000 --- a/protocol/daemons/server/types/liquidations/liquidatable_subaccount_ids_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package types_test - -import ( - "testing" - - liquidationstypes "github.com/dydxprotocol/v4-chain/protocol/daemons/server/types/liquidations" - "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" - satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" - "github.com/stretchr/testify/require" -) - -func TestNewLiquidatableSubaccountIds(t *testing.T) { - ls := liquidationstypes.NewLiquidatableSubaccountIds() - require.Empty(t, ls.GetSubaccountIds()) -} - -func TestLiquidatableSubaccountIds_Multiple_Reads(t *testing.T) { - ls := liquidationstypes.NewLiquidatableSubaccountIds() - require.Empty(t, ls.GetSubaccountIds()) - - expectedSubaccountIds := []satypes.SubaccountId{ - constants.Alice_Num1, - constants.Bob_Num0, - } - ls.UpdateSubaccountIds(expectedSubaccountIds) - require.Equal(t, expectedSubaccountIds, ls.GetSubaccountIds()) - require.Equal(t, expectedSubaccountIds, ls.GetSubaccountIds()) - require.Equal(t, expectedSubaccountIds, ls.GetSubaccountIds()) -} - -func TestLiquidatableSubaccountIds_Multiple_Writes(t *testing.T) { - ls := liquidationstypes.NewLiquidatableSubaccountIds() - require.Empty(t, ls.GetSubaccountIds()) - - expectedSubaccountIds := []satypes.SubaccountId{ - constants.Alice_Num1, - } - ls.UpdateSubaccountIds(expectedSubaccountIds) - require.Equal(t, expectedSubaccountIds, ls.GetSubaccountIds()) - - expectedSubaccountIds = []satypes.SubaccountId{ - constants.Bob_Num0, - } - ls.UpdateSubaccountIds(expectedSubaccountIds) - require.Equal(t, expectedSubaccountIds, ls.GetSubaccountIds()) - - expectedSubaccountIds = []satypes.SubaccountId{ - constants.Carl_Num0, - } - ls.UpdateSubaccountIds(expectedSubaccountIds) - require.Equal(t, expectedSubaccountIds, ls.GetSubaccountIds()) -} - -func TestLiquidatableSubaccountIds_Empty_Update(t *testing.T) { - ls := liquidationstypes.NewLiquidatableSubaccountIds() - require.Empty(t, ls.GetSubaccountIds()) - - expectedSubaccountIds := []satypes.SubaccountId{ - constants.Alice_Num1, - } - ls.UpdateSubaccountIds(expectedSubaccountIds) - require.Equal(t, expectedSubaccountIds, ls.GetSubaccountIds()) - - expectedSubaccountIds = []satypes.SubaccountId{} - ls.UpdateSubaccountIds(expectedSubaccountIds) - require.Empty(t, ls.GetSubaccountIds()) -} diff --git a/protocol/x/clob/abci.go b/protocol/x/clob/abci.go index b22303d983..f266ecc732 100644 --- a/protocol/x/clob/abci.go +++ b/protocol/x/clob/abci.go @@ -117,7 +117,7 @@ func EndBlocker( func PrepareCheckState( ctx sdk.Context, keeper *keeper.Keeper, - liquidatableSubaccountIds *liquidationtypes.LiquidatableSubaccountIds, + daemonLiquidationInfo *liquidationtypes.DaemonLiquidationInfo, ) { // Get the events generated from processing the matches in the latest block. processProposerMatchesEvents := keeper.GetProcessProposerMatchesEvents(ctx) @@ -197,7 +197,7 @@ func PrepareCheckState( } // 6. Get all potentially liquidatable subaccount IDs and attempt to liquidate them. - subaccountIds := liquidatableSubaccountIds.GetSubaccountIds() + subaccountIds := daemonLiquidationInfo.GetLiquidatableSubaccountIds() if err := keeper.LiquidateSubaccountsAgainstOrderbook(ctx, subaccountIds); err != nil { panic(err) } diff --git a/protocol/x/clob/abci_test.go b/protocol/x/clob/abci_test.go index ef0c143851..07b3626a22 100644 --- a/protocol/x/clob/abci_test.go +++ b/protocol/x/clob/abci_test.go @@ -1099,7 +1099,7 @@ func TestPrepareCheckState_WithProcessProposerMatchesEventsWithBadBlockHeight(t clob.PrepareCheckState( ks.Ctx.WithBlockHeight(int64(blockHeight+1)), ks.ClobKeeper, - liquidationtypes.NewLiquidatableSubaccountIds(), + liquidationtypes.NewDaemonLiquidationInfo(), ) }) } @@ -1126,7 +1126,7 @@ func TestCommitBlocker_WithProcessProposerMatchesEventsWithBadBlockHeight(t *tes clob.PrepareCheckState( ks.Ctx.WithBlockHeight(int64(blockHeight+1)), ks.ClobKeeper, - liquidationtypes.NewLiquidatableSubaccountIds(), + liquidationtypes.NewDaemonLiquidationInfo(), ) }) } @@ -1475,8 +1475,8 @@ func TestPrepareCheckState(t *testing.T) { } // Set the liquidatable subaccount IDs. - liquidatableSubaccountIds := liquidationtypes.NewLiquidatableSubaccountIds() - liquidatableSubaccountIds.UpdateSubaccountIds(tc.liquidatableSubaccounts) + liquidatableSubaccountIds := liquidationtypes.NewDaemonLiquidationInfo() + liquidatableSubaccountIds.UpdateLiquidatableSubaccountIds(tc.liquidatableSubaccounts) // Run the test. clob.PrepareCheckState( diff --git a/protocol/x/clob/module.go b/protocol/x/clob/module.go index aed9ea2de1..867fcb899c 100644 --- a/protocol/x/clob/module.go +++ b/protocol/x/clob/module.go @@ -104,11 +104,11 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { type AppModule struct { AppModuleBasic - keeper *keeper.Keeper - accountKeeper types.AccountKeeper - bankKeeper types.BankKeeper - subaccountsKeeper types.SubaccountsKeeper - liquidatableSubaccountIds *liquidationtypes.LiquidatableSubaccountIds + keeper *keeper.Keeper + accountKeeper types.AccountKeeper + bankKeeper types.BankKeeper + subaccountsKeeper types.SubaccountsKeeper + daemonLiquidationInfo *liquidationtypes.DaemonLiquidationInfo } func NewAppModule( @@ -117,15 +117,15 @@ func NewAppModule( accountKeeper types.AccountKeeper, bankKeeper types.BankKeeper, subaccountsKeeper types.SubaccountsKeeper, - liquidatableSubaccountIds *liquidationtypes.LiquidatableSubaccountIds, + daemonLiquidationInfo *liquidationtypes.DaemonLiquidationInfo, ) AppModule { return AppModule{ - AppModuleBasic: NewAppModuleBasic(cdc), - keeper: keeper, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - subaccountsKeeper: subaccountsKeeper, - liquidatableSubaccountIds: liquidatableSubaccountIds, + AppModuleBasic: NewAppModuleBasic(cdc), + keeper: keeper, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + subaccountsKeeper: subaccountsKeeper, + daemonLiquidationInfo: daemonLiquidationInfo, } } @@ -194,6 +194,6 @@ func (am AppModule) Commit(ctx sdk.Context) { PrepareCheckState( ctx, am.keeper, - am.liquidatableSubaccountIds, + am.daemonLiquidationInfo, ) } diff --git a/protocol/x/clob/module_test.go b/protocol/x/clob/module_test.go index f82ffa837a..5bcd88da94 100644 --- a/protocol/x/clob/module_test.go +++ b/protocol/x/clob/module_test.go @@ -103,7 +103,7 @@ func createAppModuleWithKeeper(t *testing.T) ( nil, nil, nil, - liquidations_types.NewLiquidatableSubaccountIds(), + liquidations_types.NewDaemonLiquidationInfo(), ), ks.ClobKeeper, ks.PricesKeeper, ks.PerpetualsKeeper, ks.Ctx, mockIndexerEventManager } diff --git a/protocol/x/clob/types/liquidations.pb.go b/protocol/x/clob/types/liquidations.pb.go index 316732cb6f..1fc1b71e4c 100644 --- a/protocol/x/clob/types/liquidations.pb.go +++ b/protocol/x/clob/types/liquidations.pb.go @@ -151,9 +151,74 @@ func (m *SubaccountLiquidationInfo) GetQuantumsInsuranceLost() uint64 { return 0 } +// SubaccountOpenPositionInfo holds information about open positions for a perpetual. +type SubaccountOpenPositionInfo struct { + // The id of the perpetual. + PerpetualId uint32 `protobuf:"varint,1,opt,name=perpetual_id,json=perpetualId,proto3" json:"perpetual_id,omitempty"` + // The ids of the subaccounts with long positions. + SubaccountsWithLongPosition []types.SubaccountId `protobuf:"bytes,2,rep,name=subaccounts_with_long_position,json=subaccountsWithLongPosition,proto3" json:"subaccounts_with_long_position"` + // The ids of the subaccounts with short positions. + SubaccountsWithShortPosition []types.SubaccountId `protobuf:"bytes,3,rep,name=subaccounts_with_short_position,json=subaccountsWithShortPosition,proto3" json:"subaccounts_with_short_position"` +} + +func (m *SubaccountOpenPositionInfo) Reset() { *m = SubaccountOpenPositionInfo{} } +func (m *SubaccountOpenPositionInfo) String() string { return proto.CompactTextString(m) } +func (*SubaccountOpenPositionInfo) ProtoMessage() {} +func (*SubaccountOpenPositionInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_e91628d349879778, []int{2} +} +func (m *SubaccountOpenPositionInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SubaccountOpenPositionInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SubaccountOpenPositionInfo.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SubaccountOpenPositionInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_SubaccountOpenPositionInfo.Merge(m, src) +} +func (m *SubaccountOpenPositionInfo) XXX_Size() int { + return m.Size() +} +func (m *SubaccountOpenPositionInfo) XXX_DiscardUnknown() { + xxx_messageInfo_SubaccountOpenPositionInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_SubaccountOpenPositionInfo proto.InternalMessageInfo + +func (m *SubaccountOpenPositionInfo) GetPerpetualId() uint32 { + if m != nil { + return m.PerpetualId + } + return 0 +} + +func (m *SubaccountOpenPositionInfo) GetSubaccountsWithLongPosition() []types.SubaccountId { + if m != nil { + return m.SubaccountsWithLongPosition + } + return nil +} + +func (m *SubaccountOpenPositionInfo) GetSubaccountsWithShortPosition() []types.SubaccountId { + if m != nil { + return m.SubaccountsWithShortPosition + } + return nil +} + func init() { proto.RegisterType((*PerpetualLiquidationInfo)(nil), "dydxprotocol.clob.PerpetualLiquidationInfo") proto.RegisterType((*SubaccountLiquidationInfo)(nil), "dydxprotocol.clob.SubaccountLiquidationInfo") + proto.RegisterType((*SubaccountOpenPositionInfo)(nil), "dydxprotocol.clob.SubaccountOpenPositionInfo") } func init() { @@ -161,28 +226,33 @@ func init() { } var fileDescriptor_e91628d349879778 = []byte{ - // 335 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x92, 0xc1, 0x4e, 0xf2, 0x40, - 0x14, 0x85, 0x3b, 0x3f, 0xe4, 0x5f, 0x0c, 0xb0, 0xb0, 0x42, 0x44, 0x16, 0x15, 0x89, 0x31, 0xb8, - 0xb0, 0x4d, 0xc4, 0xf0, 0x00, 0xec, 0x9a, 0xb0, 0xc0, 0xba, 0x73, 0xd3, 0x4c, 0xa7, 0x15, 0x26, - 0x29, 0x73, 0x0b, 0x33, 0x63, 0xe0, 0x2d, 0x78, 0x1d, 0xdf, 0x80, 0x25, 0x4b, 0x57, 0xc6, 0xc0, - 0x8b, 0x98, 0x96, 0xb4, 0x9d, 0xba, 0xbb, 0x39, 0xdf, 0x39, 0xe7, 0xde, 0xb4, 0x83, 0xef, 0xc2, - 0x6d, 0xb8, 0x49, 0xd6, 0x20, 0x81, 0x42, 0xec, 0xd0, 0x18, 0x02, 0x27, 0x66, 0x2b, 0xc5, 0x42, - 0x22, 0x19, 0x70, 0x61, 0x67, 0xc8, 0xbc, 0xd0, 0x5d, 0x76, 0xea, 0xea, 0xb5, 0xe7, 0x30, 0x87, - 0x4c, 0x72, 0xd2, 0xe9, 0x6c, 0xec, 0x3d, 0x54, 0xea, 0x84, 0x0a, 0x08, 0xa5, 0xa0, 0xb8, 0x14, - 0xda, 0x7c, 0xb6, 0x0e, 0x76, 0x08, 0x77, 0x67, 0xd1, 0x3a, 0x89, 0xa4, 0x22, 0xf1, 0xb4, 0xdc, - 0xe9, 0xf2, 0x77, 0x30, 0x5f, 0x70, 0xab, 0x0c, 0xf8, 0x2c, 0xec, 0xa2, 0x3e, 0x1a, 0x36, 0x9e, - 0xee, 0xed, 0xca, 0x21, 0x5a, 0xbf, 0xfd, 0x5a, 0xcc, 0x6e, 0x38, 0xa9, 0xef, 0xbf, 0x6f, 0x0c, - 0xaf, 0x29, 0x34, 0xcd, 0xbc, 0xc5, 0xcd, 0x24, 0x5f, 0x97, 0x36, 0xfe, 0xeb, 0xa3, 0x61, 0xcb, - 0x6b, 0x14, 0x9a, 0x1b, 0x0e, 0x3e, 0x11, 0xbe, 0x2e, 0x7b, 0xfe, 0xde, 0x34, 0xc2, 0x9d, 0xc2, - 0x2c, 0xfc, 0xfc, 0x2b, 0x45, 0xe9, 0x6d, 0xb5, 0x61, 0xcb, 0x6b, 0x97, 0x70, 0x5a, 0x30, 0xd3, - 0xc1, 0x97, 0x1c, 0xd2, 0x0a, 0x12, 0xeb, 0x91, 0x74, 0x79, 0xdd, 0x33, 0x73, 0xa4, 0x05, 0xc6, - 0xf8, 0x6a, 0xa5, 0x08, 0x97, 0x6a, 0x29, 0x7c, 0xc6, 0x85, 0x5a, 0x13, 0x4e, 0x23, 0x3f, 0x06, - 0x21, 0xbb, 0xb5, 0x2c, 0xd4, 0xc9, 0xb1, 0x9b, 0xd3, 0x29, 0x08, 0x39, 0x99, 0xed, 0x8f, 0x16, - 0x3a, 0x1c, 0x2d, 0xf4, 0x73, 0xb4, 0xd0, 0xee, 0x64, 0x19, 0x87, 0x93, 0x65, 0x7c, 0x9d, 0x2c, - 0xe3, 0x6d, 0x3c, 0x67, 0x72, 0xa1, 0x02, 0x9b, 0xc2, 0xd2, 0xa9, 0xfc, 0x9e, 0x8f, 0xe7, 0x47, - 0xba, 0x20, 0x8c, 0x3b, 0x85, 0xb2, 0x39, 0xbf, 0x00, 0xb9, 0x4d, 0x22, 0x11, 0xfc, 0xcf, 0xe4, - 0xd1, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0xa6, 0x46, 0x21, 0x23, 0x02, 0x00, 0x00, + // 415 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xcd, 0xae, 0xd2, 0x40, + 0x18, 0xed, 0xd0, 0x1b, 0x17, 0x73, 0x2f, 0x0b, 0x2b, 0xc4, 0x8a, 0xa6, 0x20, 0x31, 0x06, 0x17, + 0xb6, 0x89, 0x18, 0x1e, 0x80, 0x5d, 0x93, 0x26, 0x62, 0x59, 0x98, 0xb8, 0x69, 0xfa, 0x67, 0x3b, + 0x49, 0x99, 0xaf, 0x74, 0x66, 0x14, 0xde, 0x82, 0xb7, 0xf0, 0x19, 0x7c, 0x03, 0x96, 0x2c, 0x5d, + 0x19, 0x03, 0x2f, 0x62, 0x5a, 0x6c, 0x3b, 0xc0, 0x4a, 0x77, 0x5f, 0xce, 0x39, 0xdf, 0x39, 0x67, + 0xa6, 0x1d, 0xfc, 0x2a, 0xda, 0x46, 0x9b, 0xbc, 0x00, 0x0e, 0x21, 0x64, 0x56, 0x98, 0x41, 0x60, + 0x65, 0x64, 0x2d, 0x48, 0xe4, 0x73, 0x02, 0x94, 0x99, 0x15, 0xa5, 0x3d, 0x96, 0x55, 0x66, 0xa9, + 0x1a, 0xf4, 0x12, 0x48, 0xa0, 0x82, 0xac, 0x72, 0x3a, 0x0b, 0x07, 0x6f, 0x2e, 0xec, 0x98, 0x08, + 0xfc, 0x30, 0x04, 0x41, 0x39, 0x93, 0xe6, 0xb3, 0x74, 0xbc, 0x43, 0x58, 0x5f, 0xc4, 0x45, 0x1e, + 0x73, 0xe1, 0x67, 0x4e, 0x9b, 0x69, 0xd3, 0x2f, 0xa0, 0x7d, 0xc4, 0xdd, 0x76, 0xc1, 0x23, 0x91, + 0x8e, 0x46, 0x68, 0x72, 0xff, 0xee, 0xb5, 0x79, 0x51, 0x44, 0xf2, 0x37, 0x97, 0xcd, 0x6c, 0x47, + 0xf3, 0xbb, 0xfd, 0xaf, 0xa1, 0xe2, 0x3e, 0x30, 0x09, 0xd3, 0x5e, 0xe2, 0x87, 0xbc, 0x8e, 0x2b, + 0x1d, 0x3b, 0x23, 0x34, 0xe9, 0xba, 0xf7, 0x0d, 0x66, 0x47, 0xe3, 0x1f, 0x08, 0x3f, 0x6b, 0x7d, + 0xae, 0x3b, 0x4d, 0x71, 0xbf, 0x11, 0x33, 0xaf, 0xbe, 0xa5, 0xb8, 0xec, 0xa6, 0x4e, 0xba, 0x6e, + 0xaf, 0x25, 0x9d, 0x86, 0xd3, 0x2c, 0xfc, 0x84, 0x42, 0x69, 0xe1, 0x67, 0xf2, 0x4a, 0x19, 0x7e, + 0xe7, 0x6a, 0x35, 0x25, 0x2d, 0xcc, 0xf0, 0xd3, 0xb5, 0xf0, 0x29, 0x17, 0x2b, 0xe6, 0x11, 0xca, + 0x44, 0xe1, 0xd3, 0x30, 0xf6, 0x32, 0x60, 0x5c, 0x57, 0xab, 0xa5, 0x7e, 0x4d, 0xdb, 0x35, 0xeb, + 0x00, 0xe3, 0xe3, 0xef, 0x1d, 0x3c, 0x68, 0xbb, 0x7f, 0xc8, 0x63, 0xba, 0x00, 0x46, 0x9a, 0xf2, + 0xd7, 0xa7, 0x47, 0x37, 0xa7, 0xd7, 0xd6, 0xd8, 0x90, 0x2e, 0xd4, 0xfb, 0x46, 0x78, 0xea, 0x65, + 0x40, 0x13, 0x2f, 0xff, 0x6b, 0xa4, 0x77, 0x46, 0xea, 0x3f, 0x7f, 0x84, 0xe7, 0x12, 0xff, 0x89, + 0xf0, 0xd4, 0x01, 0x9a, 0xd4, 0xcd, 0x34, 0x86, 0x87, 0x37, 0x91, 0x2c, 0x85, 0x82, 0xb7, 0x99, + 0xea, 0x7f, 0x64, 0xbe, 0xb8, 0xca, 0x5c, 0x96, 0x96, 0x75, 0xe8, 0x7c, 0xb1, 0x3f, 0x1a, 0xe8, + 0x70, 0x34, 0xd0, 0xef, 0xa3, 0x81, 0x76, 0x27, 0x43, 0x39, 0x9c, 0x0c, 0xe5, 0xe7, 0xc9, 0x50, + 0x3e, 0xcf, 0x12, 0xc2, 0x53, 0x11, 0x98, 0x21, 0xac, 0xac, 0x8b, 0x1f, 0xf9, 0xeb, 0xfb, 0xb7, + 0x61, 0xea, 0x13, 0x6a, 0x35, 0xc8, 0xe6, 0xfc, 0x56, 0xf8, 0x36, 0x8f, 0x59, 0xf0, 0xa8, 0x82, + 0xa7, 0x7f, 0x02, 0x00, 0x00, 0xff, 0xff, 0x46, 0x48, 0x06, 0xe2, 0x4d, 0x03, 0x00, 0x00, } func (m *PerpetualLiquidationInfo) Marshal() (dAtA []byte, err error) { @@ -274,6 +344,62 @@ func (m *SubaccountLiquidationInfo) MarshalToSizedBuffer(dAtA []byte) (int, erro return len(dAtA) - i, nil } +func (m *SubaccountOpenPositionInfo) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SubaccountOpenPositionInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SubaccountOpenPositionInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.SubaccountsWithShortPosition) > 0 { + for iNdEx := len(m.SubaccountsWithShortPosition) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SubaccountsWithShortPosition[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintLiquidations(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if len(m.SubaccountsWithLongPosition) > 0 { + for iNdEx := len(m.SubaccountsWithLongPosition) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.SubaccountsWithLongPosition[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintLiquidations(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.PerpetualId != 0 { + i = encodeVarintLiquidations(dAtA, i, uint64(m.PerpetualId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintLiquidations(dAtA []byte, offset int, v uint64) int { offset -= sovLiquidations(v) base := offset @@ -321,6 +447,30 @@ func (m *SubaccountLiquidationInfo) Size() (n int) { return n } +func (m *SubaccountOpenPositionInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PerpetualId != 0 { + n += 1 + sovLiquidations(uint64(m.PerpetualId)) + } + if len(m.SubaccountsWithLongPosition) > 0 { + for _, e := range m.SubaccountsWithLongPosition { + l = e.Size() + n += 1 + l + sovLiquidations(uint64(l)) + } + } + if len(m.SubaccountsWithShortPosition) > 0 { + for _, e := range m.SubaccountsWithShortPosition { + l = e.Size() + n += 1 + l + sovLiquidations(uint64(l)) + } + } + return n +} + func sovLiquidations(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -593,6 +743,143 @@ func (m *SubaccountLiquidationInfo) Unmarshal(dAtA []byte) error { } return nil } +func (m *SubaccountOpenPositionInfo) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLiquidations + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SubaccountOpenPositionInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SubaccountOpenPositionInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PerpetualId", wireType) + } + m.PerpetualId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLiquidations + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PerpetualId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubaccountsWithLongPosition", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLiquidations + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthLiquidations + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthLiquidations + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SubaccountsWithLongPosition = append(m.SubaccountsWithLongPosition, types.SubaccountId{}) + if err := m.SubaccountsWithLongPosition[len(m.SubaccountsWithLongPosition)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubaccountsWithShortPosition", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLiquidations + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthLiquidations + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthLiquidations + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SubaccountsWithShortPosition = append(m.SubaccountsWithShortPosition, types.SubaccountId{}) + if err := m.SubaccountsWithShortPosition[len(m.SubaccountsWithShortPosition)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipLiquidations(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthLiquidations + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipLiquidations(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0