Updated to handle new event queue format.

This commit is contained in:
Geoff Taylor 2021-08-13 20:17:17 +01:00
parent 3403555036
commit 97bd857418
4 changed files with 160 additions and 19 deletions

View File

@ -48,6 +48,19 @@ class InstructionType(enum.IntEnum):
UpdateRootBank = 21 UpdateRootBank = 21
SettlePnl = 22 SettlePnl = 22
SettleBorrow = 23 SettleBorrow = 23
ForceCancelSpotOrders = 24
ForceCancelPerpOrders = 25
LiquidateTokenAndToken = 26
LiquidateTokenAndPerp = 27
LiquidatePerpMarket = 28
SettleFees = 29
ResolvePerpBankruptcy = 30
ResolveTokenBankruptcy = 31
InitSpotOpenOrders = 32
RedeemMngo = 33
AddMangoAccountInfo = 34
DepositMsrm = 35
WithdrawMsrm = 36
def __str__(self) -> str: def __str__(self) -> str:
return self.name return self.name

View File

@ -905,28 +905,33 @@ ORDERBOOK_SIDE = construct.Struct(
# #
# Here's the [Rust structure](https://github.com/blockworks-foundation/mango-v3/blob/main/program/src/queue.rs): # Here's the [Rust structure](https://github.com/blockworks-foundation/mango-v3/blob/main/program/src/queue.rs):
# ``` # ```
# const EVENT_SIZE: usize = 152; # const EVENT_SIZE: usize = 200;
# #[derive(Copy, Clone, Debug, Pod)] # [derive(Copy, Clone, Debug, Pod)]
# #[repr(C)] # [repr(C)]
# pub struct FillEvent { # pub struct FillEvent {
# pub event_type: u8, # pub event_type: u8,
# pub side: Side, // side from the taker's POV # pub taker_side: Side, // side from the taker's POV
# pub maker_slot: u8, # pub maker_slot: u8,
# pub maker_out: bool, // true if maker order quantity == 0 # pub maker_out: bool, // true if maker order quantity == 0
# pub padding: [u8; 4], # pub padding: [u8; 4],
# pub timestamp: u64,
# pub seq_num: usize, // note: usize same as u64
#
# pub maker: Pubkey, # pub maker: Pubkey,
# pub maker_order_id: i128, # pub maker_order_id: i128,
# pub maker_client_order_id: u64, # pub maker_client_order_id: u64,
# pub maker_fee: I80F48,
# #
# // The best bid/ask at the time the maker order was placed. Used for liquidity incentives # // The best bid/ask at the time the maker order was placed. Used for liquidity incentives
# pub best_initial: i64, # pub best_initial: i64,
# #
# // Timestamp of when the maker order was placed; copied over from the LeafNode # // Timestamp of when the maker order was placed; copied over from the LeafNode
# pub timestamp: u64, # pub maker_timestamp: u64,
# #
# pub taker: Pubkey, # pub taker: Pubkey,
# pub taker_order_id: i128, # pub taker_order_id: i128,
# pub taker_client_order_id: u64, # pub taker_client_order_id: u64,
# pub taker_fee: I80F48,
# #
# pub price: i64, # pub price: i64,
# pub quantity: i64, // number of quote lots # pub quantity: i64, // number of quote lots
@ -934,27 +939,31 @@ ORDERBOOK_SIDE = construct.Struct(
# ``` # ```
FILL_EVENT = construct.Struct( FILL_EVENT = construct.Struct(
"event_type" / construct.Const(b'\x00'), "event_type" / construct.Const(b'\x00'),
"side" / DecimalAdapter(1), "taker_side" / DecimalAdapter(1),
"maker_slot" / DecimalAdapter(1), "maker_slot" / DecimalAdapter(1),
"maker_out" / construct.Flag, "maker_out" / construct.Flag,
construct.Padding(4), construct.Padding(4),
"timestamp" / DatetimeAdapter(),
"seq_num" / DecimalAdapter(),
"maker" / PublicKeyAdapter(), "maker" / PublicKeyAdapter(),
"maker_order_id" / SignedDecimalAdapter(16), "maker_order_id" / SignedDecimalAdapter(16),
"maker_client_order_id" / DecimalAdapter(), "maker_client_order_id" / DecimalAdapter(),
"maker_fee" / FloatI80F48Adapter(),
"best_initial" / SignedDecimalAdapter(), "best_initial" / SignedDecimalAdapter(),
"maker_timestamp" / DatetimeAdapter(),
"timestamp" / DatetimeAdapter(),
"taker" / PublicKeyAdapter(), "taker" / PublicKeyAdapter(),
"taker_order_id" / SignedDecimalAdapter(16), "taker_order_id" / SignedDecimalAdapter(16),
"taker_client_order_id" / DecimalAdapter(), "taker_client_order_id" / DecimalAdapter(),
"taker_fee" / FloatI80F48Adapter(),
"price" / SignedDecimalAdapter(), "price" / SignedDecimalAdapter(),
"quantity" / SignedDecimalAdapter() "quantity" / SignedDecimalAdapter()
) )
_EVENT_SIZE = 152 _EVENT_SIZE = 200
assert FILL_EVENT.sizeof() == _EVENT_SIZE assert FILL_EVENT.sizeof() == _EVENT_SIZE, f"Fill event size is {FILL_EVENT.sizeof()} when it should be {_EVENT_SIZE}."
# # 🥭 OUT_EVENT # # 🥭 OUT_EVENT
# #
@ -967,9 +976,11 @@ assert FILL_EVENT.sizeof() == _EVENT_SIZE
# pub side: Side, # pub side: Side,
# pub slot: u8, # pub slot: u8,
# padding0: [u8; 5], # padding0: [u8; 5],
# pub timestamp: u64,
# pub seq_num: usize,
# pub owner: Pubkey, # pub owner: Pubkey,
# pub quantity: i64, # pub quantity: i64,
# padding1: [u8; EVENT_SIZE - 48], # padding1: [u8; EVENT_SIZE - 64],
# } # }
# ``` # ```
OUT_EVENT = construct.Struct( OUT_EVENT = construct.Struct(
@ -977,11 +988,48 @@ OUT_EVENT = construct.Struct(
"side" / DecimalAdapter(1), "side" / DecimalAdapter(1),
"slot" / DecimalAdapter(1), "slot" / DecimalAdapter(1),
construct.Padding(5), construct.Padding(5),
"timestamp" / DatetimeAdapter(),
"seq_num" / DecimalAdapter(),
"owner" / PublicKeyAdapter(), "owner" / PublicKeyAdapter(),
"quantity" / SignedDecimalAdapter(), "quantity" / SignedDecimalAdapter(),
construct.Padding(_EVENT_SIZE - 48) construct.Padding(_EVENT_SIZE - 64)
) )
assert OUT_EVENT.sizeof() == _EVENT_SIZE assert OUT_EVENT.sizeof() == _EVENT_SIZE, f"Out event size is {OUT_EVENT.sizeof()} when it should be {_EVENT_SIZE}."
# # 🥭 LIQUIDATE_EVENT
#
# Here's the [Rust structure](https://github.com/blockworks-foundation/mango-v3/blob/main/program/src/queue.rs):
# ```
# #[derive(Copy, Clone, Debug, Pod)]
# #[repr(C)]
# /// Liquidation for the PerpMarket this EventQueue is for
# pub struct LiquidateEvent {
# pub event_type: u8,
# padding0: [u8; 7],
# pub timestamp: u64,
# pub seq_num: usize,
# pub liqee: Pubkey,
# pub liqor: Pubkey,
# pub price: I80F48, // oracle price at the time of liquidation
# pub quantity: i64, // number of contracts that were moved from liqee to liqor
# pub liquidation_fee: I80F48, // liq fee for this earned for this market
# padding1: [u8; EVENT_SIZE - 128],
# }
# ```
LIQUIDATE_EVENT = construct.Struct(
"event_type" / construct.Const(b'\x02'),
construct.Padding(7),
"timestamp" / DatetimeAdapter(),
"seq_num" / DecimalAdapter(),
"liquidatee" / PublicKeyAdapter(),
"liquidator" / PublicKeyAdapter(),
"price" / FloatI80F48Adapter(),
"quantity" / SignedDecimalAdapter(),
"liquidation_fee" / FloatI80F48Adapter(),
construct.Padding(_EVENT_SIZE - 128)
)
assert LIQUIDATE_EVENT.sizeof(
) == _EVENT_SIZE, f"Liquidate event size is {LIQUIDATE_EVENT.sizeof()} when it should be {_EVENT_SIZE}."
UNKNOWN_EVENT = construct.Struct( UNKNOWN_EVENT = construct.Struct(
"event_type" / construct.Bytes(1), "event_type" / construct.Bytes(1),
@ -989,7 +1037,8 @@ UNKNOWN_EVENT = construct.Struct(
"owner" / PublicKeyAdapter(), "owner" / PublicKeyAdapter(),
construct.Padding(_EVENT_SIZE - 40) construct.Padding(_EVENT_SIZE - 40)
) )
assert UNKNOWN_EVENT.sizeof() == _EVENT_SIZE assert UNKNOWN_EVENT.sizeof(
) == _EVENT_SIZE, f"Unknown event size is {UNKNOWN_EVENT.sizeof()} when it should be {_EVENT_SIZE}."
# # 🥭 PERP_EVENT_QUEUE # # 🥭 PERP_EVENT_QUEUE
# #
@ -1017,9 +1066,9 @@ PERP_EVENT_QUEUE = construct.Struct(
"head" / DecimalAdapter(), "head" / DecimalAdapter(),
"count" / DecimalAdapter(), "count" / DecimalAdapter(),
"seq_num" / DecimalAdapter(), "seq_num" / DecimalAdapter(),
"maker_fee" / FloatI80F48Adapter(), # "maker_fee" / FloatI80F48Adapter(),
"taker_fee" / FloatI80F48Adapter(), # "taker_fee" / FloatI80F48Adapter(),
"events" / construct.GreedyRange(construct.Select(FILL_EVENT, OUT_EVENT, UNKNOWN_EVENT)) "events" / construct.GreedyRange(construct.Select(FILL_EVENT, OUT_EVENT, LIQUIDATE_EVENT, UNKNOWN_EVENT))
) )
# # 🥭 SERUM_EVENT_QUEUE # # 🥭 SERUM_EVENT_QUEUE

View File

@ -111,6 +111,31 @@ class PerpOutEvent(PerpEvent):
return f"""« 𝙿𝚎𝚛𝚙𝙾𝚞𝚝𝙴𝚟𝚎𝚗𝚝 [{self.original_index}] [{self.owner}] {self.side} {self.quantity}, slot: {self.slot} »""" return f"""« 𝙿𝚎𝚛𝚙𝙾𝚞𝚝𝙴𝚟𝚎𝚗𝚝 [{self.original_index}] [{self.owner}] {self.side} {self.quantity}, slot: {self.slot} »"""
# # 🥭 PerpLiquidateEvent class
#
# `PerpLiquidateEvent` stores details of a perp 'liquidate' event.
#
class PerpLiquidateEvent(PerpEvent):
def __init__(self, event_type: int, original_index: Decimal, timestamp: datetime, seq_num: Decimal,
liquidatee: PublicKey, liquidator: PublicKey, price: Decimal, quantity: Decimal,
liquidation_fee: Decimal):
super().__init__(event_type, original_index)
self.timestamp: datetime = timestamp
self.seq_num: Decimal = seq_num
self.liquidatee: PublicKey = liquidatee
self.liquidator: PublicKey = liquidator
self.price: Decimal = price
self.quantity: Decimal = quantity
self.liquidation_fee: Decimal = liquidation_fee
@property
def accounts_to_crank(self) -> typing.Sequence[PublicKey]:
return [self.liquidatee, self.liquidator]
def __str__(self) -> str:
return f"""« 𝙿𝚎𝚛𝚙𝙻𝚒𝚚𝚞𝚒𝚍𝚊𝚝𝚎𝙴𝚟𝚎𝚗𝚝 [{self.original_index}] [{self.owner}] {self.side} {self.quantity}, slot: {self.slot} »"""
# # 🥭 PerpUnknownEvent class # # 🥭 PerpUnknownEvent class
# #
# `PerpUnknownEvent` details an unknown `PerpEvent`. This should never be encountered, but might if # `PerpUnknownEvent` details an unknown `PerpEvent`. This should never be encountered, but might if
@ -137,7 +162,7 @@ def event_builder(lot_size_converter: LotSizeConverter, event_layout, original_i
if event_layout.event_type == b'\x00': if event_layout.event_type == b'\x00':
if event_layout.maker is None and event_layout.taker is None: if event_layout.maker is None and event_layout.taker is None:
return None return None
side: Side = Side.from_value(event_layout.side) side: Side = Side.from_value(event_layout.taker_side)
quantity: Decimal = lot_size_converter.quantity_lots_to_value(event_layout.quantity) quantity: Decimal = lot_size_converter.quantity_lots_to_value(event_layout.quantity)
price: Decimal = lot_size_converter.price_lots_to_value(event_layout.price) price: Decimal = lot_size_converter.price_lots_to_value(event_layout.price)
return PerpFillEvent(event_layout.event_type, original_index, event_layout.timestamp, side, return PerpFillEvent(event_layout.event_type, original_index, event_layout.timestamp, side,
@ -148,6 +173,8 @@ def event_builder(lot_size_converter: LotSizeConverter, event_layout, original_i
event_layout.taker_client_order_id) event_layout.taker_client_order_id)
elif event_layout.event_type == b'\x01': elif event_layout.event_type == b'\x01':
return PerpOutEvent(event_layout.event_type, original_index, event_layout.owner, event_layout.side, event_layout.quantity, event_layout.slot) return PerpOutEvent(event_layout.event_type, original_index, event_layout.owner, event_layout.side, event_layout.quantity, event_layout.slot)
elif event_layout.event_type == b'\x02':
return PerpLiquidateEvent(event_layout.event_type, original_index, event_layout.timestamp, event_layout.seq_num, event_layout.liquidatee, event_layout.liquidator, event_layout.price, event_layout.quantity, event_layout.liquidation_fee)
else: else:
return PerpUnknownEvent(event_layout.event_type, original_index, event_layout.owner) return PerpUnknownEvent(event_layout.event_type, original_index, event_layout.owner)

View File

@ -87,7 +87,20 @@ _instruction_signer_indices: typing.Dict[InstructionType, int] = {
InstructionType.CancelSpotOrder: 1, InstructionType.CancelSpotOrder: 1,
InstructionType.UpdateRootBank: -1, # No signer InstructionType.UpdateRootBank: -1, # No signer
InstructionType.SettlePnl: -1, # No signer InstructionType.SettlePnl: -1, # No signer
InstructionType.SettleBorrow: -1 # No signer InstructionType.SettleBorrow: -1, # No signer
InstructionType.ForceCancelSpotOrders: -1,
InstructionType.ForceCancelPerpOrders: -1,
InstructionType.LiquidateTokenAndToken: -1,
InstructionType.LiquidateTokenAndPerp: -1,
InstructionType.LiquidatePerpMarket: -1,
InstructionType.SettleFees: -1,
InstructionType.ResolvePerpBankruptcy: -1,
InstructionType.ResolveTokenBankruptcy: -1,
InstructionType.InitSpotOpenOrders: -1,
InstructionType.RedeemMngo: -1,
InstructionType.AddMangoAccountInfo: -1,
InstructionType.DepositMsrm: -1,
InstructionType.WithdrawMsrm: -1,
} }
# The index of the token IN account depends on the instruction, and for some instructions # The index of the token IN account depends on the instruction, and for some instructions
@ -117,6 +130,19 @@ _token_in_indices: typing.Dict[InstructionType, int] = {
InstructionType.UpdateRootBank: -1, InstructionType.UpdateRootBank: -1,
InstructionType.SettlePnl: -1, InstructionType.SettlePnl: -1,
InstructionType.SettleBorrow: -1, InstructionType.SettleBorrow: -1,
InstructionType.ForceCancelSpotOrders: -1,
InstructionType.ForceCancelPerpOrders: -1,
InstructionType.LiquidateTokenAndToken: -1,
InstructionType.LiquidateTokenAndPerp: -1,
InstructionType.LiquidatePerpMarket: -1,
InstructionType.SettleFees: -1,
InstructionType.ResolvePerpBankruptcy: -1,
InstructionType.ResolveTokenBankruptcy: -1,
InstructionType.InitSpotOpenOrders: -1,
InstructionType.RedeemMngo: -1,
InstructionType.AddMangoAccountInfo: -1,
InstructionType.DepositMsrm: -1,
InstructionType.WithdrawMsrm: -1,
} }
# The index of the token OUT account depends on the instruction, and for some instructions # The index of the token OUT account depends on the instruction, and for some instructions
@ -146,6 +172,19 @@ _token_out_indices: typing.Dict[InstructionType, int] = {
InstructionType.UpdateRootBank: -1, InstructionType.UpdateRootBank: -1,
InstructionType.SettlePnl: -1, InstructionType.SettlePnl: -1,
InstructionType.SettleBorrow: -1, InstructionType.SettleBorrow: -1,
InstructionType.ForceCancelSpotOrders: -1,
InstructionType.ForceCancelPerpOrders: -1,
InstructionType.LiquidateTokenAndToken: -1,
InstructionType.LiquidateTokenAndPerp: -1,
InstructionType.LiquidatePerpMarket: -1,
InstructionType.SettleFees: -1,
InstructionType.ResolvePerpBankruptcy: -1,
InstructionType.ResolveTokenBankruptcy: -1,
InstructionType.InitSpotOpenOrders: -1,
InstructionType.RedeemMngo: -1,
InstructionType.AddMangoAccountInfo: -1,
InstructionType.DepositMsrm: -1,
InstructionType.WithdrawMsrm: -1,
} }
@ -175,6 +214,19 @@ _target_indices: typing.Dict[InstructionType, int] = {
InstructionType.UpdateRootBank: -1, InstructionType.UpdateRootBank: -1,
InstructionType.SettlePnl: -1, InstructionType.SettlePnl: -1,
InstructionType.SettleBorrow: -1, InstructionType.SettleBorrow: -1,
InstructionType.ForceCancelSpotOrders: -1,
InstructionType.ForceCancelPerpOrders: -1,
InstructionType.LiquidateTokenAndToken: -1,
InstructionType.LiquidateTokenAndPerp: -1,
InstructionType.LiquidatePerpMarket: -1,
InstructionType.SettleFees: -1,
InstructionType.ResolvePerpBankruptcy: -1,
InstructionType.ResolveTokenBankruptcy: -1,
InstructionType.InitSpotOpenOrders: -1,
InstructionType.RedeemMngo: -1,
InstructionType.AddMangoAccountInfo: -1,
InstructionType.DepositMsrm: -1,
InstructionType.WithdrawMsrm: -1,
} }