diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/bundle.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/bundle.ts index 70819bb233..bf83b08c99 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/bundle.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/bundle.ts @@ -111,81 +111,82 @@ import * as _114 from "./stats/stats"; import * as _115 from "./stats/tx"; import * as _116 from "./subaccounts/asset_position"; import * as _117 from "./subaccounts/genesis"; -import * as _118 from "./subaccounts/perpetual_position"; -import * as _119 from "./subaccounts/query"; -import * as _120 from "./subaccounts/streaming"; -import * as _121 from "./subaccounts/subaccount"; -import * as _122 from "./vault/genesis"; -import * as _123 from "./vault/params"; -import * as _124 from "./vault/query"; -import * as _125 from "./vault/share"; -import * as _126 from "./vault/tx"; -import * as _127 from "./vault/vault"; -import * as _128 from "./vest/genesis"; -import * as _129 from "./vest/query"; -import * as _130 from "./vest/tx"; -import * as _131 from "./vest/vest_entry"; -import * as _139 from "./accountplus/query.lcd"; -import * as _140 from "./affiliates/query.lcd"; -import * as _141 from "./assets/query.lcd"; -import * as _142 from "./blocktime/query.lcd"; -import * as _143 from "./bridge/query.lcd"; -import * as _144 from "./clob/query.lcd"; -import * as _145 from "./delaymsg/query.lcd"; -import * as _146 from "./epochs/query.lcd"; -import * as _147 from "./feetiers/query.lcd"; -import * as _148 from "./listing/query.lcd"; -import * as _149 from "./perpetuals/query.lcd"; -import * as _150 from "./prices/query.lcd"; -import * as _151 from "./ratelimit/query.lcd"; -import * as _152 from "./revshare/query.lcd"; -import * as _153 from "./rewards/query.lcd"; -import * as _154 from "./stats/query.lcd"; -import * as _155 from "./subaccounts/query.lcd"; -import * as _156 from "./vault/query.lcd"; -import * as _157 from "./vest/query.lcd"; -import * as _158 from "./accountplus/query.rpc.Query"; -import * as _159 from "./affiliates/query.rpc.Query"; -import * as _160 from "./assets/query.rpc.Query"; -import * as _161 from "./blocktime/query.rpc.Query"; -import * as _162 from "./bridge/query.rpc.Query"; -import * as _163 from "./clob/query.rpc.Query"; -import * as _164 from "./delaymsg/query.rpc.Query"; -import * as _165 from "./epochs/query.rpc.Query"; -import * as _166 from "./feetiers/query.rpc.Query"; -import * as _167 from "./govplus/query.rpc.Query"; -import * as _168 from "./listing/query.rpc.Query"; -import * as _169 from "./perpetuals/query.rpc.Query"; -import * as _170 from "./prices/query.rpc.Query"; -import * as _171 from "./ratelimit/query.rpc.Query"; -import * as _172 from "./revshare/query.rpc.Query"; -import * as _173 from "./rewards/query.rpc.Query"; -import * as _174 from "./sending/query.rpc.Query"; -import * as _175 from "./stats/query.rpc.Query"; -import * as _176 from "./subaccounts/query.rpc.Query"; -import * as _177 from "./vault/query.rpc.Query"; -import * as _178 from "./vest/query.rpc.Query"; -import * as _179 from "./accountplus/tx.rpc.msg"; -import * as _180 from "./affiliates/tx.rpc.msg"; -import * as _181 from "./blocktime/tx.rpc.msg"; -import * as _182 from "./bridge/tx.rpc.msg"; -import * as _183 from "./clob/tx.rpc.msg"; -import * as _184 from "./delaymsg/tx.rpc.msg"; -import * as _185 from "./feetiers/tx.rpc.msg"; -import * as _186 from "./govplus/tx.rpc.msg"; -import * as _187 from "./listing/tx.rpc.msg"; -import * as _188 from "./perpetuals/tx.rpc.msg"; -import * as _189 from "./prices/tx.rpc.msg"; -import * as _190 from "./ratelimit/tx.rpc.msg"; -import * as _191 from "./revshare/tx.rpc.msg"; -import * as _192 from "./rewards/tx.rpc.msg"; -import * as _193 from "./sending/tx.rpc.msg"; -import * as _194 from "./stats/tx.rpc.msg"; -import * as _195 from "./vault/tx.rpc.msg"; -import * as _196 from "./vest/tx.rpc.msg"; -import * as _197 from "./lcd"; -import * as _198 from "./rpc.query"; -import * as _199 from "./rpc.tx"; +import * as _118 from "./subaccounts/leverage"; +import * as _119 from "./subaccounts/perpetual_position"; +import * as _120 from "./subaccounts/query"; +import * as _121 from "./subaccounts/streaming"; +import * as _122 from "./subaccounts/subaccount"; +import * as _123 from "./vault/genesis"; +import * as _124 from "./vault/params"; +import * as _125 from "./vault/query"; +import * as _126 from "./vault/share"; +import * as _127 from "./vault/tx"; +import * as _128 from "./vault/vault"; +import * as _129 from "./vest/genesis"; +import * as _130 from "./vest/query"; +import * as _131 from "./vest/tx"; +import * as _132 from "./vest/vest_entry"; +import * as _140 from "./accountplus/query.lcd"; +import * as _141 from "./affiliates/query.lcd"; +import * as _142 from "./assets/query.lcd"; +import * as _143 from "./blocktime/query.lcd"; +import * as _144 from "./bridge/query.lcd"; +import * as _145 from "./clob/query.lcd"; +import * as _146 from "./delaymsg/query.lcd"; +import * as _147 from "./epochs/query.lcd"; +import * as _148 from "./feetiers/query.lcd"; +import * as _149 from "./listing/query.lcd"; +import * as _150 from "./perpetuals/query.lcd"; +import * as _151 from "./prices/query.lcd"; +import * as _152 from "./ratelimit/query.lcd"; +import * as _153 from "./revshare/query.lcd"; +import * as _154 from "./rewards/query.lcd"; +import * as _155 from "./stats/query.lcd"; +import * as _156 from "./subaccounts/query.lcd"; +import * as _157 from "./vault/query.lcd"; +import * as _158 from "./vest/query.lcd"; +import * as _159 from "./accountplus/query.rpc.Query"; +import * as _160 from "./affiliates/query.rpc.Query"; +import * as _161 from "./assets/query.rpc.Query"; +import * as _162 from "./blocktime/query.rpc.Query"; +import * as _163 from "./bridge/query.rpc.Query"; +import * as _164 from "./clob/query.rpc.Query"; +import * as _165 from "./delaymsg/query.rpc.Query"; +import * as _166 from "./epochs/query.rpc.Query"; +import * as _167 from "./feetiers/query.rpc.Query"; +import * as _168 from "./govplus/query.rpc.Query"; +import * as _169 from "./listing/query.rpc.Query"; +import * as _170 from "./perpetuals/query.rpc.Query"; +import * as _171 from "./prices/query.rpc.Query"; +import * as _172 from "./ratelimit/query.rpc.Query"; +import * as _173 from "./revshare/query.rpc.Query"; +import * as _174 from "./rewards/query.rpc.Query"; +import * as _175 from "./sending/query.rpc.Query"; +import * as _176 from "./stats/query.rpc.Query"; +import * as _177 from "./subaccounts/query.rpc.Query"; +import * as _178 from "./vault/query.rpc.Query"; +import * as _179 from "./vest/query.rpc.Query"; +import * as _180 from "./accountplus/tx.rpc.msg"; +import * as _181 from "./affiliates/tx.rpc.msg"; +import * as _182 from "./blocktime/tx.rpc.msg"; +import * as _183 from "./bridge/tx.rpc.msg"; +import * as _184 from "./clob/tx.rpc.msg"; +import * as _185 from "./delaymsg/tx.rpc.msg"; +import * as _186 from "./feetiers/tx.rpc.msg"; +import * as _187 from "./govplus/tx.rpc.msg"; +import * as _188 from "./listing/tx.rpc.msg"; +import * as _189 from "./perpetuals/tx.rpc.msg"; +import * as _190 from "./prices/tx.rpc.msg"; +import * as _191 from "./ratelimit/tx.rpc.msg"; +import * as _192 from "./revshare/tx.rpc.msg"; +import * as _193 from "./rewards/tx.rpc.msg"; +import * as _194 from "./sending/tx.rpc.msg"; +import * as _195 from "./stats/tx.rpc.msg"; +import * as _196 from "./vault/tx.rpc.msg"; +import * as _197 from "./vest/tx.rpc.msg"; +import * as _198 from "./lcd"; +import * as _199 from "./rpc.query"; +import * as _200 from "./rpc.tx"; export namespace dydxprotocol { export const accountplus = { ..._5, ..._6, @@ -193,33 +194,33 @@ export namespace dydxprotocol { ..._8, ..._9, ..._10, - ..._139, - ..._158, - ..._179 + ..._140, + ..._159, + ..._180 }; export const affiliates = { ..._11, ..._12, ..._13, ..._14, - ..._140, - ..._159, - ..._180 + ..._141, + ..._160, + ..._181 }; export const assets = { ..._15, ..._16, ..._17, ..._18, - ..._141, - ..._160 + ..._142, + ..._161 }; export const blocktime = { ..._19, ..._20, ..._21, ..._22, ..._23, - ..._142, - ..._161, - ..._181 + ..._143, + ..._162, + ..._182 }; export const bridge = { ..._24, ..._25, @@ -227,9 +228,9 @@ export namespace dydxprotocol { ..._27, ..._28, ..._29, - ..._143, - ..._162, - ..._182 + ..._144, + ..._163, + ..._183 }; export const clob = { ..._30, ..._31, @@ -247,9 +248,9 @@ export namespace dydxprotocol { ..._43, ..._44, ..._45, - ..._144, - ..._163, - ..._183 + ..._145, + ..._164, + ..._184 }; export namespace daemons { export const bridge = { ..._46 @@ -264,15 +265,15 @@ export namespace dydxprotocol { ..._51, ..._52, ..._53, - ..._145, - ..._164, - ..._184 + ..._146, + ..._165, + ..._185 }; export const epochs = { ..._54, ..._55, ..._56, - ..._146, - ..._165 + ..._147, + ..._166 }; export const feetiers = { ..._57, ..._58, @@ -280,15 +281,15 @@ export namespace dydxprotocol { ..._60, ..._61, ..._62, - ..._147, - ..._166, - ..._185 + ..._148, + ..._167, + ..._186 }; export const govplus = { ..._63, ..._64, ..._65, - ..._167, - ..._186 + ..._168, + ..._187 }; export namespace indexer { export const events = { ..._66 @@ -315,18 +316,18 @@ export namespace dydxprotocol { ..._77, ..._78, ..._79, - ..._148, - ..._168, - ..._187 + ..._149, + ..._169, + ..._188 }; export const perpetuals = { ..._80, ..._81, ..._82, ..._83, ..._84, - ..._149, - ..._169, - ..._188 + ..._150, + ..._170, + ..._189 }; export const prices = { ..._85, ..._86, @@ -334,9 +335,9 @@ export namespace dydxprotocol { ..._88, ..._89, ..._90, - ..._150, - ..._170, - ..._189 + ..._151, + ..._171, + ..._190 }; export const ratelimit = { ..._91, ..._92, @@ -344,43 +345,43 @@ export namespace dydxprotocol { ..._94, ..._95, ..._96, - ..._151, - ..._171, - ..._190 + ..._152, + ..._172, + ..._191 }; export const revshare = { ..._97, ..._98, ..._99, ..._100, ..._101, - ..._152, - ..._172, - ..._191 + ..._153, + ..._173, + ..._192 }; export const rewards = { ..._102, ..._103, ..._104, ..._105, ..._106, - ..._153, - ..._173, - ..._192 + ..._154, + ..._174, + ..._193 }; export const sending = { ..._107, ..._108, ..._109, ..._110, - ..._174, - ..._193 + ..._175, + ..._194 }; export const stats = { ..._111, ..._112, ..._113, ..._114, ..._115, - ..._154, - ..._175, - ..._194 + ..._155, + ..._176, + ..._195 }; export const subaccounts = { ..._116, ..._117, @@ -388,29 +389,30 @@ export namespace dydxprotocol { ..._119, ..._120, ..._121, - ..._155, - ..._176 + ..._122, + ..._156, + ..._177 }; - export const vault = { ..._122, - ..._123, + export const vault = { ..._123, ..._124, ..._125, ..._126, ..._127, - ..._156, - ..._177, - ..._195 - }; - export const vest = { ..._128, - ..._129, - ..._130, - ..._131, + ..._128, ..._157, ..._178, ..._196 }; - export const ClientFactory = { ..._197, - ..._198, - ..._199 + export const vest = { ..._129, + ..._130, + ..._131, + ..._132, + ..._158, + ..._179, + ..._197 + }; + export const ClientFactory = { ..._198, + ..._199, + ..._200 }; } \ No newline at end of file diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/query.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/query.ts index ef7bf90952..979b40b3fe 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/query.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/query.ts @@ -264,6 +264,57 @@ export interface QueryNextClobPairIdResponseSDKType { /** QueryNextClobPairIdResponse is a response message for the next clob pair id */ next_clob_pair_id: number; } +<<<<<<< HEAD +======= +/** QueryLeverageRequest is a request message for Leverage. */ + +export interface QueryLeverageRequest { + /** The address of the wallet that owns the subaccount. */ + owner: string; + /** The unique number of the subaccount for the owner. */ + + number: number; +} +/** QueryLeverageRequest is a request message for Leverage. */ + +export interface QueryLeverageRequestSDKType { + /** The address of the wallet that owns the subaccount. */ + owner: string; + /** The unique number of the subaccount for the owner. */ + + number: number; +} +/** QueryLeverageResponse is a response message that contains the leverage map. */ + +export interface QueryLeverageResponse { + /** List of clob pair leverage settings. */ + clobPairLeverage: ClobPairLeverageInfo[]; +} +/** QueryLeverageResponse is a response message that contains the leverage map. */ + +export interface QueryLeverageResponseSDKType { + /** List of clob pair leverage settings. */ + clob_pair_leverage: ClobPairLeverageInfoSDKType[]; +} +/** ClobPairLeverageInfo represents the leverage setting for a single clob pair. */ + +export interface ClobPairLeverageInfo { + /** The clob pair ID. */ + clobPairId: number; + /** The user selected imf. */ + + customImfPpm: number; +} +/** ClobPairLeverageInfo represents the leverage setting for a single clob pair. */ + +export interface ClobPairLeverageInfoSDKType { + /** The clob pair ID. */ + clob_pair_id: number; + /** The user selected imf. */ + + custom_imf_ppm: number; +} +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) /** * StreamOrderbookUpdatesRequest is a request message for the * StreamOrderbookUpdates method. @@ -1308,6 +1359,164 @@ export const QueryNextClobPairIdResponse = { }; +<<<<<<< HEAD +======= +function createBaseQueryLeverageRequest(): QueryLeverageRequest { + return { + owner: "", + number: 0 + }; +} + +export const QueryLeverageRequest = { + encode(message: QueryLeverageRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.owner !== "") { + writer.uint32(10).string(message.owner); + } + + if (message.number !== 0) { + writer.uint32(16).uint32(message.number); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): QueryLeverageRequest { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryLeverageRequest(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.owner = reader.string(); + break; + + case 2: + message.number = reader.uint32(); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): QueryLeverageRequest { + const message = createBaseQueryLeverageRequest(); + message.owner = object.owner ?? ""; + message.number = object.number ?? 0; + return message; + } + +}; + +function createBaseQueryLeverageResponse(): QueryLeverageResponse { + return { + clobPairLeverage: [] + }; +} + +export const QueryLeverageResponse = { + encode(message: QueryLeverageResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + for (const v of message.clobPairLeverage) { + ClobPairLeverageInfo.encode(v!, writer.uint32(10).fork()).ldelim(); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): QueryLeverageResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryLeverageResponse(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.clobPairLeverage.push(ClobPairLeverageInfo.decode(reader, reader.uint32())); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): QueryLeverageResponse { + const message = createBaseQueryLeverageResponse(); + message.clobPairLeverage = object.clobPairLeverage?.map(e => ClobPairLeverageInfo.fromPartial(e)) || []; + return message; + } + +}; + +function createBaseClobPairLeverageInfo(): ClobPairLeverageInfo { + return { + clobPairId: 0, + customImfPpm: 0 + }; +} + +export const ClobPairLeverageInfo = { + encode(message: ClobPairLeverageInfo, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.clobPairId !== 0) { + writer.uint32(8).uint32(message.clobPairId); + } + + if (message.customImfPpm !== 0) { + writer.uint32(16).uint32(message.customImfPpm); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): ClobPairLeverageInfo { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseClobPairLeverageInfo(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.clobPairId = reader.uint32(); + break; + + case 2: + message.customImfPpm = reader.uint32(); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): ClobPairLeverageInfo { + const message = createBaseClobPairLeverageInfo(); + message.clobPairId = object.clobPairId ?? 0; + message.customImfPpm = object.customImfPpm ?? 0; + return message; + } + +}; + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) function createBaseStreamOrderbookUpdatesRequest(): StreamOrderbookUpdatesRequest { return { clobPairId: [], diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/tx.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/tx.ts index 09a1c058fc..7aa8d08a72 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/tx.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/clob/tx.ts @@ -382,6 +382,57 @@ export interface MsgUpdateLiquidationsConfigResponse {} /** MsgUpdateLiquidationsConfig is the Msg/LiquidationsConfig response type. */ export interface MsgUpdateLiquidationsConfigResponseSDKType {} +<<<<<<< HEAD +======= +/** LeverageEntry represents a single clob pair leverage setting. */ + +export interface LeverageEntry { + /** The clob pair ID. */ + clobPairId: number; + /** The user selected imf. */ + + customImfPpm: number; +} +/** LeverageEntry represents a single clob pair leverage setting. */ + +export interface LeverageEntrySDKType { + /** The clob pair ID. */ + clob_pair_id: number; + /** The user selected imf. */ + + custom_imf_ppm: number; +} +/** + * MsgUpdateLeverage is a request type used for updating leverage for + * clob pairs. + */ + +export interface MsgUpdateLeverage { + /** The subaccount that is updating leverage. */ + subaccountId?: SubaccountId; + /** List of clob pair leverage settings. */ + + clobPairLeverage: LeverageEntry[]; +} +/** + * MsgUpdateLeverage is a request type used for updating leverage for + * clob pairs. + */ + +export interface MsgUpdateLeverageSDKType { + /** The subaccount that is updating leverage. */ + subaccount_id?: SubaccountIdSDKType; + /** List of clob pair leverage settings. */ + + clob_pair_leverage: LeverageEntrySDKType[]; +} +/** MsgUpdateLeverageResponse is a response type used for updating leverage. */ + +export interface MsgUpdateLeverageResponse {} +/** MsgUpdateLeverageResponse is a response type used for updating leverage. */ + +export interface MsgUpdateLeverageResponseSDKType {} +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) function createBaseMsgCreateClobPair(): MsgCreateClobPair { return { @@ -1335,4 +1386,151 @@ export const MsgUpdateLiquidationsConfigResponse = { return message; } +<<<<<<< HEAD +======= +}; + +function createBaseLeverageEntry(): LeverageEntry { + return { + clobPairId: 0, + customImfPpm: 0 + }; +} + +export const LeverageEntry = { + encode(message: LeverageEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.clobPairId !== 0) { + writer.uint32(8).uint32(message.clobPairId); + } + + if (message.customImfPpm !== 0) { + writer.uint32(16).uint32(message.customImfPpm); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): LeverageEntry { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseLeverageEntry(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.clobPairId = reader.uint32(); + break; + + case 2: + message.customImfPpm = reader.uint32(); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): LeverageEntry { + const message = createBaseLeverageEntry(); + message.clobPairId = object.clobPairId ?? 0; + message.customImfPpm = object.customImfPpm ?? 0; + return message; + } + +}; + +function createBaseMsgUpdateLeverage(): MsgUpdateLeverage { + return { + subaccountId: undefined, + clobPairLeverage: [] + }; +} + +export const MsgUpdateLeverage = { + encode(message: MsgUpdateLeverage, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.subaccountId !== undefined) { + SubaccountId.encode(message.subaccountId, writer.uint32(10).fork()).ldelim(); + } + + for (const v of message.clobPairLeverage) { + LeverageEntry.encode(v!, writer.uint32(18).fork()).ldelim(); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): MsgUpdateLeverage { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseMsgUpdateLeverage(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.subaccountId = SubaccountId.decode(reader, reader.uint32()); + break; + + case 2: + message.clobPairLeverage.push(LeverageEntry.decode(reader, reader.uint32())); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): MsgUpdateLeverage { + const message = createBaseMsgUpdateLeverage(); + message.subaccountId = object.subaccountId !== undefined && object.subaccountId !== null ? SubaccountId.fromPartial(object.subaccountId) : undefined; + message.clobPairLeverage = object.clobPairLeverage?.map(e => LeverageEntry.fromPartial(e)) || []; + return message; + } + +}; + +function createBaseMsgUpdateLeverageResponse(): MsgUpdateLeverageResponse { + return {}; +} + +export const MsgUpdateLeverageResponse = { + encode(_: MsgUpdateLeverageResponse, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): MsgUpdateLeverageResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseMsgUpdateLeverageResponse(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(_: DeepPartial): MsgUpdateLeverageResponse { + const message = createBaseMsgUpdateLeverageResponse(); + return message; + } + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) }; \ No newline at end of file diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/leverage.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/leverage.ts new file mode 100644 index 0000000000..ff6ad67408 --- /dev/null +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/subaccounts/leverage.ts @@ -0,0 +1,138 @@ +import * as _m0 from "protobufjs/minimal"; +import { DeepPartial } from "../../helpers"; +/** + * PerpetualLeverageEntry represents a single perpetual leverage setting for + * internal storage + */ + +export interface PerpetualLeverageEntry { + /** The perpetual ID (internal storage format) */ + perpetualId: number; + /** The user selected IMF in parts per million */ + + customImfPpm: number; +} +/** + * PerpetualLeverageEntry represents a single perpetual leverage setting for + * internal storage + */ + +export interface PerpetualLeverageEntrySDKType { + /** The perpetual ID (internal storage format) */ + perpetual_id: number; + /** The user selected IMF in parts per million */ + + custom_imf_ppm: number; +} +/** LeverageData represents the leverage settings for a subaccount */ + +export interface LeverageData { + /** List of leverage entries for this subaccount */ + entries: PerpetualLeverageEntry[]; +} +/** LeverageData represents the leverage settings for a subaccount */ + +export interface LeverageDataSDKType { + /** List of leverage entries for this subaccount */ + entries: PerpetualLeverageEntrySDKType[]; +} + +function createBasePerpetualLeverageEntry(): PerpetualLeverageEntry { + return { + perpetualId: 0, + customImfPpm: 0 + }; +} + +export const PerpetualLeverageEntry = { + encode(message: PerpetualLeverageEntry, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.perpetualId !== 0) { + writer.uint32(8).uint32(message.perpetualId); + } + + if (message.customImfPpm !== 0) { + writer.uint32(16).uint32(message.customImfPpm); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): PerpetualLeverageEntry { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePerpetualLeverageEntry(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.perpetualId = reader.uint32(); + break; + + case 2: + message.customImfPpm = reader.uint32(); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): PerpetualLeverageEntry { + const message = createBasePerpetualLeverageEntry(); + message.perpetualId = object.perpetualId ?? 0; + message.customImfPpm = object.customImfPpm ?? 0; + return message; + } + +}; + +function createBaseLeverageData(): LeverageData { + return { + entries: [] + }; +} + +export const LeverageData = { + encode(message: LeverageData, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + for (const v of message.entries) { + PerpetualLeverageEntry.encode(v!, writer.uint32(10).fork()).ldelim(); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): LeverageData { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseLeverageData(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.entries.push(PerpetualLeverageEntry.decode(reader, reader.uint32())); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): LeverageData { + const message = createBaseLeverageData(); + message.entries = object.entries?.map(e => PerpetualLeverageEntry.fromPartial(e)) || []; + return message; + } + +}; \ No newline at end of file diff --git a/indexer/packages/v4-protos/src/codegen/gogoproto/bundle.ts b/indexer/packages/v4-protos/src/codegen/gogoproto/bundle.ts index dbcb66d660..c96e8e29e0 100644 --- a/indexer/packages/v4-protos/src/codegen/gogoproto/bundle.ts +++ b/indexer/packages/v4-protos/src/codegen/gogoproto/bundle.ts @@ -1,3 +1,3 @@ -import * as _132 from "./gogo"; -export const gogoproto = { ..._132 +import * as _133 from "./gogo"; +export const gogoproto = { ..._133 }; \ No newline at end of file diff --git a/indexer/packages/v4-protos/src/codegen/google/bundle.ts b/indexer/packages/v4-protos/src/codegen/google/bundle.ts index b4251166ce..859b1b0306 100644 --- a/indexer/packages/v4-protos/src/codegen/google/bundle.ts +++ b/indexer/packages/v4-protos/src/codegen/google/bundle.ts @@ -1,16 +1,16 @@ -import * as _133 from "./api/annotations"; -import * as _134 from "./api/http"; -import * as _135 from "./protobuf/descriptor"; -import * as _136 from "./protobuf/duration"; -import * as _137 from "./protobuf/timestamp"; -import * as _138 from "./protobuf/any"; +import * as _134 from "./api/annotations"; +import * as _135 from "./api/http"; +import * as _136 from "./protobuf/descriptor"; +import * as _137 from "./protobuf/duration"; +import * as _138 from "./protobuf/timestamp"; +import * as _139 from "./protobuf/any"; export namespace google { - export const api = { ..._133, - ..._134 + export const api = { ..._134, + ..._135 }; - export const protobuf = { ..._135, - ..._136, + export const protobuf = { ..._136, ..._137, - ..._138 + ..._138, + ..._139 }; } \ No newline at end of file diff --git a/proto/dydxprotocol/clob/query.proto b/proto/dydxprotocol/clob/query.proto index 7d6eeb1b61..10ef3bee29 100644 --- a/proto/dydxprotocol/clob/query.proto +++ b/proto/dydxprotocol/clob/query.proto @@ -175,6 +175,31 @@ message QueryNextClobPairIdRequest {} // QueryNextClobPairIdResponse is a response message for the next clob pair id message QueryNextClobPairIdResponse { uint32 next_clob_pair_id = 1; } +<<<<<<< HEAD +======= +// QueryLeverageRequest is a request message for Leverage. +message QueryLeverageRequest { + // The address of the wallet that owns the subaccount. + string owner = 1; + // The unique number of the subaccount for the owner. + uint32 number = 2; +} + +// QueryLeverageResponse is a response message that contains the leverage map. +message QueryLeverageResponse { + // List of clob pair leverage settings. + repeated ClobPairLeverageInfo clob_pair_leverage = 1; +} + +// ClobPairLeverageInfo represents the leverage setting for a single clob pair. +message ClobPairLeverageInfo { + // The clob pair ID. + uint32 clob_pair_id = 1; + // The user selected imf. + uint32 custom_imf_ppm = 2; +} + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) // StreamOrderbookUpdatesRequest is a request message for the // StreamOrderbookUpdates method. message StreamOrderbookUpdatesRequest { diff --git a/proto/dydxprotocol/clob/tx.proto b/proto/dydxprotocol/clob/tx.proto index d11ebb3516..73f7fc206b 100644 --- a/proto/dydxprotocol/clob/tx.proto +++ b/proto/dydxprotocol/clob/tx.proto @@ -211,3 +211,29 @@ message MsgUpdateLiquidationsConfig { // MsgUpdateLiquidationsConfig is the Msg/LiquidationsConfig response type. message MsgUpdateLiquidationsConfigResponse {} +<<<<<<< HEAD +======= + +// LeverageEntry represents a single clob pair leverage setting. +message LeverageEntry { + // The clob pair ID. + uint32 clob_pair_id = 1; + // The user selected imf. + uint32 custom_imf_ppm = 2; +} + +// MsgUpdateLeverage is a request type used for updating leverage for +// clob pairs. +message MsgUpdateLeverage { + option (cosmos.msg.v1.signer) = "subaccount_id"; + + // The subaccount that is updating leverage. + dydxprotocol.subaccounts.SubaccountId subaccount_id = 1; + + // List of clob pair leverage settings. + repeated LeverageEntry clob_pair_leverage = 2; +} + +// MsgUpdateLeverageResponse is a response type used for updating leverage. +message MsgUpdateLeverageResponse {} +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) diff --git a/proto/dydxprotocol/subaccounts/leverage.proto b/proto/dydxprotocol/subaccounts/leverage.proto new file mode 100644 index 0000000000..a27b0f7bd8 --- /dev/null +++ b/proto/dydxprotocol/subaccounts/leverage.proto @@ -0,0 +1,19 @@ +syntax = "proto3"; +package dydxprotocol.subaccounts; + +option go_package = "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types"; + +// PerpetualLeverageEntry represents a single perpetual leverage setting for +// internal storage +message PerpetualLeverageEntry { + // The perpetual ID (internal storage format) + uint32 perpetual_id = 1; + // The user selected IMF in parts per million + uint32 custom_imf_ppm = 2; +} + +// LeverageData represents the leverage settings for a subaccount +message LeverageData { + // List of leverage entries for this subaccount + repeated PerpetualLeverageEntry entries = 1; +} diff --git a/protocol/daemons/liquidation/client/sub_task_runner.go b/protocol/daemons/liquidation/client/sub_task_runner.go index f9f2e77675..bcee093424 100644 --- a/protocol/daemons/liquidation/client/sub_task_runner.go +++ b/protocol/daemons/liquidation/client/sub_task_runner.go @@ -341,6 +341,7 @@ func (c *Client) CheckSubaccountCollateralization( risk, err := salib.GetRiskForSubaccount( settledSubaccount, perpInfos, + nil, // No leverage needed for liquidation calculations ) return risk.IsLiquidatable(), risk.NC.Sign() < 0, nil diff --git a/protocol/mocks/ClobKeeper.go b/protocol/mocks/ClobKeeper.go index d1b6859d76..4af34e3dc3 100644 --- a/protocol/mocks/ClobKeeper.go +++ b/protocol/mocks/ClobKeeper.go @@ -5,10 +5,12 @@ package mocks import ( big "math/big" - indexer_manager "github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager" - affiliatetypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" + affiliatestypes "github.com/dydxprotocol/v4-chain/protocol/x/affiliates/types" + clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" + indexer_manager "github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager" + log "cosmossdk.io/log" mock "github.com/stretchr/testify/mock" @@ -592,6 +594,26 @@ func (_m *ClobKeeper) GetSubaccountMaxNotionalLiquidatable(ctx types.Context, su return r0, r1 } +// GetSubaccountsKeeper provides a mock function with no fields +func (_m *ClobKeeper) GetSubaccountsKeeper() clobtypes.SubaccountsKeeper { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for GetSubaccountsKeeper") + } + + var r0 clobtypes.SubaccountsKeeper + if rf, ok := ret.Get(0).(func() clobtypes.SubaccountsKeeper); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(clobtypes.SubaccountsKeeper) + } + } + + return r0 +} + // HandleMsgCancelOrder provides a mock function with given fields: ctx, msg func (_m *ClobKeeper) HandleMsgCancelOrder(ctx types.Context, msg *clobtypes.MsgCancelOrder) error { ret := _m.Called(ctx, msg) @@ -980,8 +1002,8 @@ func (_m *ClobKeeper) ProcessProposerOperations(ctx types.Context, operations [] return r0 } -// ProcessSingleMatch provides a mock function with given fields: ctx, matchWithOrders, affiliatesWhitelistMap -func (_m *ClobKeeper) ProcessSingleMatch(ctx types.Context, matchWithOrders *clobtypes.MatchWithOrders, affiliateOverrides map[string]bool, affiliateParameters affiliatetypes.AffiliateParameters) (bool, subaccountstypes.UpdateResult, subaccountstypes.UpdateResult, *big.Int, error) { +// ProcessSingleMatch provides a mock function with given fields: ctx, matchWithOrders, affiliateOverrides, affiliateParameters +func (_m *ClobKeeper) ProcessSingleMatch(ctx types.Context, matchWithOrders *clobtypes.MatchWithOrders, affiliateOverrides map[string]bool, affiliateParameters affiliatestypes.AffiliateParameters) (bool, subaccountstypes.UpdateResult, subaccountstypes.UpdateResult, *big.Int, error) { ret := _m.Called(ctx, matchWithOrders, affiliateOverrides, affiliateParameters) if len(ret) == 0 { @@ -993,28 +1015,28 @@ func (_m *ClobKeeper) ProcessSingleMatch(ctx types.Context, matchWithOrders *clo var r2 subaccountstypes.UpdateResult var r3 *big.Int var r4 error - if rf, ok := ret.Get(0).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatetypes.AffiliateParameters) (bool, subaccountstypes.UpdateResult, subaccountstypes.UpdateResult, *big.Int, error)); ok { + if rf, ok := ret.Get(0).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatestypes.AffiliateParameters) (bool, subaccountstypes.UpdateResult, subaccountstypes.UpdateResult, *big.Int, error)); ok { return rf(ctx, matchWithOrders, affiliateOverrides, affiliateParameters) } - if rf, ok := ret.Get(0).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatetypes.AffiliateParameters) bool); ok { + if rf, ok := ret.Get(0).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatestypes.AffiliateParameters) bool); ok { r0 = rf(ctx, matchWithOrders, affiliateOverrides, affiliateParameters) } else { r0 = ret.Get(0).(bool) } - if rf, ok := ret.Get(1).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatetypes.AffiliateParameters) subaccountstypes.UpdateResult); ok { + if rf, ok := ret.Get(1).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatestypes.AffiliateParameters) subaccountstypes.UpdateResult); ok { r1 = rf(ctx, matchWithOrders, affiliateOverrides, affiliateParameters) } else { r1 = ret.Get(1).(subaccountstypes.UpdateResult) } - if rf, ok := ret.Get(2).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatetypes.AffiliateParameters) subaccountstypes.UpdateResult); ok { + if rf, ok := ret.Get(2).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatestypes.AffiliateParameters) subaccountstypes.UpdateResult); ok { r2 = rf(ctx, matchWithOrders, affiliateOverrides, affiliateParameters) } else { r2 = ret.Get(2).(subaccountstypes.UpdateResult) } - if rf, ok := ret.Get(3).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatetypes.AffiliateParameters) *big.Int); ok { + if rf, ok := ret.Get(3).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatestypes.AffiliateParameters) *big.Int); ok { r3 = rf(ctx, matchWithOrders, affiliateOverrides, affiliateParameters) } else { if ret.Get(3) != nil { @@ -1022,7 +1044,7 @@ func (_m *ClobKeeper) ProcessSingleMatch(ctx types.Context, matchWithOrders *clo } } - if rf, ok := ret.Get(4).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatetypes.AffiliateParameters) error); ok { + if rf, ok := ret.Get(4).(func(types.Context, *clobtypes.MatchWithOrders, map[string]bool, affiliatestypes.AffiliateParameters) error); ok { r4 = rf(ctx, matchWithOrders, affiliateOverrides, affiliateParameters) } else { r4 = ret.Error(4) diff --git a/protocol/testutil/app/app.go b/protocol/testutil/app/app.go index 6d3dd3d0fe..246d96955e 100644 --- a/protocol/testutil/app/app.go +++ b/protocol/testutil/app/app.go @@ -1349,7 +1349,11 @@ func launchValidatorInDir( // MustMakeCheckTxsWithClobMsg creates one signed RequestCheckTx for each msg passed in. // The messsage must use one of the hard-coded well known subaccount owners otherwise this will panic. -func MustMakeCheckTxsWithClobMsg[T clobtypes.MsgPlaceOrder | clobtypes.MsgCancelOrder | clobtypes.MsgBatchCancel]( +func MustMakeCheckTxsWithClobMsg[ + T clobtypes.MsgPlaceOrder | + clobtypes.MsgCancelOrder | + clobtypes.MsgBatchCancel | + clobtypes.MsgUpdateLeverage]( ctx sdk.Context, app *app.App, messages ...T, @@ -1368,6 +1372,9 @@ func MustMakeCheckTxsWithClobMsg[T clobtypes.MsgPlaceOrder | clobtypes.MsgCancel case clobtypes.MsgBatchCancel: signerAddress = v.SubaccountId.Owner m = &v + case clobtypes.MsgUpdateLeverage: + signerAddress = v.SubaccountId.Owner + m = &v default: panic(fmt.Errorf("MustMakeCheckTxsWithClobMsg: Unknown message type %T", msg)) } diff --git a/protocol/testutil/keeper/listing.go b/protocol/testutil/keeper/listing.go index 4736611bd5..b7f543635c 100644 --- a/protocol/testutil/keeper/listing.go +++ b/protocol/testutil/keeper/listing.go @@ -134,6 +134,7 @@ func ListingKeepers( db, cdc, ) + // Create subaccounts keeper first with nil leverageKeeper subaccountsKeeper, _ = createSubaccountsKeeper( stateStore, db, @@ -165,6 +166,7 @@ func ListingKeepers( mockIndexerEventManager, transientStoreKey, ) + // Create the listing keeper keeper, storeKey, _ = createListingKeeper( stateStore, diff --git a/protocol/x/clob/ante/clob.go b/protocol/x/clob/ante/clob.go index 295fb5a624..d93aec6b44 100644 --- a/protocol/x/clob/ante/clob.go +++ b/protocol/x/clob/ante/clob.go @@ -192,6 +192,38 @@ func (cd ClobDecorator) AnteHandle( ) return ctx, err } +<<<<<<< HEAD +======= + case *types.MsgUpdateLeverage: + // Process UpdateLeverage message - delegate to subaccounts keeper + // Convert from LeverageEntry slice to map + perpetualLeverageMap, err := types.ValidateAndConstructPerpetualLeverageMap(ctx, msg, cd.clobKeeper) + if err != nil { + return ctx, err + } + + // Delegate to subaccounts keeper for leverage storage and validation + if err := cd.clobKeeper.GetSubaccountsKeeper().UpdateLeverage( + ctx, + msg.SubaccountId, + perpetualLeverageMap, + ); err != nil { + log.DebugLog( + ctx, + "Failed to update leverage in ante handler", + log.Tx, cometbftlog.NewLazySprintf("%X", tmhash.Sum(ctx.TxBytes())), + log.Error, err, + ) + return ctx, err + } + + log.DebugLog( + ctx, + "Received new leverage update", + log.Tx, cometbftlog.NewLazySprintf("%X", tmhash.Sum(ctx.TxBytes())), + "subaccount", msg.SubaccountId.String(), + ) +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) } if err != nil { return ctx, err diff --git a/protocol/x/clob/client/cli/tx_update_leverage.go b/protocol/x/clob/client/cli/tx_update_leverage.go new file mode 100644 index 0000000000..e2063281b4 --- /dev/null +++ b/protocol/x/clob/client/cli/tx_update_leverage.go @@ -0,0 +1,77 @@ +package cli + +import ( + "encoding/json" + "fmt" + "sort" + "strconv" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" + satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" +) + +func CmdUpdateLeverage() *cobra.Command { + cmd := &cobra.Command{ + Use: "update-leverage [address] [subaccount-number] [leverage-map]", + Short: "Update leverage for perpetuals", + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + // Parse address and subaccount number + address := args[0] + subaccountNumber, err := strconv.ParseUint(args[1], 10, 32) + if err != nil { + return fmt.Errorf("invalid subaccount number %s: %w", args[1], err) + } + + // Parse leverage map + var leverageMap map[string]uint32 + if err := json.Unmarshal([]byte(args[2]), &leverageMap); err != nil { + return fmt.Errorf("invalid leverage map JSON: %w", err) + } + + // Sort the keys to ensure deterministic ordering + keys := make([]string, 0, len(leverageMap)) + for clobPairIdStr := range leverageMap { + keys = append(keys, clobPairIdStr) + } + sort.Strings(keys) + + var clobPairLeverage []*types.LeverageEntry + for _, clobPairIdStr := range keys { + clobPairId, err := strconv.ParseUint(clobPairIdStr, 10, 32) + if err != nil { + return fmt.Errorf("invalid clob pair ID %s: %w", clobPairIdStr, err) + } + + clobPairLeverage = append(clobPairLeverage, &types.LeverageEntry{ + ClobPairId: uint32(clobPairId), + CustomImfPpm: leverageMap[clobPairIdStr], + }) + } + + msg := &types.MsgUpdateLeverage{ + SubaccountId: &satypes.SubaccountId{ + Owner: address, + Number: uint32(subaccountNumber), + }, + ClobPairLeverage: clobPairLeverage, + } + + return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} diff --git a/protocol/x/clob/e2e/app_test.go b/protocol/x/clob/e2e/app_test.go index ebd7ddc2d8..e3b5eaeeff 100644 --- a/protocol/x/clob/e2e/app_test.go +++ b/protocol/x/clob/e2e/app_test.go @@ -315,6 +315,47 @@ var ( }, 20, ) +<<<<<<< HEAD +======= + + // Leverage update message constants + UpdateLeverage_Alice_Num0_PerpId0_Lev5 = clobtypes.MsgUpdateLeverage{ + SubaccountId: &constants.Alice_Num0, + ClobPairLeverage: []*clobtypes.LeverageEntry{ + { + ClobPairId: 0, + CustomImfPpm: 200_000, + }, + }, + } + UpdateLeverage_Alice_Num0_PerpId1_Lev10 = clobtypes.MsgUpdateLeverage{ + SubaccountId: &constants.Alice_Num0, + ClobPairLeverage: []*clobtypes.LeverageEntry{ + { + ClobPairId: 1, + CustomImfPpm: 100_000, + }, + }, + } + UpdateLeverage_Alice_Num1_PerpId0_Lev4 = clobtypes.MsgUpdateLeverage{ + SubaccountId: &constants.Alice_Num1, + ClobPairLeverage: []*clobtypes.LeverageEntry{ + { + ClobPairId: 0, + CustomImfPpm: 250_000, + }, + }, + } + UpdateLeverage_Bob_Num0_PerpId0_Lev5 = clobtypes.MsgUpdateLeverage{ + SubaccountId: &constants.Bob_Num0, + ClobPairLeverage: []*clobtypes.LeverageEntry{ + { + ClobPairId: 0, + CustomImfPpm: 200_000, + }, + }, + } +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) ) func TestHydrationInPreBlocker(t *testing.T) { diff --git a/protocol/x/clob/keeper/grpc_query_leverage.go b/protocol/x/clob/keeper/grpc_query_leverage.go new file mode 100644 index 0000000000..ac6800a254 --- /dev/null +++ b/protocol/x/clob/keeper/grpc_query_leverage.go @@ -0,0 +1,56 @@ +package keeper + +import ( + "context" + "sort" + + errorsmod "cosmossdk.io/errors" + "github.com/dydxprotocol/v4-chain/protocol/lib" + "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" + satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// Leverage returns the leverage for a subaccount. +func (k Keeper) Leverage( + c context.Context, + req *types.QueryLeverageRequest, +) (*types.QueryLeverageResponse, error) { + if req == nil { + return nil, status.Error(codes.InvalidArgument, "invalid request") + } + + ctx := lib.UnwrapSDKContext(c, types.ModuleName) + + // Get leverage for the subaccount + leverageMap, exists := k.subaccountsKeeper.GetLeverage(ctx, &satypes.SubaccountId{ + Owner: req.Owner, + Number: req.Number, + }) + if !exists { + leverageMap = make(map[uint32]uint32) + } + + // Sort the keys to ensure deterministic ordering + keys := make([]uint32, 0, len(leverageMap)) + for perpetualId := range leverageMap { + keys = append(keys, perpetualId) + } + sort.Slice(keys, func(i, j int) bool { + return keys[i] < keys[j] + }) + + clobPairLeverage := make([]*types.ClobPairLeverageInfo, 0, len(leverageMap)) + for _, perpetualId := range keys { + clobPairId, err := k.GetClobPairIdForPerpetual(ctx, perpetualId) + if err != nil { + return nil, status.Error(codes.Internal, errorsmod.Wrap(err, "failed to get clob pair id for perpetual").Error()) + } + clobPairLeverage = append(clobPairLeverage, &types.ClobPairLeverageInfo{ + ClobPairId: clobPairId.ToUint32(), + CustomImfPpm: leverageMap[perpetualId], + }) + } + return &types.QueryLeverageResponse{ClobPairLeverage: clobPairLeverage}, nil +} diff --git a/protocol/x/clob/keeper/keeper.go b/protocol/x/clob/keeper/keeper.go index 64355aed7c..fb8d74e40f 100644 --- a/protocol/x/clob/keeper/keeper.go +++ b/protocol/x/clob/keeper/keeper.go @@ -161,6 +161,10 @@ func (k Keeper) GetFullNodeStreamingManager() streamingtypes.FullNodeStreamingMa return k.streamingManager } +func (k Keeper) GetSubaccountsKeeper() types.SubaccountsKeeper { + return k.subaccountsKeeper +} + func (k Keeper) GetCrossInsuranceFundBalance(ctx sdk.Context) *big.Int { return k.subaccountsKeeper.GetCrossInsuranceFundBalance(ctx) } diff --git a/protocol/x/clob/keeper/leverage.go b/protocol/x/clob/keeper/leverage.go new file mode 100644 index 0000000000..ce7ae24b10 --- /dev/null +++ b/protocol/x/clob/keeper/leverage.go @@ -0,0 +1,15 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" +) + +// UpdateLeverage updates leverage for specific perpetuals for a subaccount. +func (k Keeper) UpdateLeverage( + ctx sdk.Context, + subaccountId *satypes.SubaccountId, + perpetualLeverage map[uint32]uint32, +) error { + return k.subaccountsKeeper.UpdateLeverage(ctx, subaccountId, perpetualLeverage) +} diff --git a/protocol/x/clob/keeper/leverage_e2e_test.go b/protocol/x/clob/keeper/leverage_e2e_test.go new file mode 100644 index 0000000000..96698ce79d --- /dev/null +++ b/protocol/x/clob/keeper/leverage_e2e_test.go @@ -0,0 +1,266 @@ +package keeper_test + +import ( + "math/big" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/dydxprotocol/v4-chain/protocol/dtypes" + testapp "github.com/dydxprotocol/v4-chain/protocol/testutil/app" + "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" + assettypes "github.com/dydxprotocol/v4-chain/protocol/x/assets/types" + 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" +) + +// Test helper functions for leverage e2e tests + +// setupLeverageTest creates a test app with the necessary state for leverage testing +func setupLeverageTest(t *testing.T) *testapp.TestApp { + tApp := testapp.NewTestAppBuilder(t).Build() + return tApp +} + +// configureLeverage sets leverage for a subaccount and perpetual +func configureLeverage( + t *testing.T, + tApp *testapp.TestApp, + ctx sdk.Context, + subaccountId satypes.SubaccountId, + perpetualId uint32, + custom_imf_ppm uint32, +) { + leverageMap := map[uint32]uint32{ + perpetualId: custom_imf_ppm, + } + + err := tApp.App.SubaccountsKeeper.UpdateLeverage(ctx, &subaccountId, leverageMap) + require.NoError(t, err) +} + +// createSubaccountWithBalance creates a subaccount with specified USDC balance +func createSubaccountWithBalance( + tApp *testapp.TestApp, + ctx sdk.Context, + subaccountId satypes.SubaccountId, + usdcBalance *big.Int, +) { + subaccount := satypes.Subaccount{ + Id: &subaccountId, + AssetPositions: []*satypes.AssetPosition{ + { + AssetId: assettypes.AssetUsdc.Id, + Quantums: dtypes.NewIntFromBigInt(usdcBalance), + }, + }, + } + + tApp.App.SubaccountsKeeper.SetSubaccount(ctx, subaccount) +} + +// TestLeverageKeeperSetup verifies that the LeverageKeeper is properly wired up +func TestLeverageKeeperSetup(t *testing.T) { + tApp := setupLeverageTest(t) + ctx := tApp.InitChain() + + // Test that the SubaccountsKeeper has a non-nil LeverageKeeper + // We can't directly access the leverageKeeper field since it's private, + // but we can test that leverage-aware operations work + + subaccountId := constants.Alice_Num0 + perpetualId := uint32(0) + custom_imf_ppm := uint32(50_000) + + // Configure leverage first + configureLeverage(t, tApp, ctx, subaccountId, perpetualId, custom_imf_ppm) + + // Verify leverage was set + leverageMap, exists := tApp.App.SubaccountsKeeper.GetLeverage(ctx, &subaccountId) + require.True(t, exists) + require.Equal(t, custom_imf_ppm, leverageMap[perpetualId]) + + // Create a subaccount with some balance + createSubaccountWithBalance(tApp, ctx, subaccountId, big.NewInt(1000_000_000)) + + // Test that CanUpdateSubaccounts works (this internally uses the leverageKeeper) + updates := []satypes.Update{ + { + SubaccountId: subaccountId, + AssetUpdates: []satypes.AssetUpdate{ + { + AssetId: assettypes.AssetUsdc.Id, + BigQuantumsDelta: big.NewInt(-100_000_000), // Spend $100 + }, + }, + PerpetualUpdates: []satypes.PerpetualUpdate{ + { + PerpetualId: perpetualId, + BigQuantumsDelta: big.NewInt(1_000_000), // Small position + }, + }, + }, + } + + // This should work without panicking (leverageKeeper should not be nil) + success, results, err := tApp.App.SubaccountsKeeper.CanUpdateSubaccounts( + ctx, + updates, + satypes.CollatCheck, + ) + + require.NoError(t, err, "CanUpdateSubaccounts should not error") + require.NotNil(t, results, "Results should not be nil") + require.Len(t, results, 1, "Should have one result") + + t.Logf("✅ LeverageKeeper is properly wired up") + t.Logf(" CanUpdateSubaccounts success: %v", success) + t.Logf(" Update result: %v", results[0]) +} + +// TestLeverageBasicOrderPlacement tests basic order placement with leverage configuration +func TestLeverageBasicOrderPlacement(t *testing.T) { + tApp := setupLeverageTest(t) + ctx := tApp.InitChain() + + // Test parameters + subaccountId := constants.Alice_Num0 + perpetualId := uint32(0) // BTC-USD + custom_imf_ppm := uint32(100_000) // 10x leverage + initialBalance := big.NewInt(1000_000_000) // $1000 USDC (6 decimals) + + // Set up subaccount with initial balance + createSubaccountWithBalance(tApp, ctx, subaccountId, initialBalance) + + // Configure leverage + configureLeverage(t, tApp, ctx, subaccountId, perpetualId, custom_imf_ppm) + + // Verify leverage was set correctly + leverageMap, exists := tApp.App.SubaccountsKeeper.GetLeverage(ctx, &subaccountId) + require.True(t, exists) + require.Equal(t, custom_imf_ppm, leverageMap[perpetualId]) + + t.Logf("✅ Successfully configured and verified %dx leverage for subaccount", custom_imf_ppm) + t.Logf(" Subaccount: %v", subaccountId) + t.Logf(" Perpetual ID: %d", perpetualId) + t.Logf(" Initial balance: $%s", new(big.Int).Div(initialBalance, big.NewInt(1_000_000))) +} + +// TestLeverageConfiguration tests basic leverage configuration functionality +func TestLeverageConfiguration(t *testing.T) { + tApp := setupLeverageTest(t) + ctx := tApp.InitChain() + + subaccountId := constants.Alice_Num0 + perpetualId := uint32(0) + + testCases := []struct { + name string + custom_imf_ppm uint32 + }{ + {"2x Leverage", 500_000}, + {"10x Leverage", 100_000}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // Configure leverage + configureLeverage(t, tApp, ctx, subaccountId, perpetualId, tc.custom_imf_ppm) + + // Verify leverage was set correctly + leverageMap, exists := tApp.App.SubaccountsKeeper.GetLeverage(ctx, &subaccountId) + require.True(t, exists) + require.Equal(t, tc.custom_imf_ppm, leverageMap[perpetualId]) + + t.Logf("✅ Successfully configured %dx leverage", tc.custom_imf_ppm) + }) + } +} + +func TestOrderPlacementFailsWithLeverageConfigured(t *testing.T) { + tApp := testapp.NewTestAppBuilder(t).Build() + ctx := tApp.InitChain() + + // Verify Alice and Bob have identical subaccounts + gotAlice := tApp.App.SubaccountsKeeper.GetSubaccount(ctx, constants.Alice_Num0) + gotBob := tApp.App.SubaccountsKeeper.GetSubaccount(ctx, constants.Bob_Num0) + require.Equal(t, gotAlice.AssetPositions, gotBob.AssetPositions, "Alice and Bob should have identical asset positions") + + // Configure leverage for Alice: 1x on BTC perpetual + aliceLeverage := &clobtypes.MsgUpdateLeverage{ + SubaccountId: &constants.Alice_Num0, + ClobPairLeverage: []*clobtypes.LeverageEntry{ + { + ClobPairId: 0, + CustomImfPpm: 1_000_000, + }, + }, + } + for _, checkTx := range testapp.MustMakeCheckTxsWithClobMsg( + ctx, + tApp.App, + *aliceLeverage, + ) { + resp := tApp.CheckTx(checkTx) + require.True(t, resp.IsOK(), "Expected Alice's CheckTx to succeed. Response: %+v", resp) + } + + ctx = tApp.AdvanceToBlock(2, testapp.AdvanceToBlockOptions{}) + + // Place orders for both Alice and Bob that would require the entire margin if leverage was unchanged + orderSize := dtypes.NewIntFromBigInt(big.NewInt(5_500_000_000_000_000)) + + // Use the same price and clob pair as in the other test + price := uint64(2_000_000_000) + + // Bob's order should succeed + bobOrder := &clobtypes.Order{ + OrderId: clobtypes.OrderId{ + SubaccountId: constants.Bob_Num0, + ClientId: 0, + OrderFlags: clobtypes.OrderIdFlags_LongTerm, + ClobPairId: 0, + }, + Side: clobtypes.Order_SIDE_BUY, + Quantums: orderSize.BigInt().Uint64(), + Subticks: price, + GoodTilOneof: &clobtypes.Order_GoodTilBlockTime{ + GoodTilBlockTime: uint32(ctx.BlockTime().Unix() + 100), + }, + } + for _, checkTx := range testapp.MustMakeCheckTxsWithClobMsg( + ctx, + tApp.App, + *clobtypes.NewMsgPlaceOrder(*bobOrder), + ) { + resp := tApp.CheckTx(checkTx) + require.True(t, resp.IsOK(), "Expected Bob's CheckTx to succeed. Response: %+v", resp) + } + + bobSubaccount := tApp.App.SubaccountsKeeper.GetSubaccount(ctx, constants.Bob_Num0) + require.True(t, bobSubaccount.AssetPositions != nil, "Bob should have a subaccount") + + // Alice's order should fail due to leverage config + aliceOrder := &clobtypes.Order{ + OrderId: clobtypes.OrderId{ + SubaccountId: constants.Alice_Num0, + ClientId: 0, + OrderFlags: clobtypes.OrderIdFlags_LongTerm, + ClobPairId: 0, + }, + Side: clobtypes.Order_SIDE_BUY, + Quantums: orderSize.BigInt().Uint64(), + Subticks: price, + GoodTilOneof: &clobtypes.Order_GoodTilBlockTime{ + GoodTilBlockTime: uint32(ctx.BlockTime().Unix() + 100), + }, + } + for _, checkTx := range testapp.MustMakeCheckTxsWithClobMsg( + ctx, + tApp.App, + *clobtypes.NewMsgPlaceOrder(*aliceOrder), + ) { + resp := tApp.CheckTx(checkTx) + require.False(t, resp.IsOK(), "Expected Alice's CheckTx to fail due to leverage. Response: %+v", resp) + } +} diff --git a/protocol/x/clob/keeper/liquidations.go b/protocol/x/clob/keeper/liquidations.go index aa4f9636d9..9b979f536f 100644 --- a/protocol/x/clob/keeper/liquidations.go +++ b/protocol/x/clob/keeper/liquidations.go @@ -456,12 +456,14 @@ func (k Keeper) GetBankruptcyPriceInQuoteQuantums( marketPrice, liquidityTier, psBig, + 0, // No custom IMF for liquidations ) riskPosNew := perplib.GetPositionNetNotionalValueAndMarginRequirements( perpetual, marketPrice, liquidityTier, new(big.Int).Add(psBig, deltaQuantums), + 0, // No custom IMF for liquidations ) // `DMMR = PMMRAD - PMMR`, where `PMMRAD` is the perpetual's maintenance margin requirement // with a position size of `PS + deltaQuantums`. @@ -546,6 +548,7 @@ func (k Keeper) GetFillablePrice( marketPrice, liquidityTier, psBig, + 0, // No custom IMF for liquidations ) riskTotal, err := k.subaccountsKeeper.GetNetCollateralAndMarginRequirements( diff --git a/protocol/x/clob/types/clob_keeper.go b/protocol/x/clob/types/clob_keeper.go index ad29d1f4ea..ad87a2b8de 100644 --- a/protocol/x/clob/types/clob_keeper.go +++ b/protocol/x/clob/types/clob_keeper.go @@ -155,4 +155,12 @@ type ClobKeeper interface { // Migrate order expiration state (for upgrading to 5.2 only) UnsafeMigrateOrderExpirationState(ctx sdk.Context) SetNextClobPairID(ctx sdk.Context, nextID uint32) +<<<<<<< HEAD +======= + + // Leverage methods + UpdateLeverage(ctx sdk.Context, subaccountId *satypes.SubaccountId, perpetualLeverage map[uint32]uint32) error + RateLimitUpdateLeverage(ctx sdk.Context, msg *MsgUpdateLeverage) error + GetSubaccountsKeeper() SubaccountsKeeper +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) } diff --git a/protocol/x/clob/types/expected_keepers.go b/protocol/x/clob/types/expected_keepers.go index fbc77e831d..cd7bcef9b4 100644 --- a/protocol/x/clob/types/expected_keepers.go +++ b/protocol/x/clob/types/expected_keepers.go @@ -105,6 +105,26 @@ type SubaccountsKeeper interface { revSharesForFill revsharetypes.RevSharesForFill, fillForProcess FillForProcess, ) error + + // Leverage methods + SetLeverage( + ctx sdk.Context, + subaccountId *satypes.SubaccountId, + leverageMap map[uint32]uint32, + ) + GetLeverage( + ctx sdk.Context, + subaccountId *satypes.SubaccountId, + ) (map[uint32]uint32, bool) + UpdateLeverage( + ctx sdk.Context, + subaccountId *satypes.SubaccountId, + perpetualLeverage map[uint32]uint32, + ) error + GetMinImfForPerpetual( + ctx sdk.Context, + perpetualId uint32, + ) (uint32, error) } type AssetsKeeper interface { diff --git a/protocol/x/clob/types/leverage.go b/protocol/x/clob/types/leverage.go new file mode 100644 index 0000000000..2a40f030b6 --- /dev/null +++ b/protocol/x/clob/types/leverage.go @@ -0,0 +1,75 @@ +package types + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func ValidateUpdateLeverageMsg(ctx sdk.Context, msg *MsgUpdateLeverage, clobKeeper ClobKeeper) error { + if msg.SubaccountId == nil { + return errorsmod.Wrap(ErrInvalidAddress, "subaccount ID cannot be nil") + } + + if err := msg.SubaccountId.Validate(); err != nil { + return err + } + + // Validate that leverage entries are not empty + if len(msg.ClobPairLeverage) == 0 { + return errorsmod.Wrap(ErrInvalidLeverage, "clob pair leverage entries cannot be empty") + } + + // Validate leverage values are positive and clob pair IDs are unique + clobPairIds := make(map[uint32]bool) + for _, entry := range msg.ClobPairLeverage { + if entry == nil { + return errorsmod.Wrap(ErrInvalidLeverage, "leverage entry cannot be nil") + } + + if entry.CustomImfPpm == 0 || entry.CustomImfPpm > 1_000_000 { + return errorsmod.Wrap( + ErrInvalidLeverage, + fmt.Sprintf("imf ppm for clob pair %d must be between (0, 1,000,000]", entry.ClobPairId), + ) + } + + if clobPairIds[entry.ClobPairId] { + return errorsmod.Wrap( + ErrInvalidLeverage, + fmt.Sprintf("duplicate clob pair ID %d", entry.ClobPairId), + ) + } + + // Validate that the clob pair ID is a valid clob pair ID + if _, found := clobKeeper.GetClobPair(ctx, ClobPairId(entry.ClobPairId)); !found { + return errorsmod.Wrap( + ErrInvalidClob, + fmt.Sprintf("clob pair ID %d does not exist", entry.ClobPairId), + ) + } + clobPairIds[entry.ClobPairId] = true + } + + return nil +} + +func ValidateAndConstructPerpetualLeverageMap( + ctx sdk.Context, + msg *MsgUpdateLeverage, + clobKeeper ClobKeeper, +) (map[uint32]uint32, error) { + if err := ValidateUpdateLeverageMsg(ctx, msg, clobKeeper); err != nil { + return nil, err + } + + perpetualLeverageMap := make(map[uint32]uint32) + for _, entry := range msg.ClobPairLeverage { + clob, _ := clobKeeper.GetClobPair(ctx, ClobPairId(entry.ClobPairId)) + perpetualId := clob.MustGetPerpetualId() + perpetualLeverageMap[perpetualId] = entry.CustomImfPpm + } + + return perpetualLeverageMap, nil +} diff --git a/protocol/x/clob/types/query.pb.go b/protocol/x/clob/types/query.pb.go index 335430b2c0..76d9d186b0 100644 --- a/protocol/x/clob/types/query.pb.go +++ b/protocol/x/clob/types/query.pb.go @@ -849,6 +849,165 @@ func (m *QueryNextClobPairIdResponse) GetNextClobPairId() uint32 { return 0 } +<<<<<<< HEAD +======= +// QueryLeverageRequest is a request message for Leverage. +type QueryLeverageRequest struct { + // The address of the wallet that owns the subaccount. + Owner string `protobuf:"bytes,1,opt,name=owner,proto3" json:"owner,omitempty"` + // The unique number of the subaccount for the owner. + Number uint32 `protobuf:"varint,2,opt,name=number,proto3" json:"number,omitempty"` +} + +func (m *QueryLeverageRequest) Reset() { *m = QueryLeverageRequest{} } +func (m *QueryLeverageRequest) String() string { return proto.CompactTextString(m) } +func (*QueryLeverageRequest) ProtoMessage() {} +func (*QueryLeverageRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_3365c195b25c5bc0, []int{16} +} +func (m *QueryLeverageRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLeverageRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLeverageRequest.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 *QueryLeverageRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLeverageRequest.Merge(m, src) +} +func (m *QueryLeverageRequest) XXX_Size() int { + return m.Size() +} +func (m *QueryLeverageRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLeverageRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLeverageRequest proto.InternalMessageInfo + +func (m *QueryLeverageRequest) GetOwner() string { + if m != nil { + return m.Owner + } + return "" +} + +func (m *QueryLeverageRequest) GetNumber() uint32 { + if m != nil { + return m.Number + } + return 0 +} + +// QueryLeverageResponse is a response message that contains the leverage map. +type QueryLeverageResponse struct { + // List of clob pair leverage settings. + ClobPairLeverage []*ClobPairLeverageInfo `protobuf:"bytes,1,rep,name=clob_pair_leverage,json=clobPairLeverage,proto3" json:"clob_pair_leverage,omitempty"` +} + +func (m *QueryLeverageResponse) Reset() { *m = QueryLeverageResponse{} } +func (m *QueryLeverageResponse) String() string { return proto.CompactTextString(m) } +func (*QueryLeverageResponse) ProtoMessage() {} +func (*QueryLeverageResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_3365c195b25c5bc0, []int{17} +} +func (m *QueryLeverageResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QueryLeverageResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QueryLeverageResponse.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 *QueryLeverageResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QueryLeverageResponse.Merge(m, src) +} +func (m *QueryLeverageResponse) XXX_Size() int { + return m.Size() +} +func (m *QueryLeverageResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QueryLeverageResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QueryLeverageResponse proto.InternalMessageInfo + +func (m *QueryLeverageResponse) GetClobPairLeverage() []*ClobPairLeverageInfo { + if m != nil { + return m.ClobPairLeverage + } + return nil +} + +// ClobPairLeverageInfo represents the leverage setting for a single clob pair. +type ClobPairLeverageInfo struct { + // The clob pair ID. + ClobPairId uint32 `protobuf:"varint,1,opt,name=clob_pair_id,json=clobPairId,proto3" json:"clob_pair_id,omitempty"` + // The user selected imf. + CustomImfPpm uint32 `protobuf:"varint,2,opt,name=custom_imf_ppm,json=customImfPpm,proto3" json:"custom_imf_ppm,omitempty"` +} + +func (m *ClobPairLeverageInfo) Reset() { *m = ClobPairLeverageInfo{} } +func (m *ClobPairLeverageInfo) String() string { return proto.CompactTextString(m) } +func (*ClobPairLeverageInfo) ProtoMessage() {} +func (*ClobPairLeverageInfo) Descriptor() ([]byte, []int) { + return fileDescriptor_3365c195b25c5bc0, []int{18} +} +func (m *ClobPairLeverageInfo) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClobPairLeverageInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ClobPairLeverageInfo.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 *ClobPairLeverageInfo) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClobPairLeverageInfo.Merge(m, src) +} +func (m *ClobPairLeverageInfo) XXX_Size() int { + return m.Size() +} +func (m *ClobPairLeverageInfo) XXX_DiscardUnknown() { + xxx_messageInfo_ClobPairLeverageInfo.DiscardUnknown(m) +} + +var xxx_messageInfo_ClobPairLeverageInfo proto.InternalMessageInfo + +func (m *ClobPairLeverageInfo) GetClobPairId() uint32 { + if m != nil { + return m.ClobPairId + } + return 0 +} + +func (m *ClobPairLeverageInfo) GetCustomImfPpm() uint32 { + if m != nil { + return m.CustomImfPpm + } + return 0 +} + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) // StreamOrderbookUpdatesRequest is a request message for the // StreamOrderbookUpdates method. type StreamOrderbookUpdatesRequest struct { @@ -1451,6 +1610,7 @@ func init() { func init() { proto.RegisterFile("dydxprotocol/clob/query.proto", fileDescriptor_3365c195b25c5bc0) } var fileDescriptor_3365c195b25c5bc0 = []byte{ +<<<<<<< HEAD // 1798 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0x4d, 0x6c, 0xdc, 0xc6, 0x15, 0x5e, 0x4a, 0xb2, 0x2d, 0xbd, 0xb5, 0x14, 0x69, 0x1c, 0x3b, 0x9b, 0x95, 0xbc, 0x92, 0xe9, @@ -1565,6 +1725,130 @@ var fileDescriptor_3365c195b25c5bc0 = []byte{ 0x6c, 0xe6, 0x65, 0x4d, 0xe9, 0x7f, 0x70, 0x57, 0x0c, 0x24, 0xc6, 0x80, 0x72, 0x2c, 0xcd, 0xe3, 0x27, 0x3d, 0x12, 0xb6, 0x2f, 0x0a, 0xf2, 0xfb, 0xdf, 0x04, 0x00, 0x00, 0xff, 0xff, 0x55, 0xfb, 0x6d, 0x6f, 0xdd, 0x15, 0x00, 0x00, +======= + // 1933 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0x4d, 0x6c, 0xdc, 0xc6, + 0x15, 0x5e, 0x4a, 0xb2, 0x2d, 0xbd, 0x95, 0x14, 0x69, 0x2c, 0x3b, 0xca, 0x4a, 0x5e, 0xc9, 0xb4, + 0xad, 0x1f, 0xc7, 0x5e, 0xca, 0x8a, 0x11, 0xa4, 0x76, 0x91, 0xc2, 0x72, 0x6a, 0x4b, 0xa8, 0x95, + 0x6c, 0x68, 0xc7, 0x31, 0xda, 0xa0, 0x04, 0x97, 0x9c, 0x5d, 0x0d, 0x44, 0x72, 0x28, 0x72, 0xb8, + 0x95, 0x60, 0x18, 0x05, 0x7a, 0xc8, 0xa5, 0x2d, 0x50, 0x20, 0x87, 0x1e, 0x8a, 0x9e, 0x7a, 0x2e, + 0xd0, 0x4b, 0x8f, 0x45, 0xdb, 0x5b, 0x8e, 0x01, 0xda, 0x43, 0x0f, 0x45, 0x51, 0xd8, 0x3d, 0xf7, + 0x52, 0xa0, 0xe7, 0x80, 0x33, 0xc3, 0x5d, 0x72, 0x49, 0xae, 0xd6, 0xbe, 0x48, 0x3b, 0x6f, 0xde, + 0xcf, 0xf7, 0xe6, 0xbd, 0x99, 0xf7, 0x1e, 0xe1, 0x92, 0x7d, 0x62, 0x1f, 0xfb, 0x01, 0x65, 0xd4, + 0xa2, 0x8e, 0x66, 0x39, 0xb4, 0xa5, 0x1d, 0x45, 0x38, 0x38, 0x69, 0x70, 0x1a, 0x9a, 0x4f, 0x6f, + 0x37, 0xe2, 0xed, 0xda, 0x42, 0x87, 0x76, 0x28, 0x27, 0x69, 0xf1, 0x2f, 0xc1, 0x58, 0x5b, 0xee, + 0x50, 0xda, 0x71, 0xb0, 0x66, 0xfa, 0x44, 0x33, 0x3d, 0x8f, 0x32, 0x93, 0x11, 0xea, 0x85, 0x72, + 0xf7, 0xba, 0x45, 0x43, 0x97, 0x86, 0x5a, 0xcb, 0x0c, 0xb1, 0xd0, 0xaf, 0x75, 0x6f, 0xb5, 0x30, + 0x33, 0x6f, 0x69, 0xbe, 0xd9, 0x21, 0x1e, 0x67, 0x96, 0xbc, 0x5a, 0x1e, 0x51, 0xcb, 0xa1, 0xd6, + 0xa1, 0x11, 0x98, 0x0c, 0x1b, 0x0e, 0x71, 0x09, 0x33, 0x2c, 0xea, 0xb5, 0x49, 0x47, 0x0a, 0x5c, + 0xce, 0x0b, 0xc4, 0x7f, 0x0c, 0xdf, 0x24, 0x81, 0x64, 0xd9, 0xca, 0xb3, 0xe0, 0xa3, 0x88, 0xb0, + 0x13, 0x83, 0x11, 0x1c, 0x14, 0x29, 0x2d, 0x38, 0x17, 0x1a, 0xd8, 0x38, 0x51, 0xb8, 0x92, 0xdf, + 0x76, 0x4d, 0x66, 0x1d, 0xe0, 0xc4, 0xe3, 0x77, 0xf3, 0x0c, 0x0e, 0x39, 0x8a, 0x88, 0x2d, 0xce, + 0x25, 0x6b, 0x6c, 0xa9, 0x40, 0x1b, 0xee, 0xca, 0xcd, 0x0f, 0x33, 0x9b, 0xc4, 0xb3, 0xf1, 0x31, + 0x0e, 0x34, 0xda, 0x6e, 0x1b, 0xd6, 0x81, 0x49, 0x3c, 0x23, 0xf2, 0x6d, 0x93, 0xe1, 0x30, 0x4f, + 0x91, 0xf2, 0x1b, 0x19, 0xf9, 0x30, 0x6a, 0x99, 0x96, 0x45, 0x23, 0x8f, 0x85, 0x5a, 0xc8, 0x02, + 0x6c, 0xba, 0xc4, 0x4b, 0x60, 0x6c, 0x96, 0x73, 0xf6, 0x7e, 0x4b, 0xd6, 0x2b, 0x19, 0x56, 0x3f, + 0x20, 0x16, 0xce, 0xe9, 0x53, 0x37, 0xe1, 0xed, 0x4f, 0xe3, 0x58, 0x3f, 0xc4, 0xec, 0xbe, 0x43, + 0x5b, 0x4d, 0x93, 0x04, 0x3a, 0x3e, 0x8a, 0x70, 0xc8, 0xd0, 0x2c, 0x8c, 0x11, 0x7b, 0x51, 0x59, + 0x55, 0x36, 0x66, 0xf4, 0x31, 0x62, 0xab, 0x9f, 0xc3, 0x05, 0xce, 0xda, 0xe7, 0x0b, 0x7d, 0xea, + 0x85, 0x18, 0x7d, 0x08, 0x53, 0xbd, 0x60, 0x72, 0xfe, 0xea, 0xf6, 0x52, 0x23, 0x97, 0x94, 0x8d, + 0x44, 0x6e, 0x67, 0xe2, 0xeb, 0x7f, 0xad, 0x54, 0xf4, 0x49, 0x4b, 0xae, 0x55, 0x53, 0x62, 0xb8, + 0xe7, 0x38, 0x83, 0x18, 0x1e, 0x00, 0xf4, 0x93, 0x4f, 0xea, 0x5e, 0x6b, 0x88, 0x4c, 0x6d, 0xc4, + 0x99, 0xda, 0x10, 0x37, 0x41, 0x66, 0x6a, 0xa3, 0x69, 0x76, 0xb0, 0x94, 0xd5, 0x53, 0x92, 0xea, + 0xef, 0x14, 0x58, 0xcc, 0x80, 0xbf, 0xe7, 0x38, 0x65, 0xf8, 0xc7, 0x5f, 0x13, 0x3f, 0x7a, 0x98, + 0x01, 0x39, 0xc6, 0x41, 0xae, 0x9f, 0x0a, 0x52, 0x18, 0xcf, 0xa0, 0xfc, 0xa7, 0x02, 0x2b, 0xfb, + 0xb8, 0xfb, 0x31, 0xb5, 0xf1, 0x13, 0x1a, 0xff, 0xbd, 0x6f, 0x3a, 0x56, 0xe4, 0xf0, 0xcd, 0xe4, + 0x44, 0xbe, 0x80, 0x8b, 0xe2, 0xaa, 0xf9, 0x01, 0xf5, 0x69, 0x88, 0x03, 0x43, 0x26, 0x75, 0xef, + 0x74, 0xf2, 0xc8, 0x9f, 0x9a, 0x4e, 0x9c, 0xd4, 0x34, 0xd8, 0xc7, 0xdd, 0x7d, 0xc1, 0xad, 0x2f, + 0x70, 0x2d, 0x4d, 0xa9, 0x44, 0x52, 0xd1, 0x8f, 0xe0, 0x42, 0x37, 0x61, 0x36, 0x5c, 0xdc, 0x35, + 0x5c, 0xcc, 0x02, 0x62, 0x85, 0x3d, 0xaf, 0xf2, 0xca, 0x33, 0x80, 0xf7, 0x05, 0xbb, 0x7e, 0xbe, + 0x9b, 0x36, 0x29, 0x88, 0xea, 0x7f, 0x15, 0x58, 0x2d, 0x77, 0x4f, 0x06, 0xa3, 0x03, 0xe7, 0x02, + 0x1c, 0x46, 0x0e, 0x0b, 0x65, 0x28, 0x1e, 0x9e, 0x66, 0xb3, 0x40, 0x4b, 0xcc, 0x70, 0xcf, 0xb3, + 0x9f, 0x52, 0x27, 0x72, 0x71, 0x13, 0x07, 0x71, 0xe8, 0x64, 0xd8, 0x12, 0xed, 0x35, 0x13, 0xce, + 0x17, 0x70, 0xa1, 0x55, 0x98, 0xee, 0x25, 0x83, 0xd1, 0xcb, 0x7f, 0x48, 0x82, 0xbd, 0x67, 0xa3, + 0x39, 0x18, 0x77, 0x71, 0x97, 0x9f, 0xc8, 0x98, 0x1e, 0xff, 0x44, 0x17, 0xe1, 0x6c, 0x97, 0x2b, + 0x59, 0x1c, 0x5f, 0x55, 0x36, 0x26, 0x74, 0xb9, 0x52, 0xaf, 0xc3, 0x06, 0x4f, 0xba, 0xef, 0xf3, + 0x77, 0xec, 0x09, 0xc1, 0xc1, 0xa3, 0xf8, 0x15, 0xbb, 0xcf, 0xdf, 0x95, 0x28, 0x48, 0xc7, 0x55, + 0xfd, 0x8d, 0x02, 0x9b, 0x23, 0x30, 0xcb, 0x53, 0xf2, 0x60, 0xb1, 0xec, 0x71, 0x94, 0x79, 0xa0, + 0x15, 0x1c, 0xdb, 0x30, 0xd5, 0xf2, 0x78, 0x2e, 0xe0, 0x22, 0x1e, 0x75, 0x13, 0xd6, 0x39, 0xb8, + 0x9d, 0x38, 0x69, 0x74, 0x93, 0xe1, 0x72, 0x47, 0x7e, 0xad, 0x48, 0xaf, 0x87, 0xf2, 0x4a, 0x3f, + 0x0e, 0xe1, 0xed, 0x92, 0xc2, 0x21, 0xdd, 0x68, 0x14, 0xb8, 0x31, 0x44, 0xb1, 0xf4, 0x42, 0x24, + 0xf7, 0x00, 0x8b, 0xfa, 0x0c, 0xde, 0xe1, 0xc0, 0x1e, 0x33, 0x93, 0xe1, 0x76, 0xe4, 0x7c, 0x12, + 0x17, 0x8b, 0xe4, 0x5e, 0xdd, 0x85, 0x49, 0x5e, 0x3c, 0x92, 0x98, 0x57, 0xb7, 0x6b, 0x05, 0xa6, + 0xb9, 0xc8, 0x9e, 0x9d, 0xe4, 0x12, 0x15, 0x4b, 0xf5, 0x8f, 0x0a, 0xd4, 0x8a, 0x54, 0x4b, 0x2f, + 0x9f, 0xc1, 0x5b, 0x42, 0xb7, 0xef, 0x98, 0x16, 0x76, 0xb1, 0xc7, 0xa4, 0x89, 0xcd, 0x02, 0x13, + 0x8f, 0xa8, 0xd7, 0x79, 0x82, 0x03, 0x97, 0xab, 0x68, 0x26, 0x02, 0xd2, 0xe2, 0x2c, 0xcd, 0x50, + 0xd1, 0x0a, 0x54, 0xdb, 0xc4, 0x71, 0x0c, 0xd3, 0x8d, 0x1f, 0x7e, 0x9e, 0x93, 0x13, 0x3a, 0xc4, + 0xa4, 0x7b, 0x9c, 0x82, 0x96, 0x61, 0x8a, 0x05, 0xa4, 0xd3, 0xc1, 0x01, 0xb6, 0x79, 0x76, 0x4e, + 0xea, 0x7d, 0x82, 0xba, 0x0e, 0xd7, 0x38, 0xec, 0x47, 0xa9, 0xb2, 0x57, 0x18, 0xd4, 0x2f, 0x15, + 0x58, 0x3b, 0x8d, 0x53, 0x3a, 0xfb, 0x05, 0x9c, 0x2f, 0xa8, 0xa2, 0xd2, 0xe1, 0x6b, 0x45, 0x0e, + 0xe7, 0x54, 0x4a, 0x67, 0x91, 0x93, 0xdb, 0x51, 0x97, 0xe5, 0x41, 0x7f, 0x8c, 0x8f, 0x7b, 0x05, + 0x6b, 0xcf, 0x4e, 0x60, 0xee, 0xc2, 0x52, 0xe1, 0xae, 0x84, 0xb6, 0x09, 0xf3, 0x1e, 0x3e, 0x66, + 0x46, 0xc1, 0x05, 0x9f, 0xf5, 0x32, 0x22, 0xea, 0x47, 0xb0, 0x20, 0xfc, 0xc5, 0x5d, 0x1c, 0xf4, + 0x8b, 0x0a, 0x5a, 0x80, 0x33, 0xf4, 0x27, 0x1e, 0x16, 0x75, 0x6e, 0x4a, 0x17, 0x8b, 0xf8, 0x01, + 0xf0, 0x22, 0xb7, 0x85, 0x03, 0x1e, 0x81, 0x19, 0x5d, 0xae, 0x54, 0x4f, 0x96, 0xcc, 0xbe, 0x16, + 0x89, 0xe4, 0x33, 0x40, 0x7d, 0x10, 0x8e, 0xdc, 0x95, 0x0f, 0xde, 0xfa, 0x90, 0xda, 0x93, 0x28, + 0xda, 0xf3, 0xda, 0x54, 0x9f, 0xb3, 0x06, 0xa8, 0xea, 0x8f, 0x61, 0xa1, 0x88, 0x73, 0x84, 0x47, + 0xed, 0x2a, 0xcc, 0x5a, 0x51, 0xc8, 0xa8, 0x6b, 0x10, 0xb7, 0x6d, 0xf8, 0xbe, 0x2b, 0x3d, 0x99, + 0x16, 0xd4, 0x3d, 0xb7, 0xdd, 0xf4, 0x5d, 0xf5, 0x7f, 0x0a, 0x5c, 0x7a, 0xcc, 0x3b, 0x08, 0x9e, + 0x9d, 0x2d, 0x4a, 0x0f, 0x3f, 0x13, 0x8d, 0x4c, 0x72, 0x3e, 0x79, 0x4b, 0xe3, 0x03, 0x96, 0xf6, + 0x61, 0xb6, 0xdf, 0xaa, 0x18, 0xc4, 0x8e, 0x6b, 0xcb, 0x78, 0xbe, 0x70, 0xa5, 0x5a, 0x9b, 0xc6, + 0xe3, 0xde, 0xef, 0x3d, 0x5b, 0x9f, 0x09, 0x53, 0xab, 0x10, 0x5d, 0x02, 0x70, 0xcd, 0xe0, 0x10, + 0x0b, 0x55, 0xe3, 0xdc, 0xdc, 0x94, 0xa0, 0xc4, 0xdb, 0x3b, 0x50, 0x6f, 0x13, 0x87, 0xe1, 0xc0, + 0xe0, 0x37, 0x27, 0x34, 0x5a, 0x27, 0x46, 0xc6, 0xfc, 0xe2, 0x04, 0xbf, 0x14, 0x35, 0xc1, 0xc5, + 0xdd, 0x0a, 0x77, 0x4e, 0xd2, 0x16, 0x55, 0x13, 0xea, 0x65, 0x4e, 0xcb, 0x70, 0x7e, 0x0f, 0xce, + 0xc9, 0x86, 0x4e, 0xc6, 0x70, 0xa5, 0x20, 0x86, 0x42, 0x87, 0x10, 0x4d, 0x1e, 0x10, 0x29, 0xa5, + 0xfe, 0x7f, 0x1c, 0xa6, 0xd3, 0xfb, 0xe8, 0x32, 0x4c, 0x8b, 0x87, 0xf1, 0x00, 0x93, 0xce, 0x01, + 0x93, 0x11, 0xab, 0x72, 0xda, 0x2e, 0x27, 0xa1, 0x25, 0x98, 0xc2, 0xc7, 0xd8, 0x32, 0x5c, 0x6a, + 0x63, 0x19, 0xad, 0xc9, 0x98, 0xb0, 0x4f, 0xed, 0x38, 0xc1, 0xe6, 0x68, 0x82, 0x56, 0x36, 0x9b, + 0xfc, 0xfa, 0x57, 0xb7, 0x37, 0x4a, 0xa1, 0x0d, 0xb8, 0xb7, 0x5b, 0xd1, 0xdf, 0xa2, 0x59, 0x52, + 0xdc, 0xea, 0x88, 0x97, 0x2c, 0x7e, 0x62, 0xf8, 0xd1, 0x15, 0x77, 0x1c, 0x03, 0x0a, 0x1f, 0x10, + 0xc7, 0xd9, 0xad, 0xe8, 0x53, 0x5c, 0x36, 0x5e, 0xa0, 0x07, 0x50, 0x65, 0xe6, 0x61, 0x12, 0x96, + 0xc5, 0x33, 0x5c, 0xd3, 0x95, 0x52, 0x4d, 0x4f, 0x62, 0x5e, 0xae, 0x6e, 0xb7, 0xa2, 0x03, 0xeb, + 0xad, 0x90, 0x01, 0xf3, 0xa9, 0x70, 0x4a, 0x47, 0xcf, 0x72, 0x6d, 0x5b, 0x43, 0x12, 0x8a, 0x2b, + 0xed, 0x07, 0xb9, 0xe7, 0xf0, 0x5c, 0x38, 0x40, 0x43, 0x3f, 0x80, 0x69, 0xde, 0x3a, 0x27, 0xba, + 0xcf, 0x15, 0xf9, 0x2c, 0x9a, 0x6b, 0xa9, 0xb6, 0x19, 0x2f, 0x7a, 0x1a, 0xab, 0x7e, 0x7f, 0xb9, + 0x33, 0x07, 0xb3, 0x42, 0x8d, 0xe1, 0xe2, 0x30, 0x8c, 0x6f, 0xec, 0x2f, 0x15, 0xb8, 0x50, 0x78, + 0xfa, 0xa8, 0x06, 0x93, 0xa1, 0x67, 0xfa, 0xe1, 0x01, 0x15, 0xd1, 0x9f, 0xd4, 0x7b, 0x6b, 0xf4, + 0xac, 0x9f, 0x6f, 0xe2, 0xf2, 0x7c, 0x90, 0xc5, 0x23, 0x27, 0x90, 0x46, 0x7e, 0xde, 0xf8, 0xa4, + 0xdd, 0xbe, 0x1f, 0x13, 0x84, 0x91, 0xa7, 0xb7, 0x06, 0x13, 0xf1, 0xf7, 0x0a, 0x9c, 0x2f, 0x08, + 0x1e, 0xba, 0x0b, 0xfc, 0x0e, 0x8b, 0x66, 0x53, 0x3e, 0xe6, 0xcb, 0x25, 0x0f, 0x15, 0x6f, 0x26, + 0x75, 0xde, 0x53, 0xf3, 0x9f, 0xe8, 0x7d, 0x38, 0x2b, 0x6e, 0x9f, 0x44, 0xbb, 0x58, 0x56, 0x59, + 0x25, 0x1a, 0xc9, 0x1d, 0x5f, 0x82, 0x54, 0x75, 0x13, 0xb7, 0x7b, 0x42, 0xaf, 0xf6, 0xcb, 0x5b, + 0xa8, 0x7e, 0x39, 0x06, 0x73, 0x83, 0x29, 0x82, 0xb6, 0xe0, 0x8c, 0x48, 0x2b, 0x81, 0xb3, 0xd4, + 0xdc, 0x6e, 0x45, 0x17, 0x8c, 0xe8, 0x19, 0xcc, 0xa7, 0x8a, 0x8d, 0x4c, 0xca, 0xb1, 0xd2, 0x1a, + 0x2d, 0x2c, 0xa6, 0x0a, 0x57, 0xa2, 0x6e, 0xce, 0x19, 0xa0, 0xa1, 0xcf, 0x01, 0xa5, 0x12, 0xdd, + 0x08, 0x99, 0xc9, 0xa2, 0x50, 0x5e, 0xc5, 0xcd, 0x11, 0xf2, 0xfd, 0x31, 0x17, 0xd0, 0xe7, 0xd8, + 0x00, 0x65, 0x67, 0x26, 0x73, 0x83, 0xd4, 0x3f, 0x28, 0x70, 0xb1, 0x58, 0x36, 0x3e, 0xc6, 0x8c, + 0x71, 0xf9, 0x96, 0xd0, 0x14, 0xcb, 0x4d, 0x40, 0x01, 0x76, 0x4d, 0xe2, 0x11, 0xaf, 0x63, 0x1c, + 0x45, 0xa6, 0xc7, 0x22, 0x37, 0x94, 0xed, 0xc4, 0x7c, 0x6f, 0xe7, 0x53, 0xb9, 0x81, 0x3e, 0x82, + 0x3a, 0xf5, 0x19, 0x71, 0x49, 0xc8, 0x88, 0x65, 0x3a, 0xce, 0x09, 0x7f, 0x0f, 0xb0, 0xdd, 0x17, + 0x15, 0x8d, 0xf0, 0x72, 0x96, 0xeb, 0x01, 0x67, 0x4a, 0xb4, 0x6c, 0xff, 0x7d, 0x1a, 0xce, 0xf0, + 0xf2, 0x88, 0x7e, 0xae, 0xc0, 0x64, 0x52, 0xb8, 0xd0, 0xf5, 0x82, 0x53, 0x29, 0x99, 0x51, 0x6b, + 0x1b, 0x65, 0xbc, 0x83, 0x43, 0xaa, 0xba, 0xf9, 0xb3, 0xbf, 0xfd, 0xe7, 0xab, 0xb1, 0x2b, 0xe8, + 0xb2, 0x36, 0xe4, 0x53, 0x84, 0xf6, 0x9c, 0xd8, 0x2f, 0xd0, 0x2f, 0x14, 0xa8, 0xa6, 0xe6, 0xc4, + 0x72, 0x40, 0xf9, 0x81, 0xb5, 0xf6, 0xee, 0x69, 0x80, 0x52, 0x83, 0xa7, 0x7a, 0x95, 0x63, 0xaa, + 0xa3, 0xe5, 0x61, 0x98, 0xd0, 0x9f, 0x15, 0x58, 0x2c, 0x1b, 0x78, 0xd0, 0xf6, 0x6b, 0x4d, 0x47, + 0x02, 0xe3, 0x7b, 0x6f, 0x30, 0x51, 0xa9, 0x77, 0x38, 0xd6, 0xdb, 0x77, 0x94, 0xeb, 0xaa, 0xa6, + 0x15, 0x7e, 0x0b, 0x31, 0x3c, 0x6a, 0x63, 0x83, 0x51, 0xf1, 0xdf, 0x4a, 0x81, 0xfc, 0xab, 0x02, + 0xcb, 0xc3, 0x66, 0x0f, 0x74, 0xb7, 0xec, 0xd4, 0x46, 0x98, 0x9c, 0x6a, 0xdf, 0x7d, 0x33, 0x61, + 0xe9, 0xd7, 0x1a, 0xf7, 0x6b, 0x15, 0xd5, 0xb5, 0xa1, 0xdf, 0x9f, 0xd0, 0x9f, 0x14, 0x58, 0x1a, + 0x32, 0x78, 0xa0, 0x3b, 0x65, 0x28, 0x4e, 0x1f, 0x99, 0x6a, 0x77, 0xdf, 0x48, 0x56, 0x3a, 0x70, + 0x8d, 0x3b, 0xb0, 0x82, 0x2e, 0x0d, 0xfd, 0x28, 0x87, 0xfe, 0xa2, 0xc0, 0x3b, 0xa5, 0xcd, 0x3b, + 0xfa, 0xa0, 0x0c, 0xc1, 0x69, 0x93, 0x41, 0xed, 0x3b, 0x6f, 0x20, 0x29, 0x91, 0x37, 0x38, 0xf2, + 0x0d, 0xb4, 0xa6, 0x8d, 0xf4, 0x21, 0x0e, 0x79, 0x30, 0x93, 0x99, 0xaf, 0xd0, 0x8d, 0x32, 0xdb, + 0x45, 0x13, 0x5e, 0xed, 0xe6, 0x88, 0xdc, 0x12, 0x5d, 0x05, 0xfd, 0x56, 0x81, 0xd9, 0xec, 0x24, + 0x81, 0x4a, 0x75, 0x14, 0xce, 0x23, 0xb5, 0xc6, 0xa8, 0xec, 0xd2, 0xe6, 0x0d, 0x7e, 0x22, 0x6b, + 0xe8, 0x6a, 0xc1, 0x89, 0xe4, 0x26, 0x17, 0xf4, 0x95, 0x02, 0x93, 0x49, 0x9b, 0x8f, 0xd6, 0x4b, + 0xe3, 0x90, 0x9d, 0x60, 0xca, 0x9f, 0xcc, 0xc1, 0x21, 0x45, 0xbd, 0xcd, 0xd1, 0x34, 0xd0, 0x8d, + 0xa2, 0xf8, 0x48, 0x66, 0xed, 0x39, 0x9f, 0x80, 0x5e, 0x68, 0xcf, 0xc5, 0xc8, 0xf3, 0x02, 0xfd, + 0x34, 0xa9, 0x43, 0x83, 0xdd, 0x32, 0xda, 0x1a, 0xb5, 0xf3, 0x4c, 0xa6, 0x89, 0xda, 0xad, 0xd7, + 0x90, 0x10, 0xa0, 0xb7, 0x94, 0x9d, 0xe6, 0xd7, 0x2f, 0xeb, 0xca, 0x37, 0x2f, 0xeb, 0xca, 0xbf, + 0x5f, 0xd6, 0x95, 0x5f, 0xbd, 0xaa, 0x57, 0xbe, 0x79, 0x55, 0xaf, 0xfc, 0xe3, 0x55, 0xbd, 0xf2, + 0xc3, 0xf7, 0x3b, 0x84, 0x1d, 0x44, 0xad, 0x86, 0x45, 0xdd, 0xac, 0x4b, 0xdd, 0xdb, 0x37, 0x79, + 0x9b, 0xa4, 0xf5, 0x28, 0xc7, 0xc2, 0x4d, 0x76, 0xe2, 0xe3, 0xb0, 0x75, 0x96, 0x93, 0xdf, 0xfb, + 0x36, 0x00, 0x00, 0xff, 0xff, 0x6a, 0xb8, 0x06, 0x80, 0x89, 0x17, 0x00, 0x00, +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) } // Reference imports to suppress errors if they are not otherwise used. @@ -2551,6 +2835,114 @@ func (m *QueryNextClobPairIdResponse) MarshalToSizedBuffer(dAtA []byte) (int, er return len(dAtA) - i, nil } +<<<<<<< HEAD +======= +func (m *QueryLeverageRequest) 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 *QueryLeverageRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLeverageRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Number != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.Number)) + i-- + dAtA[i] = 0x10 + } + if len(m.Owner) > 0 { + i -= len(m.Owner) + copy(dAtA[i:], m.Owner) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Owner))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QueryLeverageResponse) 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 *QueryLeverageResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QueryLeverageResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ClobPairLeverage) > 0 { + for iNdEx := len(m.ClobPairLeverage) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ClobPairLeverage[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *ClobPairLeverageInfo) 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 *ClobPairLeverageInfo) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ClobPairLeverageInfo) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CustomImfPpm != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.CustomImfPpm)) + i-- + dAtA[i] = 0x10 + } + if m.ClobPairId != 0 { + i = encodeVarintQuery(dAtA, i, uint64(m.ClobPairId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) func (m *StreamOrderbookUpdatesRequest) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -3281,6 +3673,55 @@ func (m *QueryNextClobPairIdResponse) Size() (n int) { return n } +<<<<<<< HEAD +======= +func (m *QueryLeverageRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Owner) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + if m.Number != 0 { + n += 1 + sovQuery(uint64(m.Number)) + } + return n +} + +func (m *QueryLeverageResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.ClobPairLeverage) > 0 { + for _, e := range m.ClobPairLeverage { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } + } + return n +} + +func (m *ClobPairLeverageInfo) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ClobPairId != 0 { + n += 1 + sovQuery(uint64(m.ClobPairId)) + } + if m.CustomImfPpm != 0 { + n += 1 + sovQuery(uint64(m.CustomImfPpm)) + } + return n +} + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) func (m *StreamOrderbookUpdatesRequest) Size() (n int) { if m == nil { return 0 @@ -4900,6 +5341,282 @@ func (m *QueryNextClobPairIdResponse) Unmarshal(dAtA []byte) error { } return nil } +<<<<<<< HEAD +======= +func (m *QueryLeverageRequest) 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 ErrIntOverflowQuery + } + 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: QueryLeverageRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLeverageRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Owner = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Number", wireType) + } + m.Number = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Number |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QueryLeverageResponse) 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 ErrIntOverflowQuery + } + 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: QueryLeverageResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QueryLeverageResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClobPairLeverage", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClobPairLeverage = append(m.ClobPairLeverage, &ClobPairLeverageInfo{}) + if err := m.ClobPairLeverage[len(m.ClobPairLeverage)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ClobPairLeverageInfo) 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 ErrIntOverflowQuery + } + 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: ClobPairLeverageInfo: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClobPairLeverageInfo: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ClobPairId", wireType) + } + m.ClobPairId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ClobPairId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CustomImfPpm", wireType) + } + m.CustomImfPpm = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CustomImfPpm |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) func (m *StreamOrderbookUpdatesRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/protocol/x/clob/types/tx.pb.go b/protocol/x/clob/types/tx.pb.go index 511f805142..21c569d8c6 100644 --- a/protocol/x/clob/types/tx.pb.go +++ b/protocol/x/clob/types/tx.pb.go @@ -1091,6 +1091,157 @@ func (m *MsgUpdateLiquidationsConfigResponse) XXX_DiscardUnknown() { var xxx_messageInfo_MsgUpdateLiquidationsConfigResponse proto.InternalMessageInfo +<<<<<<< HEAD +======= +// LeverageEntry represents a single clob pair leverage setting. +type LeverageEntry struct { + // The clob pair ID. + ClobPairId uint32 `protobuf:"varint,1,opt,name=clob_pair_id,json=clobPairId,proto3" json:"clob_pair_id,omitempty"` + // The user selected imf. + CustomImfPpm uint32 `protobuf:"varint,2,opt,name=custom_imf_ppm,json=customImfPpm,proto3" json:"custom_imf_ppm,omitempty"` +} + +func (m *LeverageEntry) Reset() { *m = LeverageEntry{} } +func (m *LeverageEntry) String() string { return proto.CompactTextString(m) } +func (*LeverageEntry) ProtoMessage() {} +func (*LeverageEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_19b9e2c0de4ab64a, []int{20} +} +func (m *LeverageEntry) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LeverageEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LeverageEntry.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 *LeverageEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_LeverageEntry.Merge(m, src) +} +func (m *LeverageEntry) XXX_Size() int { + return m.Size() +} +func (m *LeverageEntry) XXX_DiscardUnknown() { + xxx_messageInfo_LeverageEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_LeverageEntry proto.InternalMessageInfo + +func (m *LeverageEntry) GetClobPairId() uint32 { + if m != nil { + return m.ClobPairId + } + return 0 +} + +func (m *LeverageEntry) GetCustomImfPpm() uint32 { + if m != nil { + return m.CustomImfPpm + } + return 0 +} + +// MsgUpdateLeverage is a request type used for updating leverage for +// clob pairs. +type MsgUpdateLeverage struct { + // The subaccount that is updating leverage. + SubaccountId *types.SubaccountId `protobuf:"bytes,1,opt,name=subaccount_id,json=subaccountId,proto3" json:"subaccount_id,omitempty"` + // List of clob pair leverage settings. + ClobPairLeverage []*LeverageEntry `protobuf:"bytes,2,rep,name=clob_pair_leverage,json=clobPairLeverage,proto3" json:"clob_pair_leverage,omitempty"` +} + +func (m *MsgUpdateLeverage) Reset() { *m = MsgUpdateLeverage{} } +func (m *MsgUpdateLeverage) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateLeverage) ProtoMessage() {} +func (*MsgUpdateLeverage) Descriptor() ([]byte, []int) { + return fileDescriptor_19b9e2c0de4ab64a, []int{21} +} +func (m *MsgUpdateLeverage) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateLeverage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateLeverage.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 *MsgUpdateLeverage) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateLeverage.Merge(m, src) +} +func (m *MsgUpdateLeverage) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateLeverage) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateLeverage.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateLeverage proto.InternalMessageInfo + +func (m *MsgUpdateLeverage) GetSubaccountId() *types.SubaccountId { + if m != nil { + return m.SubaccountId + } + return nil +} + +func (m *MsgUpdateLeverage) GetClobPairLeverage() []*LeverageEntry { + if m != nil { + return m.ClobPairLeverage + } + return nil +} + +// MsgUpdateLeverageResponse is a response type used for updating leverage. +type MsgUpdateLeverageResponse struct { +} + +func (m *MsgUpdateLeverageResponse) Reset() { *m = MsgUpdateLeverageResponse{} } +func (m *MsgUpdateLeverageResponse) String() string { return proto.CompactTextString(m) } +func (*MsgUpdateLeverageResponse) ProtoMessage() {} +func (*MsgUpdateLeverageResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_19b9e2c0de4ab64a, []int{22} +} +func (m *MsgUpdateLeverageResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgUpdateLeverageResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgUpdateLeverageResponse.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 *MsgUpdateLeverageResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgUpdateLeverageResponse.Merge(m, src) +} +func (m *MsgUpdateLeverageResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgUpdateLeverageResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgUpdateLeverageResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgUpdateLeverageResponse proto.InternalMessageInfo + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) func init() { proto.RegisterType((*MsgCreateClobPair)(nil), "dydxprotocol.clob.MsgCreateClobPair") proto.RegisterType((*MsgCreateClobPairResponse)(nil), "dydxprotocol.clob.MsgCreateClobPairResponse") @@ -1117,6 +1268,7 @@ func init() { func init() { proto.RegisterFile("dydxprotocol/clob/tx.proto", fileDescriptor_19b9e2c0de4ab64a) } var fileDescriptor_19b9e2c0de4ab64a = []byte{ +<<<<<<< HEAD // 1149 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x57, 0x4d, 0x4f, 0x24, 0x45, 0x18, 0x9e, 0x5e, 0xd4, 0x85, 0x17, 0x86, 0x85, 0x5a, 0x56, 0x66, 0x1b, 0x19, 0x86, 0x11, 0xc8, @@ -1190,6 +1342,88 @@ var fileDescriptor_19b9e2c0de4ab64a = []byte{ 0xc1, 0x51, 0xaf, 0x55, 0xb7, 0xa9, 0x97, 0xfc, 0x45, 0x7a, 0x72, 0x7f, 0xd5, 0x3e, 0xb2, 0x48, 0xa7, 0x21, 0x67, 0x4e, 0xa3, 0x9f, 0xc7, 0x67, 0x5d, 0xcc, 0x5a, 0xaf, 0xf1, 0xe9, 0x77, 0xff, 0x09, 0x00, 0x00, 0xff, 0xff, 0xf5, 0x64, 0x28, 0x2e, 0x40, 0x0f, 0x00, 0x00, +======= + // 1250 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x58, 0xcd, 0x6f, 0x1b, 0x45, + 0x14, 0xf7, 0xb6, 0x40, 0xeb, 0x17, 0x3b, 0x4d, 0xa7, 0x29, 0x71, 0xb7, 0xc4, 0x71, 0x4c, 0x12, + 0xb9, 0xd0, 0xd8, 0x25, 0x54, 0x01, 0x15, 0xf1, 0xe5, 0x28, 0x55, 0x22, 0x12, 0xe2, 0x6c, 0x82, + 0x40, 0x80, 0xb4, 0x5a, 0xef, 0x4e, 0x9c, 0x51, 0x77, 0x3d, 0x9b, 0xdd, 0x75, 0x48, 0xae, 0x95, + 0xb8, 0x73, 0x47, 0x48, 0xfc, 0x09, 0x1c, 0x7a, 0xe0, 0x0e, 0x87, 0x1e, 0x2b, 0x4e, 0x95, 0x40, + 0x80, 0x92, 0x03, 0xff, 0x06, 0xda, 0x9d, 0xdd, 0xf1, 0x6c, 0xf6, 0x23, 0x26, 0x70, 0xe0, 0x92, + 0xec, 0xcc, 0xfc, 0xde, 0xd7, 0xef, 0xbd, 0x79, 0x6f, 0x64, 0x90, 0x8d, 0x63, 0xe3, 0xc8, 0x76, + 0xa8, 0x47, 0x75, 0x6a, 0xb6, 0x74, 0x93, 0x76, 0x5b, 0xde, 0x51, 0x33, 0xd8, 0x40, 0xd7, 0xc5, + 0xb3, 0xa6, 0x7f, 0x26, 0xdf, 0xd2, 0xa9, 0x6b, 0x51, 0x57, 0x0d, 0x76, 0x5b, 0x6c, 0xc1, 0xd0, + 0xf2, 0x14, 0x5b, 0xb5, 0x2c, 0xb7, 0xd7, 0x3a, 0x7c, 0xc3, 0xff, 0x17, 0x1e, 0x4c, 0xf6, 0x68, + 0x8f, 0x32, 0x01, 0xff, 0x2b, 0xdc, 0x6d, 0x25, 0x0d, 0x77, 0x4d, 0xaa, 0x3f, 0x52, 0x1d, 0xcd, + 0xc3, 0xaa, 0x49, 0x2c, 0xe2, 0xa9, 0x3a, 0xed, 0xef, 0x91, 0x48, 0xcd, 0x6c, 0x52, 0xc0, 0xff, + 0xa3, 0xda, 0x1a, 0x71, 0x42, 0xc8, 0xbd, 0x24, 0x04, 0x1f, 0x0c, 0x88, 0x77, 0xac, 0x7a, 0x04, + 0x3b, 0x69, 0x4a, 0x67, 0x92, 0x12, 0x96, 0xe6, 0xe9, 0xfb, 0x38, 0x8a, 0x6a, 0x3a, 0x09, 0xa0, + 0x8e, 0x81, 0x23, 0x8b, 0x0b, 0x19, 0xc7, 0xaa, 0x83, 0x2d, 0x7a, 0xa8, 0x99, 0x91, 0x9a, 0xd7, + 0x93, 0x38, 0x93, 0x1c, 0x0c, 0x88, 0xa1, 0x79, 0x84, 0xf6, 0xdd, 0xb8, 0x53, 0x77, 0x62, 0x60, + 0x77, 0xd0, 0xd5, 0x74, 0x9d, 0x0e, 0xfa, 0x9e, 0x2b, 0x7c, 0x33, 0x68, 0xfd, 0x5b, 0x09, 0xae, + 0x6f, 0xba, 0xbd, 0x15, 0x07, 0x6b, 0x1e, 0x5e, 0x31, 0x69, 0xb7, 0xa3, 0x11, 0x07, 0x2d, 0x43, + 0x51, 0x1b, 0x78, 0xfb, 0xd4, 0x21, 0xde, 0x71, 0x45, 0xaa, 0x49, 0x8d, 0x62, 0xbb, 0xf2, 0xcb, + 0x93, 0xc5, 0xc9, 0x30, 0x5f, 0x1f, 0x1a, 0x86, 0x83, 0x5d, 0x77, 0xc7, 0x73, 0x48, 0xbf, 0xa7, + 0x0c, 0xa1, 0xe8, 0x3d, 0x28, 0x72, 0x4a, 0x2b, 0x97, 0x6a, 0x52, 0x63, 0x6c, 0xe9, 0x76, 0x33, + 0x51, 0x04, 0xcd, 0xc8, 0x4e, 0xfb, 0x85, 0xa7, 0xbf, 0xcf, 0x14, 0x94, 0xab, 0x7a, 0xb8, 0x7e, + 0x30, 0xfe, 0xf8, 0xaf, 0x1f, 0x5e, 0x1b, 0xea, 0xab, 0xdf, 0x86, 0x5b, 0x09, 0xe7, 0x14, 0xec, + 0xda, 0xb4, 0xef, 0xe2, 0x3a, 0x81, 0x9b, 0x9b, 0x6e, 0xaf, 0xe3, 0x50, 0x9b, 0xba, 0xd8, 0xd8, + 0xb2, 0xb1, 0xc3, 0xb8, 0x40, 0x1d, 0x98, 0xa0, 0x7c, 0xa5, 0x1e, 0x0c, 0xf0, 0x00, 0x57, 0xa4, + 0xda, 0xe5, 0xc6, 0xd8, 0xd2, 0x4c, 0x8a, 0x33, 0x5c, 0x50, 0xd1, 0xbe, 0x0a, 0x1d, 0xba, 0x36, + 0x14, 0xdf, 0xf6, 0xa5, 0xeb, 0x33, 0x30, 0x9d, 0x6a, 0x8a, 0xfb, 0xb2, 0x0a, 0x65, 0x1f, 0x60, + 0x6a, 0x3a, 0xde, 0xf2, 0xd3, 0x87, 0xee, 0xc3, 0x8b, 0x41, 0x1e, 0x03, 0xf6, 0xc6, 0x96, 0x2a, + 0x69, 0x86, 0xfd, 0xf3, 0xd0, 0x22, 0x03, 0xd7, 0xa7, 0x58, 0x48, 0x5c, 0x0d, 0xd7, 0xff, 0xa3, + 0x04, 0xe3, 0x3e, 0x13, 0x5a, 0x5f, 0xc7, 0x26, 0xb3, 0xf0, 0x0e, 0x5c, 0x65, 0x95, 0x42, 0x8c, + 0xd0, 0x88, 0x9c, 0x65, 0x64, 0xdd, 0x08, 0xcd, 0x5c, 0xa1, 0x6c, 0x89, 0x16, 0x60, 0xbc, 0x47, + 0xa9, 0xa1, 0x7a, 0xc4, 0x54, 0x83, 0x5b, 0x13, 0x64, 0xab, 0xbc, 0x56, 0x50, 0x4a, 0xfe, 0xfe, + 0x2e, 0x31, 0xdb, 0xfe, 0x2e, 0x6a, 0xc1, 0x8d, 0x38, 0x4e, 0xf5, 0x88, 0x85, 0x2b, 0x97, 0x6b, + 0x52, 0xe3, 0xca, 0x5a, 0x41, 0x99, 0x10, 0xc1, 0xbb, 0xc4, 0xc2, 0xed, 0x09, 0x41, 0x31, 0xed, + 0x63, 0xba, 0x57, 0xaf, 0xc0, 0xcb, 0x71, 0xcf, 0x79, 0x50, 0xbf, 0xb1, 0xa0, 0xda, 0xfe, 0x7d, + 0x61, 0xe7, 0x68, 0x1b, 0xca, 0xc3, 0x12, 0x1d, 0x46, 0xb6, 0x10, 0x8f, 0x4c, 0xa8, 0xe8, 0xe6, + 0x0e, 0xff, 0xe6, 0x51, 0x96, 0x5c, 0x61, 0x0f, 0x6d, 0x03, 0x72, 0xf7, 0xa9, 0xe3, 0xa9, 0x1e, + 0x76, 0x2c, 0x55, 0x0f, 0xec, 0xb8, 0x95, 0x4b, 0x41, 0x3d, 0x4c, 0x67, 0xa6, 0xc5, 0xf7, 0x29, + 0x54, 0x37, 0x11, 0x88, 0xef, 0x62, 0xc7, 0x62, 0x4e, 0xba, 0x68, 0x2e, 0xc1, 0x9e, 0x4f, 0x48, + 0x39, 0xce, 0x5d, 0x7d, 0x13, 0x60, 0xa8, 0x0b, 0xd5, 0xa0, 0xc4, 0xaf, 0x46, 0x14, 0x58, 0x59, + 0x81, 0xa8, 0xf4, 0xd7, 0x0d, 0x34, 0x0d, 0xa0, 0x9b, 0x04, 0x07, 0x71, 0x33, 0x07, 0xcb, 0x4a, + 0x91, 0xed, 0xac, 0x1b, 0x6e, 0xfd, 0x89, 0x14, 0x10, 0x29, 0xb0, 0x15, 0x11, 0x89, 0xb6, 0x60, + 0x52, 0x08, 0xd1, 0x1d, 0xe8, 0x3a, 0xc6, 0x06, 0x36, 0xc2, 0xa2, 0xcf, 0x0f, 0x52, 0x41, 0x3c, + 0xbc, 0x9d, 0x48, 0x10, 0xad, 0xc3, 0x75, 0x41, 0xe1, 0x9e, 0x46, 0x4c, 0x6c, 0x8c, 0x44, 0x99, + 0x72, 0x8d, 0x6b, 0x7b, 0x18, 0x48, 0x45, 0x0d, 0xe6, 0x13, 0xdb, 0xf8, 0xff, 0x36, 0x98, 0xb8, + 0x73, 0xbc, 0x3e, 0x9f, 0x4b, 0x50, 0x12, 0xbb, 0x83, 0x7f, 0xa9, 0x83, 0xe6, 0x1e, 0x56, 0xe5, + 0x2b, 0x19, 0x96, 0x37, 0x7d, 0xcc, 0x5a, 0x41, 0x61, 0x60, 0xf4, 0x2e, 0xc8, 0x02, 0x99, 0xec, + 0xce, 0xda, 0xfe, 0x15, 0xb7, 0x70, 0xdf, 0x0b, 0x82, 0x28, 0xad, 0x15, 0x94, 0x29, 0x4e, 0x5c, + 0xc0, 0x66, 0x27, 0x02, 0xa0, 0x87, 0x50, 0x8e, 0x4d, 0x84, 0xa0, 0xd6, 0x32, 0x5a, 0x19, 0xbb, + 0x5e, 0x01, 0xcc, 0xbf, 0xca, 0x54, 0x58, 0xb7, 0xc7, 0xa0, 0xc8, 0xdb, 0x5a, 0xfd, 0x0f, 0x09, + 0xe6, 0x79, 0xe0, 0xab, 0xc1, 0x88, 0xdb, 0x25, 0xd8, 0xd9, 0xf0, 0x07, 0xdc, 0x4a, 0x30, 0x4a, + 0x06, 0x0c, 0x79, 0xe1, 0x4c, 0xf5, 0xa1, 0x92, 0x35, 0x3a, 0xc3, 0xc4, 0xb5, 0x52, 0x22, 0xc8, + 0x73, 0x25, 0x4c, 0xe6, 0x4d, 0x9c, 0x86, 0x49, 0x64, 0xb6, 0x05, 0x8b, 0x23, 0x05, 0xc8, 0xb3, + 0xfd, 0xab, 0x04, 0x73, 0x5c, 0x22, 0xb8, 0xc1, 0x8a, 0xe6, 0xe1, 0xff, 0x90, 0x91, 0x47, 0x30, + 0x95, 0xf1, 0x40, 0x09, 0x53, 0xda, 0x4c, 0x21, 0x24, 0xc7, 0x91, 0x90, 0x8f, 0xc9, 0x6e, 0x0a, + 0x24, 0x41, 0x47, 0x13, 0xee, 0x8e, 0x12, 0x1c, 0x67, 0xe3, 0x27, 0x09, 0x6e, 0x73, 0x81, 0x0d, + 0xe1, 0xa5, 0xc1, 0xe0, 0x17, 0x26, 0xe1, 0x4b, 0xb8, 0x91, 0xf2, 0x6e, 0x09, 0x2b, 0x62, 0x3e, + 0x85, 0x80, 0xa4, 0xed, 0x30, 0x6e, 0x64, 0x26, 0x4e, 0x12, 0x51, 0xcf, 0xc3, 0xab, 0x39, 0x41, + 0xf0, 0x60, 0x3f, 0x85, 0xf2, 0x06, 0x3e, 0xc4, 0x8e, 0xd6, 0xc3, 0xab, 0x7d, 0xcf, 0x39, 0x1e, + 0xa1, 0x59, 0xcf, 0xc1, 0xb8, 0x3e, 0x70, 0x3d, 0x6a, 0xa9, 0xc4, 0xda, 0x53, 0x6d, 0xdb, 0x62, + 0x03, 0x54, 0x29, 0xb1, 0xdd, 0x75, 0x6b, 0xaf, 0x63, 0x5b, 0xf5, 0x9f, 0xc5, 0xe6, 0x17, 0x99, + 0x40, 0x1f, 0xfd, 0xab, 0x21, 0x77, 0x66, 0xbc, 0x7d, 0x0c, 0x68, 0xe8, 0xaa, 0x19, 0x9a, 0x08, + 0x7b, 0x75, 0x2d, 0x8d, 0x4f, 0x31, 0x50, 0x65, 0x22, 0x0a, 0x29, 0xda, 0x7e, 0x80, 0x7c, 0x0a, + 0xe3, 0xfe, 0xc5, 0xba, 0x64, 0x04, 0x8c, 0xc8, 0x5b, 0xfa, 0xba, 0x08, 0x97, 0x37, 0xdd, 0x1e, + 0xb2, 0x01, 0xa5, 0xbc, 0xc5, 0x1a, 0x29, 0x2e, 0xa4, 0x3e, 0xa5, 0xe4, 0x7b, 0xa3, 0x22, 0xf9, + 0xd8, 0xfb, 0x0c, 0x40, 0x78, 0x71, 0xd5, 0x32, 0xe4, 0x39, 0x42, 0x6e, 0x9c, 0x87, 0xe0, 0x9a, + 0xbf, 0x80, 0x31, 0xf1, 0xa9, 0x35, 0x9b, 0x2e, 0x28, 0x40, 0xe4, 0x3b, 0xe7, 0x42, 0x44, 0xe5, + 0xe2, 0x93, 0x27, 0x43, 0xb9, 0x00, 0xc9, 0x52, 0x9e, 0xf6, 0x14, 0x30, 0x60, 0xfc, 0xcc, 0x5b, + 0x7e, 0x2e, 0xc3, 0xb3, 0x18, 0x4a, 0xbe, 0x3b, 0x0a, 0x4a, 0xb4, 0x72, 0x66, 0xa0, 0x67, 0x58, + 0x89, 0xa3, 0xb2, 0xac, 0xa4, 0xcf, 0x5f, 0xf4, 0xbd, 0x04, 0xf5, 0x11, 0x26, 0xd4, 0xdb, 0x79, + 0x4a, 0xf3, 0x24, 0xe5, 0x0f, 0x2e, 0x2a, 0xc9, 0x5d, 0xfc, 0x4e, 0x82, 0xd9, 0xf3, 0x27, 0xc6, + 0x5b, 0x79, 0x76, 0x72, 0x04, 0xe5, 0xf7, 0x2f, 0x28, 0xc8, 0xfd, 0x7b, 0x2c, 0x41, 0x25, 0xb3, + 0x87, 0x37, 0xf3, 0xb4, 0x27, 0xf1, 0xf2, 0xf2, 0x3f, 0xc3, 0x27, 0xab, 0x85, 0x77, 0xc0, 0xdc, + 0x6a, 0x89, 0x50, 0xf9, 0xd5, 0x72, 0xb6, 0x0f, 0xb5, 0x3b, 0x4f, 0x4f, 0xaa, 0xd2, 0xb3, 0x93, + 0xaa, 0xf4, 0xe7, 0x49, 0x55, 0xfa, 0xe6, 0xb4, 0x5a, 0x78, 0x76, 0x5a, 0x2d, 0x3c, 0x3f, 0xad, + 0x16, 0x3e, 0x5f, 0xee, 0x11, 0x6f, 0x7f, 0xd0, 0x6d, 0xea, 0xd4, 0x8a, 0xff, 0x68, 0x70, 0x78, + 0x7f, 0x51, 0xdf, 0xd7, 0x48, 0xbf, 0xc5, 0x77, 0x8e, 0xc2, 0x5f, 0x30, 0x8e, 0x6d, 0xec, 0x76, + 0x5f, 0x0a, 0xb6, 0xdf, 0xfc, 0x3b, 0x00, 0x00, 0xff, 0xff, 0xcd, 0x24, 0x47, 0xbc, 0xe3, 0x10, + 0x00, 0x00, +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) } // Reference imports to suppress errors if they are not otherwise used. @@ -2350,6 +2584,114 @@ func (m *MsgUpdateLiquidationsConfigResponse) MarshalToSizedBuffer(dAtA []byte) return len(dAtA) - i, nil } +<<<<<<< HEAD +======= +func (m *LeverageEntry) 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 *LeverageEntry) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LeverageEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CustomImfPpm != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.CustomImfPpm)) + i-- + dAtA[i] = 0x10 + } + if m.ClobPairId != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.ClobPairId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateLeverage) 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 *MsgUpdateLeverage) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateLeverage) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ClobPairLeverage) > 0 { + for iNdEx := len(m.ClobPairLeverage) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ClobPairLeverage[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if m.SubaccountId != nil { + { + size, err := m.SubaccountId.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgUpdateLeverageResponse) 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 *MsgUpdateLeverageResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgUpdateLeverageResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + return len(dAtA) - i, nil +} + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) func encodeVarintTx(dAtA []byte, offset int, v uint64) int { offset -= sovTx(v) base := offset @@ -2674,6 +3016,52 @@ func (m *MsgUpdateLiquidationsConfigResponse) Size() (n int) { return n } +<<<<<<< HEAD +======= +func (m *LeverageEntry) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.ClobPairId != 0 { + n += 1 + sovTx(uint64(m.ClobPairId)) + } + if m.CustomImfPpm != 0 { + n += 1 + sovTx(uint64(m.CustomImfPpm)) + } + return n +} + +func (m *MsgUpdateLeverage) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.SubaccountId != nil { + l = m.SubaccountId.Size() + n += 1 + l + sovTx(uint64(l)) + } + if len(m.ClobPairLeverage) > 0 { + for _, e := range m.ClobPairLeverage { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } + return n +} + +func (m *MsgUpdateLeverageResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + return n +} + +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) func sovTx(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -4488,6 +4876,267 @@ func (m *MsgUpdateLiquidationsConfigResponse) Unmarshal(dAtA []byte) error { } return nil } +<<<<<<< HEAD +======= +func (m *LeverageEntry) 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 ErrIntOverflowTx + } + 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: LeverageEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LeverageEntry: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field ClobPairId", wireType) + } + m.ClobPairId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.ClobPairId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CustomImfPpm", wireType) + } + m.CustomImfPpm = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CustomImfPpm |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateLeverage) 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 ErrIntOverflowTx + } + 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: MsgUpdateLeverage: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateLeverage: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SubaccountId", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.SubaccountId == nil { + m.SubaccountId = &types.SubaccountId{} + } + if err := m.SubaccountId.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClobPairLeverage", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClobPairLeverage = append(m.ClobPairLeverage, &LeverageEntry{}) + if err := m.ClobPairLeverage[len(m.ClobPairLeverage)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgUpdateLeverageResponse) 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 ErrIntOverflowTx + } + 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: MsgUpdateLeverageResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgUpdateLeverageResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +>>>>>>> d5af215c (Check Leverage On Order Placement (#3141)) func skipTx(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/protocol/x/perpetuals/lib/lib.go b/protocol/x/perpetuals/lib/lib.go index 81b638c1f2..19d3200153 100644 --- a/protocol/x/perpetuals/lib/lib.go +++ b/protocol/x/perpetuals/lib/lib.go @@ -43,6 +43,7 @@ func GetPositionNetNotionalValueAndMarginRequirements( marketPrice pricestypes.MarketPrice, liquidityTier types.LiquidityTier, quantums *big.Int, + custom_imf_ppm uint32, ) ( risk margin.Risk, ) { @@ -56,6 +57,7 @@ func GetPositionNetNotionalValueAndMarginRequirements( marketPrice, liquidityTier, quantums, + custom_imf_ppm, ) return margin.Risk{ NC: nc, @@ -72,6 +74,7 @@ func GetNetCollateralAndMarginRequirements( liquidityTier types.LiquidityTier, quantums *big.Int, quoteBalance *big.Int, + custom_imf_ppm uint32, // 0 means use default liquidity tier margins ) ( risk margin.Risk, ) { @@ -80,6 +83,7 @@ func GetNetCollateralAndMarginRequirements( marketPrice, liquidityTier, quantums, + custom_imf_ppm, ) risk.NC.Add(risk.NC, quoteBalance) return risk @@ -109,11 +113,13 @@ func GetNetNotionalInQuoteQuantums( // GetMarginRequirementsInQuoteQuantums returns initial and maintenance margin requirements // in quote quantums, given the position size in base quantums. +// If leverage > 0, scales the margin requirements based on maxLeverage/userLeverage ratio. func GetMarginRequirementsInQuoteQuantums( perpetual types.Perpetual, marketPrice pricestypes.MarketPrice, liquidityTier types.LiquidityTier, bigQuantums *big.Int, + custom_imf_ppm uint32, // 0 means use default liquidity tier margins ) ( bigInitialMarginQuoteQuantums *big.Int, bigMaintenanceMarginQuoteQuantums *big.Int, @@ -140,6 +146,7 @@ func GetMarginRequirementsInQuoteQuantums( bigBaseInitialMarginQuoteQuantums := liquidityTier.GetInitialMarginQuoteQuantums( bigQuoteQuantums, big.NewInt(0), // pass in 0 as open interest to get base IMR. + big.NewInt(0), // pass in 0 to use the base IMR ) // Maintenance margin requirement quote quantums = IM in quote quantums * maintenance fraction PPM. bigMaintenanceMarginQuoteQuantums = lib.BigMulPpm( @@ -151,6 +158,8 @@ func GetMarginRequirementsInQuoteQuantums( bigInitialMarginQuoteQuantums = liquidityTier.GetInitialMarginQuoteQuantums( bigQuoteQuantums, openInterestQuoteQuantums, // pass in current OI to get scaled IMR. + lib.BigU(custom_imf_ppm), ) + return bigInitialMarginQuoteQuantums, bigMaintenanceMarginQuoteQuantums } diff --git a/protocol/x/perpetuals/lib/lib_test.go b/protocol/x/perpetuals/lib/lib_test.go index 2da3190acd..5bc6a52f8b 100644 --- a/protocol/x/perpetuals/lib/lib_test.go +++ b/protocol/x/perpetuals/lib/lib_test.go @@ -209,6 +209,7 @@ func TestGetNetCollateralAndMarginRequirements(t *testing.T) { test.marketPrice, test.liquidityTier, test.quantums, + 0, ) risk := lib.GetNetCollateralAndMarginRequirements( test.perpetual, @@ -216,6 +217,7 @@ func TestGetNetCollateralAndMarginRequirements(t *testing.T) { test.liquidityTier, test.quantums, test.quoteBalance, + 0, ) require.Equal(t, 0, new(big.Int).Add(enc, test.quoteBalance).Cmp(risk.NC)) require.Equal(t, eimr, risk.IMR) @@ -314,6 +316,7 @@ func BenchmarkGetMarginRequirementsInQuoteQuantums(b *testing.B) { marketPrice, liquidityTier, quantums, + 0, ) } } @@ -399,6 +402,7 @@ func TestGetMarginRequirementsInQuoteQuantums(t *testing.T) { test.marketPrice, test.liquidityTier, test.quantums, + 0, ) require.Equal(t, test.expectedImr, imr) require.Equal(t, test.expectedMmr, mmr) @@ -681,6 +685,7 @@ func TestGetMarginRequirementsInQuoteQuantums_2(t *testing.T) { marketPrice, liquidityTier, tc.bigBaseQuantums, + 0, ) require.Equal(t, tc.bigExpectedInitialMargin, imr, "Initial margin mismatch") diff --git a/protocol/x/perpetuals/types/liquidity_tier.go b/protocol/x/perpetuals/types/liquidity_tier.go index 543cf494f2..0b0697b55a 100644 --- a/protocol/x/perpetuals/types/liquidity_tier.go +++ b/protocol/x/perpetuals/types/liquidity_tier.go @@ -77,13 +77,14 @@ func (liquidityTier LiquidityTier) GetMaxAbsFundingClampPpm(clampFactorPpm uint3 func (liquidityTier LiquidityTier) GetInitialMarginQuoteQuantums( quoteQuantums *big.Int, oiQuoteQuantums *big.Int, + custom_imf_ppm *big.Int, ) *big.Int { totalImfPpm := liquidityTier.GetAdjustedInitialMarginPpm(oiQuoteQuantums) - return lib.BigMulPpm( - quoteQuantums, - totalImfPpm, - true, // Round up initial margin. - ) + if custom_imf_ppm.Sign() > 0 { + // use the configured IMF if it is greater than the OI scaled IMF + totalImfPpm = lib.BigMax(totalImfPpm, custom_imf_ppm) + } + return lib.BigMulPpm(quoteQuantums, totalImfPpm, true) // Round up initial margin. } // GetAdjustedInitialMarginPpm returns the adjusted initial margin (in ppm) based on the current open interest. diff --git a/protocol/x/perpetuals/types/liquidity_tier_test.go b/protocol/x/perpetuals/types/liquidity_tier_test.go index ccc196b67f..28b73ede54 100644 --- a/protocol/x/perpetuals/types/liquidity_tier_test.go +++ b/protocol/x/perpetuals/types/liquidity_tier_test.go @@ -235,9 +235,9 @@ func BenchmarkGetInitialMarginQuoteQuantums(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - _ = liquidityTier.GetInitialMarginQuoteQuantums(bigQuoteQuantums, oiLower) - _ = liquidityTier.GetInitialMarginQuoteQuantums(bigQuoteQuantums, oiUpper) - _ = liquidityTier.GetInitialMarginQuoteQuantums(bigQuoteQuantums, oiMiddle) + _ = liquidityTier.GetInitialMarginQuoteQuantums(bigQuoteQuantums, oiLower, big.NewInt(0)) + _ = liquidityTier.GetInitialMarginQuoteQuantums(bigQuoteQuantums, oiUpper, big.NewInt(0)) + _ = liquidityTier.GetInitialMarginQuoteQuantums(bigQuoteQuantums, oiMiddle, big.NewInt(0)) } } @@ -357,7 +357,11 @@ func TestGetInitialMarginQuoteQuantums(t *testing.T) { if tc.openInterestNotional != nil { openInterestNotional.Set(tc.openInterestNotional) } - adjustedIMQuoteQuantums := liquidityTier.GetInitialMarginQuoteQuantums(tc.bigQuoteQuantums, openInterestNotional) + adjustedIMQuoteQuantums := liquidityTier.GetInitialMarginQuoteQuantums( + tc.bigQuoteQuantums, + openInterestNotional, + big.NewInt(0), // no leverage configured + ) require.Equal(t, tc.expectedInitialMarginQuoteQuantums, adjustedIMQuoteQuantums) }) diff --git a/protocol/x/subaccounts/keeper/leverage.go b/protocol/x/subaccounts/keeper/leverage.go new file mode 100644 index 0000000000..d0b172e7b6 --- /dev/null +++ b/protocol/x/subaccounts/keeper/leverage.go @@ -0,0 +1,128 @@ +package keeper + +import ( + errorsmod "cosmossdk.io/errors" + "cosmossdk.io/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/dydxprotocol/v4-chain/protocol/lib" + "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" +) + +// getLeverageStore returns a prefix store where leverage data is stored. +func (k Keeper) getLeverageStore(ctx sdk.Context) prefix.Store { + return prefix.NewStore(ctx.KVStore(k.storeKey), []byte(types.LeverageKeyPrefix)) +} + +// leverageKey returns the store key to retrieve leverage data for a subaccount. +func leverageKey(subaccountId *types.SubaccountId) []byte { + return subaccountId.ToStateKey() +} + +// SetLeverage stores leverage data for a subaccount. +func (k Keeper) SetLeverage(ctx sdk.Context, subaccountId *types.SubaccountId, leverageMap map[uint32]uint32) { + store := k.getLeverageStore(ctx) + key := leverageKey(subaccountId) + + var entries []*types.PerpetualLeverageEntry + sortedPerpIds := lib.GetSortedKeys[lib.Sortable[uint32]](leverageMap) + for _, perpetualId := range sortedPerpIds { + customImfPpm := leverageMap[perpetualId] + entries = append(entries, &types.PerpetualLeverageEntry{ + PerpetualId: perpetualId, + CustomImfPpm: customImfPpm, + }) + } + + leverageData := &types.LeverageData{ + Entries: entries, + } + + b := k.cdc.MustMarshal(leverageData) + store.Set(key, b) +} + +// GetLeverage retrieves leverage data for a subaccount. +func (k Keeper) GetLeverage(ctx sdk.Context, subaccountId *types.SubaccountId) (map[uint32]uint32, bool) { + store := k.getLeverageStore(ctx) + key := leverageKey(subaccountId) + + b := store.Get(key) + if b == nil { + return nil, false + } + + var leverageData types.LeverageData + k.cdc.MustUnmarshal(b, &leverageData) + + leverageMap := make(map[uint32]uint32) + for _, entry := range leverageData.Entries { + leverageMap[entry.PerpetualId] = entry.CustomImfPpm + } + + return leverageMap, true +} + +// UpdateLeverage updates leverage for specific perpetuals for a subaccount. +func (k Keeper) UpdateLeverage( + ctx sdk.Context, + subaccountId *types.SubaccountId, + perpetualLeverage map[uint32]uint32, +) error { + // Sort the perpetual IDs to ensure deterministic ordering + sortedPerpIds := lib.GetSortedKeys[lib.Sortable[uint32]](perpetualLeverage) + + // Validate leverage against maximum allowed leverage for each perpetual + for _, perpetualId := range sortedPerpIds { + custom_imf_ppm := perpetualLeverage[perpetualId] + minImfPpm, err := k.GetMinImfForPerpetual(ctx, perpetualId) + if err != nil { + return errorsmod.Wrapf( + types.ErrInvalidLeverage, + "failed to get max leverage for perpetual %d: %v", + perpetualId, + err, + ) + } + + if custom_imf_ppm < minImfPpm { + return errorsmod.Wrapf( + types.ErrLeverageExceedsMaximum, + "%d is less than minimum allowed imf (%d) for perpetual %d resulting in higher than allowed leverage", + custom_imf_ppm, + minImfPpm, + perpetualId, + ) + } + } + + // Get existing leverage data + existingLeverage, exists := k.GetLeverage(ctx, subaccountId) + if !exists { + existingLeverage = make(map[uint32]uint32) + } + + // Update with new leverage values + for perpetualId, custom_imf_ppm := range perpetualLeverage { + existingLeverage[perpetualId] = custom_imf_ppm + } + + // Store updated leverage + k.SetLeverage(ctx, subaccountId, existingLeverage) + return nil +} + +// GetMinImfForPerpetual returns the IMF ppm allowed for a perpetual +// based on its liquidity tier's initial margin requirement. +func (k Keeper) GetMinImfForPerpetual(ctx sdk.Context, perpetualId uint32) (uint32, error) { + // Get the perpetual and its liquidity tier in one call + _, _, liquidityTier, err := k.perpetualsKeeper.GetPerpetualAndMarketPriceAndLiquidityTier(ctx, perpetualId) + if err != nil { + return 0, err + } + + if liquidityTier.InitialMarginPpm == 0 { + return 0, types.ErrInitialMarginPpmIsZero + } + + return liquidityTier.InitialMarginPpm, nil +} diff --git a/protocol/x/subaccounts/keeper/margining.go b/protocol/x/subaccounts/keeper/margining.go index dacb3a1b59..517732f8dd 100644 --- a/protocol/x/subaccounts/keeper/margining.go +++ b/protocol/x/subaccounts/keeper/margining.go @@ -76,6 +76,7 @@ func getMarginedUpdate( perpInfo.LiquidityTier, pos.GetBigQuantums(), pos.GetQuoteBalance(), + 0, // Margining uses default leverage and MMR ) // case 2: the position is undercollateralized w.r.t. the maintenance margin requirement. @@ -171,6 +172,7 @@ func withdrawCollateralFromPerpetualPositions( perpInfo.LiquidityTier, pos.GetBigQuantums(), pos.GetQuoteBalance(), + 0, ) // Calculate the amount of extra collateral that can be withdrawn. diff --git a/protocol/x/subaccounts/keeper/subaccount.go b/protocol/x/subaccounts/keeper/subaccount.go index f195e2dbf3..397d33502d 100644 --- a/protocol/x/subaccounts/keeper/subaccount.go +++ b/protocol/x/subaccounts/keeper/subaccount.go @@ -251,6 +251,7 @@ func (k Keeper) getSettledUpdates( err error, ) { var idToSettledSubaccount = make(map[types.SubaccountId]types.Subaccount) + var idToLeverageMap = make(map[types.SubaccountId]map[uint32]uint32) settledUpdates = make([]types.SettledUpdate, len(updates)) subaccountIdToFundingPayments = make(map[types.SubaccountId]map[uint32]dtypes.SerializableInt) @@ -258,25 +259,41 @@ func (k Keeper) getSettledUpdates( for i, u := range updates { settledSubaccount, exists := idToSettledSubaccount[u.SubaccountId] var fundingPayments map[uint32]dtypes.SerializableInt + var leverageMap map[uint32]uint32 if exists && requireUniqueSubaccount { return nil, nil, types.ErrNonUniqueUpdatesSubaccount } - // Get and store the settledSubaccount if SubaccountId doesn't exist in - // idToSettledSubaccount map. + // Get and store the settledSubaccount and leverage if SubaccountId doesn't exist in maps. if !exists { subaccount := k.GetSubaccount(ctx, u.SubaccountId) settledSubaccount, fundingPayments = salib.GetSettledSubaccountWithPerpetuals(subaccount, perpInfos) + // Only fetch leverage if there are perpetual updates or perpetual positions + // to avoid unnecessary gas consumption + if len(u.PerpetualUpdates) > 0 || len(settledSubaccount.PerpetualPositions) > 0 { + if leverage, found := k.GetLeverage(ctx, &u.SubaccountId); found { + leverageMap = leverage + } + } + idToSettledSubaccount[u.SubaccountId] = settledSubaccount + idToLeverageMap[u.SubaccountId] = leverageMap subaccountIdToFundingPayments[u.SubaccountId] = fundingPayments + } else { + // Reuse cached leverage map if there are perpetual updates + // or perpetual positions + if len(u.PerpetualUpdates) > 0 || len(settledSubaccount.PerpetualPositions) > 0 { + leverageMap = idToLeverageMap[u.SubaccountId] + } } settledUpdate := types.SettledUpdate{ SettledSubaccount: settledSubaccount, AssetUpdates: u.AssetUpdates, PerpetualUpdates: u.PerpetualUpdates, + LeverageMap: leverageMap, } settledUpdates[i] = settledUpdate @@ -366,7 +383,7 @@ func (k Keeper) UpdateSubaccounts( return false, nil, err } - success, successPerUpdate, err = k.internalCanUpdateSubaccounts( + success, successPerUpdate, err = k.internalCanUpdateSubaccountsWithLeverage( ctx, settledUpdates, updateType, @@ -479,6 +496,9 @@ func (k Keeper) UpdateSubaccounts( // with the same `SubaccountId`, they are validated without respect to each // other. // +// This method automatically fetches leverage configuration for all subaccounts +// being updated and applies leverage-aware margin requirements. +// // Returns a `success` value of `true` if all updates are valid. // Returns a `successPerUpdates` value, which is a slice of `UpdateResult`. // These map to the updates and are used to indicate which of the updates @@ -511,23 +531,11 @@ func (k Keeper) CanUpdateSubaccounts( return false, nil, err } - success, successPerUpdate, err = k.internalCanUpdateSubaccounts(ctx, settledUpdates, updateType, perpInfos) + success, successPerUpdate, err = k.internalCanUpdateSubaccountsWithLeverage(ctx, settledUpdates, updateType, perpInfos) return success, successPerUpdate, err } -// internalCanUpdateSubaccounts will validate all `updates` to the relevant subaccounts and compute -// if any of the updates led to an isolated perpetual position being opened or closed. -// The `updates` do not have to contain `Subaccounts` with unique `SubaccountIds`. -// Each update is considered in isolation. Thus if two updates are provided -// with the same `Subaccount`, they are validated without respect to each -// other. -// The input subaccounts must be settled. -// -// Returns a `success` value of `true` if all updates are valid. -// Returns a `successPerUpdates` value, which is a slice of `UpdateResult`. -// These map to the updates and are used to indicate which of the updates -// caused a failure, if any. -func (k Keeper) internalCanUpdateSubaccounts( +func (k Keeper) internalCanUpdateSubaccountsWithLeverage( ctx sdk.Context, settledUpdates []types.SettledUpdate, updateType types.UpdateType, @@ -673,11 +681,7 @@ func (k Keeper) internalCanUpdateSubaccounts( } // Get the new collateralization and margin requirements with the update applied. - updatedSubaccount := salib.CalculateUpdatedSubaccount(u, perpInfos) - riskNew, err := salib.GetRiskForSubaccount( - updatedSubaccount, - perpInfos, - ) + riskNew, err := salib.GetRiskForSettledUpdate(u, perpInfos) if err != nil { return false, nil, err } @@ -699,6 +703,7 @@ func (k Keeper) internalCanUpdateSubaccounts( riskCurMap[saKey], err = salib.GetRiskForSubaccount( u.SettledSubaccount, perpInfos, + u.LeverageMap, ) if err != nil { return false, nil, err @@ -755,9 +760,16 @@ func (k Keeper) GetNetCollateralAndMarginRequirements( } updatedSubaccount := salib.CalculateUpdatedSubaccount(settledUpdate, perpInfos) + // Get leverage configuration for this subaccount + var leverageMap map[uint32]uint32 + if leverage, found := k.GetLeverage(ctx, &update.SubaccountId); found { + leverageMap = leverage + } + return salib.GetRiskForSubaccount( updatedSubaccount, perpInfos, + leverageMap, ) } diff --git a/protocol/x/subaccounts/lib/updates.go b/protocol/x/subaccounts/lib/updates.go index 672415cc27..3a30c2e0e4 100644 --- a/protocol/x/subaccounts/lib/updates.go +++ b/protocol/x/subaccounts/lib/updates.go @@ -343,6 +343,7 @@ func CalculateUpdatedSubaccount( func GetRiskForSubaccount( subaccount types.Subaccount, perpInfos perptypes.PerpInfos, + leverageMap map[uint32]uint32, // leverage per perpetual, nil means no leverage configured ) ( risk margin.Risk, err error, @@ -365,15 +366,37 @@ func GetRiskForSubaccount( // Iterate over all perpetuals and updates and calculate change to net collateral and margin requirements. for _, pos := range subaccount.PerpetualPositions { perpInfo := perpInfos.MustGet(pos.PerpetualId) + + // Get the configured imf for this perpetual (0 if not configured) + custom_imf_ppm := uint32(0) + if leverageMap != nil { + custom_imf_ppm = leverageMap[pos.PerpetualId] + } + r := perplib.GetNetCollateralAndMarginRequirements( perpInfo.Perpetual, perpInfo.Price, perpInfo.LiquidityTier, pos.GetBigQuantums(), pos.GetQuoteBalance(), + custom_imf_ppm, ) risk.AddInPlace(r) } return risk, nil } + +// GetRiskForSettledUpdate returns the risk value for a SettledUpdate with embedded leverage. +// This is a convenience function that extracts the leverage from the SettledUpdate and +// calls GetRiskForSubaccount with the updated subaccount. +func GetRiskForSettledUpdate( + settledUpdate types.SettledUpdate, + perpInfos perptypes.PerpInfos, +) ( + risk margin.Risk, + err error, +) { + updatedSubaccount := CalculateUpdatedSubaccount(settledUpdate, perpInfos) + return GetRiskForSubaccount(updatedSubaccount, perpInfos, settledUpdate.LeverageMap) +} diff --git a/protocol/x/subaccounts/lib/updates_test.go b/protocol/x/subaccounts/lib/updates_test.go index 4e75261c4b..250815a4b5 100644 --- a/protocol/x/subaccounts/lib/updates_test.go +++ b/protocol/x/subaccounts/lib/updates_test.go @@ -160,7 +160,7 @@ func TestGetRiskForSubaccount(t *testing.T) { } for name, tc := range tests { t.Run(name, func(t *testing.T) { - risk, err := lib.GetRiskForSubaccount(tc.subaccount, tc.perpInfos) + risk, err := lib.GetRiskForSubaccount(tc.subaccount, tc.perpInfos, nil) require.Equal(t, tc.expectedRisk, risk) if tc.expectedErr != nil { require.Equal(t, tc.expectedErr, err) @@ -183,6 +183,6 @@ func TestGetRiskForSubaccount_Panic(t *testing.T) { // Panics since relevant perpetual information cannot be found. require.Panics(t, func() { - _, _ = lib.GetRiskForSubaccount(subaccount, emptyPerpInfos) + _, _ = lib.GetRiskForSubaccount(subaccount, emptyPerpInfos, nil) }) } diff --git a/protocol/x/subaccounts/types/errors.go b/protocol/x/subaccounts/types/errors.go index 9650673ce0..5c0d938d20 100644 --- a/protocol/x/subaccounts/types/errors.go +++ b/protocol/x/subaccounts/types/errors.go @@ -78,4 +78,9 @@ var ( "subaccount not found at index in safety heap", ) ErrSafetyHeapSubaccountIndexNotFound = errorsmod.Register(ModuleName, 602, "subaccount index not found") + + // 700 - 799: leverage related. + ErrInvalidLeverage = errorsmod.Register(ModuleName, 700, "invalid leverage") + ErrLeverageExceedsMaximum = errorsmod.Register(ModuleName, 701, "leverage exceeds maximum allowed") + ErrInitialMarginPpmIsZero = errorsmod.Register(ModuleName, 702, "initial margin ppm cannot be zero") ) diff --git a/protocol/x/subaccounts/types/keys.go b/protocol/x/subaccounts/types/keys.go index f67d476082..921d1de5df 100644 --- a/protocol/x/subaccounts/types/keys.go +++ b/protocol/x/subaccounts/types/keys.go @@ -25,4 +25,7 @@ const ( SafetyHeapSubaccountIdsPrefix = "Heap/" SafetyHeapSubaccountToIndexPrefix = "Idx/" SafetyHeapLengthPrefix = "Len/" + + // Leverage + LeverageKeyPrefix = "Lev:" ) diff --git a/protocol/x/subaccounts/types/leverage.pb.go b/protocol/x/subaccounts/types/leverage.pb.go new file mode 100644 index 0000000000..a65dbe4dd5 --- /dev/null +++ b/protocol/x/subaccounts/types/leverage.pb.go @@ -0,0 +1,528 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: dydxprotocol/subaccounts/leverage.proto + +package types + +import ( + fmt "fmt" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// PerpetualLeverageEntry represents a single perpetual leverage setting for +// internal storage +type PerpetualLeverageEntry struct { + // The perpetual ID (internal storage format) + PerpetualId uint32 `protobuf:"varint,1,opt,name=perpetual_id,json=perpetualId,proto3" json:"perpetual_id,omitempty"` + // The user selected IMF in parts per million + CustomImfPpm uint32 `protobuf:"varint,2,opt,name=custom_imf_ppm,json=customImfPpm,proto3" json:"custom_imf_ppm,omitempty"` +} + +func (m *PerpetualLeverageEntry) Reset() { *m = PerpetualLeverageEntry{} } +func (m *PerpetualLeverageEntry) String() string { return proto.CompactTextString(m) } +func (*PerpetualLeverageEntry) ProtoMessage() {} +func (*PerpetualLeverageEntry) Descriptor() ([]byte, []int) { + return fileDescriptor_78a5174593f1c911, []int{0} +} +func (m *PerpetualLeverageEntry) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *PerpetualLeverageEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_PerpetualLeverageEntry.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 *PerpetualLeverageEntry) XXX_Merge(src proto.Message) { + xxx_messageInfo_PerpetualLeverageEntry.Merge(m, src) +} +func (m *PerpetualLeverageEntry) XXX_Size() int { + return m.Size() +} +func (m *PerpetualLeverageEntry) XXX_DiscardUnknown() { + xxx_messageInfo_PerpetualLeverageEntry.DiscardUnknown(m) +} + +var xxx_messageInfo_PerpetualLeverageEntry proto.InternalMessageInfo + +func (m *PerpetualLeverageEntry) GetPerpetualId() uint32 { + if m != nil { + return m.PerpetualId + } + return 0 +} + +func (m *PerpetualLeverageEntry) GetCustomImfPpm() uint32 { + if m != nil { + return m.CustomImfPpm + } + return 0 +} + +// LeverageData represents the leverage settings for a subaccount +type LeverageData struct { + // List of leverage entries for this subaccount + Entries []*PerpetualLeverageEntry `protobuf:"bytes,1,rep,name=entries,proto3" json:"entries,omitempty"` +} + +func (m *LeverageData) Reset() { *m = LeverageData{} } +func (m *LeverageData) String() string { return proto.CompactTextString(m) } +func (*LeverageData) ProtoMessage() {} +func (*LeverageData) Descriptor() ([]byte, []int) { + return fileDescriptor_78a5174593f1c911, []int{1} +} +func (m *LeverageData) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *LeverageData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_LeverageData.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 *LeverageData) XXX_Merge(src proto.Message) { + xxx_messageInfo_LeverageData.Merge(m, src) +} +func (m *LeverageData) XXX_Size() int { + return m.Size() +} +func (m *LeverageData) XXX_DiscardUnknown() { + xxx_messageInfo_LeverageData.DiscardUnknown(m) +} + +var xxx_messageInfo_LeverageData proto.InternalMessageInfo + +func (m *LeverageData) GetEntries() []*PerpetualLeverageEntry { + if m != nil { + return m.Entries + } + return nil +} + +func init() { + proto.RegisterType((*PerpetualLeverageEntry)(nil), "dydxprotocol.subaccounts.PerpetualLeverageEntry") + proto.RegisterType((*LeverageData)(nil), "dydxprotocol.subaccounts.LeverageData") +} + +func init() { + proto.RegisterFile("dydxprotocol/subaccounts/leverage.proto", fileDescriptor_78a5174593f1c911) +} + +var fileDescriptor_78a5174593f1c911 = []byte{ + // 249 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4f, 0xa9, 0x4c, 0xa9, + 0x28, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0xce, 0xcf, 0xd1, 0x2f, 0x2e, 0x4d, 0x4a, 0x4c, 0x4e, 0xce, + 0x2f, 0xcd, 0x2b, 0x29, 0xd6, 0xcf, 0x49, 0x2d, 0x4b, 0x2d, 0x4a, 0x4c, 0x4f, 0xd5, 0x03, 0xcb, + 0x0a, 0x49, 0x20, 0x2b, 0xd4, 0x43, 0x52, 0xa8, 0x94, 0xc8, 0x25, 0x16, 0x90, 0x5a, 0x54, 0x90, + 0x5a, 0x52, 0x9a, 0x98, 0xe3, 0x03, 0xd5, 0xe4, 0x9a, 0x57, 0x52, 0x54, 0x29, 0xa4, 0xc8, 0xc5, + 0x53, 0x00, 0x93, 0x89, 0xcf, 0x4c, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x0d, 0xe2, 0x86, 0x8b, + 0x79, 0xa6, 0x08, 0xa9, 0x70, 0xf1, 0x25, 0x97, 0x16, 0x97, 0xe4, 0xe7, 0xc6, 0x67, 0xe6, 0xa6, + 0xc5, 0x17, 0x14, 0xe4, 0x4a, 0x30, 0x81, 0x15, 0xf1, 0x40, 0x44, 0x3d, 0x73, 0xd3, 0x02, 0x0a, + 0x72, 0x95, 0xa2, 0xb8, 0x78, 0x60, 0x26, 0xbb, 0x24, 0x96, 0x24, 0x0a, 0x79, 0x71, 0xb1, 0xa7, + 0xe6, 0x95, 0x14, 0x65, 0xa6, 0x16, 0x4b, 0x30, 0x2a, 0x30, 0x6b, 0x70, 0x1b, 0x19, 0xe8, 0xe1, + 0x72, 0x9e, 0x1e, 0x76, 0xb7, 0x05, 0xc1, 0x0c, 0x70, 0x0a, 0x3f, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, + 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, + 0xc6, 0x63, 0x39, 0x86, 0x28, 0xdb, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, + 0x7d, 0x94, 0x60, 0x2a, 0x33, 0xd1, 0x4d, 0xce, 0x48, 0xcc, 0xcc, 0xd3, 0x87, 0x8b, 0x54, 0xa0, + 0x04, 0x5d, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0x58, 0xd6, 0x18, 0x10, 0x00, 0x00, 0xff, + 0xff, 0x83, 0xd3, 0xb1, 0xbe, 0x63, 0x01, 0x00, 0x00, +} + +func (m *PerpetualLeverageEntry) 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 *PerpetualLeverageEntry) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *PerpetualLeverageEntry) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.CustomImfPpm != 0 { + i = encodeVarintLeverage(dAtA, i, uint64(m.CustomImfPpm)) + i-- + dAtA[i] = 0x10 + } + if m.PerpetualId != 0 { + i = encodeVarintLeverage(dAtA, i, uint64(m.PerpetualId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *LeverageData) 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 *LeverageData) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *LeverageData) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Entries) > 0 { + for iNdEx := len(m.Entries) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Entries[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintLeverage(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintLeverage(dAtA []byte, offset int, v uint64) int { + offset -= sovLeverage(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *PerpetualLeverageEntry) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.PerpetualId != 0 { + n += 1 + sovLeverage(uint64(m.PerpetualId)) + } + if m.CustomImfPpm != 0 { + n += 1 + sovLeverage(uint64(m.CustomImfPpm)) + } + return n +} + +func (m *LeverageData) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Entries) > 0 { + for _, e := range m.Entries { + l = e.Size() + n += 1 + l + sovLeverage(uint64(l)) + } + } + return n +} + +func sovLeverage(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozLeverage(x uint64) (n int) { + return sovLeverage(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *PerpetualLeverageEntry) 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 ErrIntOverflowLeverage + } + 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: PerpetualLeverageEntry: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: PerpetualLeverageEntry: 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 ErrIntOverflowLeverage + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PerpetualId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field CustomImfPpm", wireType) + } + m.CustomImfPpm = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLeverage + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.CustomImfPpm |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipLeverage(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthLeverage + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *LeverageData) 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 ErrIntOverflowLeverage + } + 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: LeverageData: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: LeverageData: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Entries", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowLeverage + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthLeverage + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthLeverage + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Entries = append(m.Entries, &PerpetualLeverageEntry{}) + if err := m.Entries[len(m.Entries)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipLeverage(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthLeverage + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipLeverage(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowLeverage + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowLeverage + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowLeverage + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthLeverage + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupLeverage + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthLeverage + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthLeverage = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowLeverage = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupLeverage = fmt.Errorf("proto: unexpected end of group") +) diff --git a/protocol/x/subaccounts/types/settled_update.go b/protocol/x/subaccounts/types/settled_update.go index d41b5bffef..e60a185b4c 100644 --- a/protocol/x/subaccounts/types/settled_update.go +++ b/protocol/x/subaccounts/types/settled_update.go @@ -11,6 +11,9 @@ type SettledUpdate struct { AssetUpdates []AssetUpdate // A list of changes to make to any `PerpetualPositions` in the `Subaccount`. PerpetualUpdates []PerpetualUpdate + // Leverage configuration for this subaccount (perpetualId -> custom imf). + // nil means no leverage configured (use default margin requirements). + LeverageMap map[uint32]uint32 } func (u *SettledUpdate) GetAssetUpdates() map[uint32]AssetUpdate {