1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
use crate::{
    accounts_ix::FlashLoanType,
    state::{OracleType, PerpMarket, PerpPosition},
};
use anchor_lang::prelude::*;
use borsh::BorshSerialize;

#[inline(never)] // ensure fresh stack frame
pub fn emit_stack<T: anchor_lang::Event>(e: T) {
    use std::io::{Cursor, Write};

    // stack buffer, stack frames are 4kb
    let mut buffer = [0u8; 3000];

    let mut cursor = Cursor::new(&mut buffer[..]);
    cursor.write_all(&T::DISCRIMINATOR).unwrap();
    e.serialize(&mut cursor)
        .expect("event must fit into stack buffer");

    let pos = cursor.position() as usize;
    anchor_lang::solana_program::log::sol_log_data(&[&buffer[..pos]]);
}

pub fn emit_perp_balances(
    mango_group: Pubkey,
    mango_account: Pubkey,
    pp: &PerpPosition,
    pm: &PerpMarket,
) {
    emit_stack(PerpBalanceLog {
        mango_group,
        mango_account,
        market_index: pm.perp_market_index,
        base_position: pp.base_position_lots(),
        quote_position: pp.quote_position_native().to_bits(),
        long_settled_funding: pp.long_settled_funding.to_bits(),
        short_settled_funding: pp.short_settled_funding.to_bits(),
        long_funding: pm.long_funding.to_bits(),
        short_funding: pm.short_funding.to_bits(),
    });
}

#[event]
pub struct PerpBalanceLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub market_index: u16,
    pub base_position: i64,
    pub quote_position: i128,        // I80F48
    pub long_settled_funding: i128,  // I80F48
    pub short_settled_funding: i128, // I80F48
    pub long_funding: i128,          // I80F48
    pub short_funding: i128,         // I80F48
}

#[event]
pub struct TokenBalanceLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_index: u16,       // IDL doesn't support usize
    pub indexed_position: i128, // on client convert i128 to I80F48 easily by passing in the BN to I80F48 ctor
    pub deposit_index: i128,    // I80F48
    pub borrow_index: i128,     // I80F48
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct FlashLoanTokenDetail {
    pub token_index: u16,
    pub change_amount: i128,
    pub loan: i128,
    pub loan_origination_fee: i128,
    pub deposit_index: i128,
    pub borrow_index: i128,
    pub price: i128,
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct FlashLoanTokenDetailV2 {
    pub token_index: u16,

    /// The amount by which the user's token position changed at the end
    ///
    /// So if the user repaid the approved_amount in full, it'd be 0.
    ///
    /// Does NOT include the loan_origination_fee or deposit_fee, so the true
    /// change is `change_amount - loan_origination_fee - deposit_fee`.
    pub change_amount: i128,

    /// The amount that was a loan (<= approved_amount, depends on user's deposits)
    pub loan: i128,

    /// The fee paid on the loan, not included in `loan` or `change_amount`
    pub loan_origination_fee: i128,

    pub deposit_index: i128,
    pub borrow_index: i128,
    pub price: i128,

    /// Deposit fee paid for positive change_amount.
    ///
    /// Not factored into change_amount.
    pub deposit_fee: i128,

    /// The amount that was transfered out to the user
    pub approved_amount: u64,
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct FlashLoanTokenDetailV3 {
    pub token_index: u16,

    /// The amount by which the user's token position changed at the end
    ///
    /// So if the user repaid the approved_amount in full, it'd be 0.
    ///
    /// Does NOT include the loan_origination_fee or deposit_fee, so the true
    /// change is `change_amount - loan_origination_fee - deposit_fee`.
    pub change_amount: i128,

    /// The amount that was a loan (<= approved_amount, depends on user's deposits)
    pub loan: i128,

    /// The fee paid on the loan, not included in `loan` or `change_amount`
    pub loan_origination_fee: i128,

    pub deposit_index: i128,
    pub borrow_index: i128,
    pub price: i128,

    /// Swap fee paid on the in token of a swap.
    ///
    /// Not factored into change_amount.
    pub swap_fee: i128,

    /// The amount that was transfered out to the user
    pub approved_amount: u64,
}

#[event]
pub struct FlashLoanLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_loan_details: Vec<FlashLoanTokenDetail>,
    pub flash_loan_type: FlashLoanType,
}

#[event]
pub struct FlashLoanLogV2 {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_loan_details: Vec<FlashLoanTokenDetailV2>,
    pub flash_loan_type: FlashLoanType,
}

#[event]
pub struct FlashLoanLogV3 {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_loan_details: Vec<FlashLoanTokenDetailV3>,
    pub flash_loan_type: FlashLoanType,
}

#[event]
pub struct WithdrawLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub signer: Pubkey,
    pub token_index: u16,
    pub quantity: u64,
    pub price: i128, // I80F48
}

#[event]
pub struct DepositLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub signer: Pubkey,
    pub token_index: u16,
    pub quantity: u64,
    pub price: i128, // I80F48
}

#[event]
pub struct FillLog {
    pub mango_group: Pubkey,
    pub market_index: u16,
    pub taker_side: u8, // side from the taker's POV
    pub maker_slot: u8,
    pub maker_out: bool, // true if maker order quantity == 0
    pub timestamp: u64,
    pub seq_num: u64, // note: usize same as u64

    pub maker: Pubkey,
    pub maker_order_id: u128,
    pub maker_fee: i128,

    // Timestamp of when the maker order was placed; copied over from the LeafNode
    pub maker_timestamp: u64,

    pub taker: Pubkey,
    pub taker_order_id: u128,
    pub taker_client_order_id: u64,
    pub taker_fee: i128,

    pub price: i64,
    pub quantity: i64, // number of base lots
}

#[event]
pub struct FillLogV2 {
    pub mango_group: Pubkey,
    pub market_index: u16,
    pub taker_side: u8, // side from the taker's POV
    pub maker_slot: u8,
    pub maker_out: bool, // true if maker order quantity == 0
    pub timestamp: u64,
    pub seq_num: u64, // note: usize same as u64

    pub maker: Pubkey,
    pub maker_client_order_id: u64,
    pub maker_fee: f32,

    // Timestamp of when the maker order was placed; copied over from the LeafNode
    pub maker_timestamp: u64,

    pub taker: Pubkey,
    pub taker_client_order_id: u64,
    pub taker_fee: f32,

    pub price: i64,
    pub quantity: i64, // number of base lots
}

#[event]
pub struct FillLogV3 {
    pub mango_group: Pubkey,
    pub market_index: u16,
    pub taker_side: u8, // side from the taker's POV
    pub maker_slot: u8,
    pub maker_out: bool, // true if maker order quantity == 0
    pub timestamp: u64,
    pub seq_num: u64, // note: usize same as u64

    pub maker: Pubkey,
    pub maker_client_order_id: u64,
    pub maker_fee: f32,

    // Timestamp of when the maker order was placed; copied over from the LeafNode
    pub maker_timestamp: u64,

    pub taker: Pubkey,
    pub taker_client_order_id: u64,
    pub taker_fee: f32,

    pub price: i64,
    pub quantity: i64,         // number of base lots
    pub maker_closed_pnl: f64, // settle-token-native units
    pub taker_closed_pnl: f64, // settle-token-native units
}

#[event]
pub struct PerpUpdateFundingLog {
    pub mango_group: Pubkey,
    pub market_index: u16,
    pub long_funding: i128,
    pub short_funding: i128,
    pub price: i128,
    pub oracle_slot: u64,
    pub stable_price: i128,
    pub fees_accrued: i128,
    pub fees_settled: i128,
    pub open_interest: i64,
    pub instantaneous_funding_rate: i128,
}

#[event]
pub struct PerpUpdateFundingLogV2 {
    pub mango_group: Pubkey,
    pub market_index: u16,
    pub long_funding: i128,
    pub short_funding: i128,
    pub price: i128,
    pub oracle_slot: u64,
    pub oracle_confidence: i128,
    pub oracle_type: OracleType,
    pub stable_price: i128,
    pub fees_accrued: i128,
    pub fees_settled: i128,
    pub open_interest: i64,
    pub instantaneous_funding_rate: i128,
}

#[event]
pub struct UpdateIndexLog {
    pub mango_group: Pubkey,
    pub token_index: u16,
    pub deposit_index: i128,   // I80F48
    pub borrow_index: i128,    // I80F48
    pub avg_utilization: i128, // I80F48
    pub price: i128,           // I80F48
    pub stable_price: i128,    // I80F48
    pub collected_fees: i128,  // I80F48
    pub loan_fee_rate: i128,   // I80F48
    pub total_borrows: i128,
    pub total_deposits: i128,
    pub borrow_rate: i128,
    pub deposit_rate: i128,
}

#[event]
pub struct UpdateRateLog {
    pub mango_group: Pubkey,
    pub token_index: u16,
    pub rate0: i128,    // I80F48
    pub rate1: i128,    // I80F48
    pub max_rate: i128, // I80F48
}

#[event]
pub struct UpdateRateLogV2 {
    pub mango_group: Pubkey,
    pub token_index: u16,
    // contrary to v1 these do not have curve_scaling factored in!
    pub rate0: i128,    // I80F48
    pub util0: i128,    // I80F48
    pub rate1: i128,    // I80F48
    pub util1: i128,    // I80F48
    pub max_rate: i128, // I80F48
    pub curve_scaling: f64,
    pub target_utilization: f32,
}

#[event]
pub struct TokenLiqWithTokenLog {
    pub mango_group: Pubkey,
    pub liqee: Pubkey,
    pub liqor: Pubkey,
    pub asset_token_index: u16,
    pub liab_token_index: u16,
    pub asset_transfer: i128, // I80F48
    pub liab_transfer: i128,  // I80F48
    pub asset_price: i128,    // I80F48
    pub liab_price: i128,     // I80F48
    pub bankruptcy: bool,
}

#[event]
pub struct TokenLiqWithTokenLogV2 {
    pub mango_group: Pubkey,
    pub liqee: Pubkey,
    pub liqor: Pubkey,
    pub asset_token_index: u16,
    pub liab_token_index: u16,
    pub asset_transfer_from_liqee: i128, // I80F48
    pub asset_transfer_to_liqor: i128,   // I80F48
    pub asset_liquidation_fee: i128,     // I80F48
    pub liab_transfer: i128,             // I80F48
    pub asset_price: i128,               // I80F48
    pub liab_price: i128,                // I80F48
    pub bankruptcy: bool,
}

#[event]
pub struct Serum3OpenOrdersBalanceLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub base_token_index: u16,
    pub quote_token_index: u16,
    pub base_total: u64,
    pub base_free: u64,
    pub quote_total: u64,
    pub quote_free: u64,
    pub referrer_rebates_accrued: u64,
}

#[event]
pub struct Serum3OpenOrdersBalanceLogV2 {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub market_index: u16,
    pub base_token_index: u16,
    pub quote_token_index: u16,
    pub base_total: u64,
    pub base_free: u64,
    pub quote_total: u64,
    pub quote_free: u64,
    pub referrer_rebates_accrued: u64,
}

#[event]
pub struct OpenbookV2OpenOrdersBalanceLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub market_index: u16,
    pub base_token_index: u16,
    pub quote_token_index: u16,
    pub base_total: u64,
    pub base_free: u64,
    pub quote_total: u64,
    pub quote_free: u64,
    pub referrer_rebates_accrued: u64,
}

#[derive(PartialEq, Copy, Clone, Debug, AnchorSerialize, AnchorDeserialize)]
#[repr(u8)]
pub enum LoanOriginationFeeInstruction {
    Unknown,
    LiqTokenBankruptcy,
    LiqTokenWithToken,
    Serum3LiqForceCancelOrders,
    Serum3PlaceOrder,
    Serum3SettleFunds,
    TokenWithdraw,
    TokenConditionalSwapTrigger,
    OpenbookV2LiqForceCancelOrders,
    OpenbookV2PlaceOrder,
    OpenbookV2SettleFunds,
}

#[event]
pub struct WithdrawLoanOriginationFeeLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_index: u16,
    pub loan_origination_fee: i128, // I80F48
    pub instruction: LoanOriginationFeeInstruction,
}

#[event]
pub struct WithdrawLoanLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_index: u16,
    pub loan_amount: i128,
    pub loan_origination_fee: i128,
    pub instruction: LoanOriginationFeeInstruction,
    pub price: Option<i128>, // Ideally would log price everywhere but in serum3_settle_funds oracle is not a passed in account
}

#[event]
pub struct TokenLiqBankruptcyLog {
    pub mango_group: Pubkey,
    pub liqee: Pubkey,
    pub liqor: Pubkey,
    pub liab_token_index: u16,
    pub initial_liab_native: i128,
    pub liab_price: i128,
    pub insurance_token_index: u16,
    pub insurance_transfer: i128,
    pub socialized_loss: i128,
    pub starting_liab_deposit_index: i128,
    pub ending_liab_deposit_index: i128,
}

#[event]
pub struct DeactivateTokenPositionLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_index: u16,
    pub cumulative_deposit_interest: f64,
    pub cumulative_borrow_interest: f64,
}

#[event]
pub struct DeactivatePerpPositionLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub market_index: u16,
    pub cumulative_long_funding: f64,
    pub cumulative_short_funding: f64,
    pub maker_volume: u64,
    pub taker_volume: u64,
    pub perp_spot_transfers: i64,
}

#[event]
pub struct TokenMetaDataLog {
    pub mango_group: Pubkey,
    pub mint: Pubkey,
    pub token_index: u16,
    pub mint_decimals: u8,
    pub oracle: Pubkey,
    pub mint_info: Pubkey,
}

#[event]
pub struct TokenMetaDataLogV2 {
    pub mango_group: Pubkey,
    pub mint: Pubkey,
    pub token_index: u16,
    pub mint_decimals: u8,
    pub oracle: Pubkey,
    pub fallback_oracle: Pubkey,
    pub mint_info: Pubkey,
}

#[event]
pub struct PerpMarketMetaDataLog {
    pub mango_group: Pubkey,
    pub perp_market: Pubkey,
    pub perp_market_index: u16,
    pub base_decimals: u8,
    pub base_lot_size: i64,
    pub quote_lot_size: i64,
    pub oracle: Pubkey,
}

#[event]
pub struct Serum3RegisterMarketLog {
    pub mango_group: Pubkey,
    pub serum_market: Pubkey,
    pub market_index: u16,
    pub base_token_index: u16,
    pub quote_token_index: u16,
    pub serum_program: Pubkey,
    pub serum_program_external: Pubkey,
}

#[event]
pub struct OpenbookV2RegisterMarketLog {
    pub mango_group: Pubkey,
    pub openbook_market: Pubkey,
    pub market_index: u16,
    pub base_token_index: u16,
    pub quote_token_index: u16,
    pub openbook_program: Pubkey,
    pub openbook_market_external: Pubkey,
}

#[event]
pub struct PerpLiqBaseOrPositivePnlLog {
    pub mango_group: Pubkey,
    pub perp_market_index: u16,
    pub liqor: Pubkey,
    pub liqee: Pubkey,
    pub base_transfer: i64,
    pub quote_transfer: i128,
    pub pnl_transfer: i128,
    pub pnl_settle_limit_transfer: i128,
    pub price: i128,
}

#[event]
pub struct PerpLiqBaseOrPositivePnlLogV2 {
    pub mango_group: Pubkey,
    pub perp_market_index: u16,
    pub liqor: Pubkey,
    pub liqee: Pubkey,
    pub base_transfer_liqee: i64,
    pub quote_transfer_liqee: i128,
    pub quote_transfer_liqor: i128,
    pub quote_platform_fee: i128,
    pub pnl_transfer: i128,
    pub pnl_settle_limit_transfer: i128,
    pub price: i128,
}

#[event]
pub struct PerpLiqBaseOrPositivePnlLogV3 {
    pub mango_group: Pubkey,
    pub perp_market_index: u16,
    pub liqor: Pubkey,
    pub liqee: Pubkey,
    pub base_transfer_liqee: i64,
    pub quote_transfer_liqee: i128,
    pub quote_transfer_liqor: i128,
    pub quote_platform_fee: i128,
    pub pnl_transfer: i128,
    pub pnl_settle_limit_transfer_recurring: i64,
    pub pnl_settle_limit_transfer_oneshot: i64,
    pub price: i128,
}

#[event]
pub struct PerpLiqBankruptcyLog {
    pub mango_group: Pubkey,
    pub liqee: Pubkey,
    pub liqor: Pubkey,
    pub perp_market_index: u16,
    pub insurance_transfer: i128,
    pub socialized_loss: i128,
    pub starting_long_funding: i128,
    pub starting_short_funding: i128,
    pub ending_long_funding: i128,
    pub ending_short_funding: i128,
}

#[event]
pub struct PerpLiqNegativePnlOrBankruptcyLog {
    pub mango_group: Pubkey,
    pub liqee: Pubkey,
    pub liqor: Pubkey,
    pub perp_market_index: u16,
    pub settlement: i128,
}

#[event]
pub struct PerpSettlePnlLog {
    pub mango_group: Pubkey,
    pub mango_account_a: Pubkey,
    pub mango_account_b: Pubkey,
    pub perp_market_index: u16,
    pub settlement: i128,
    pub settler: Pubkey,
    pub fee: i128,
}

#[event]
pub struct PerpSettleFeesLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub perp_market_index: u16,
    pub settlement: i128,
}

#[event]
pub struct AccountBuybackFeesWithMngoLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub buyback_fees: i128,
    pub buyback_mngo: i128,
    pub mngo_buyback_price: i128,
    pub oracle_price: i128,
}

#[event]
pub struct FilledPerpOrderLog {
    pub mango_group: Pubkey,
    pub perp_market_index: u16,
    pub seq_num: u64,
}

#[event]
pub struct PerpTakerTradeLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub perp_market_index: u16,
    pub taker_side: u8,
    pub total_base_lots_taken: i64, // includes decremented base lots
    pub total_base_lots_decremented: i64, // from DecrementTake self-trades
    pub total_quote_lots_taken: i64, // exclusive fees paid, includes decremented quote lots
    pub total_quote_lots_decremented: i64, // from DecrementTake self-trades
    pub taker_fees_paid: i128,      // in native quote units
    pub fee_penalty: i128,          // in native quote units
}

#[event]
pub struct PerpForceClosePositionLog {
    pub mango_group: Pubkey,
    pub perp_market_index: u16,
    pub account_a: Pubkey,
    pub account_b: Pubkey,
    pub base_transfer: i64,
    pub quote_transfer: i128,
    pub price: i128,
}

#[event]
pub struct TokenForceCloseBorrowsWithTokenLog {
    pub mango_group: Pubkey,
    pub liqor: Pubkey,
    pub liqee: Pubkey,
    pub asset_token_index: u16,
    pub liab_token_index: u16,
    pub asset_transfer: i128,
    pub liab_transfer: i128,
    pub asset_price: i128,
    pub liab_price: i128,
    pub fee_factor: i128,
}

#[event]
pub struct TokenForceCloseBorrowsWithTokenLogV2 {
    pub mango_group: Pubkey,
    pub liqor: Pubkey,
    pub liqee: Pubkey,
    pub asset_token_index: u16,
    pub liab_token_index: u16,
    pub asset_transfer_from_liqee: i128, // I80F48
    pub asset_transfer_to_liqor: i128,   // I80F48
    pub asset_liquidation_fee: i128,     // I80F48
    pub liab_transfer: i128,             // I80F48
    pub asset_price: i128,               // I80F48
    pub liab_price: i128,                // I80F48
    /// including liqor and platform liquidation fees
    pub fee_factor: i128, // I80F48
}

#[event]
pub struct TokenConditionalSwapCreateLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub id: u64,
    pub max_buy: u64,
    pub max_sell: u64,
    pub expiry_timestamp: u64,
    pub price_lower_limit: f64,
    pub price_upper_limit: f64,
    pub price_premium_rate: f64,
    pub taker_fee_rate: f32,
    pub maker_fee_rate: f32,
    pub buy_token_index: u16,
    pub sell_token_index: u16,
    pub allow_creating_deposits: bool,
    pub allow_creating_borrows: bool,
}

#[event]
pub struct TokenConditionalSwapCreateLogV2 {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub id: u64,
    pub max_buy: u64,
    pub max_sell: u64,
    pub expiry_timestamp: u64,
    pub price_lower_limit: f64,
    pub price_upper_limit: f64,
    pub price_premium_rate: f64,
    pub taker_fee_rate: f32,
    pub maker_fee_rate: f32,
    pub buy_token_index: u16,
    pub sell_token_index: u16,
    pub allow_creating_deposits: bool,
    pub allow_creating_borrows: bool,
    pub display_price_style: u8,
    pub intention: u8,
}

#[event]
pub struct TokenConditionalSwapCreateLogV3 {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub id: u64,
    pub max_buy: u64,
    pub max_sell: u64,
    pub expiry_timestamp: u64,
    pub price_lower_limit: f64,
    pub price_upper_limit: f64,
    pub price_premium_rate: f64,
    pub taker_fee_rate: f32,
    pub maker_fee_rate: f32,
    pub buy_token_index: u16,
    pub sell_token_index: u16,
    pub allow_creating_deposits: bool,
    pub allow_creating_borrows: bool,
    pub display_price_style: u8,
    pub intention: u8,
    pub tcs_type: u8,
    pub start_timestamp: u64,
    pub duration_seconds: u64,
}

#[event]
pub struct TokenConditionalSwapTriggerLog {
    pub mango_group: Pubkey,
    pub liqee: Pubkey,
    pub liqor: Pubkey,
    pub token_conditional_swap_id: u64,
    pub buy_token_index: u16,
    pub sell_token_index: u16,
    pub buy_amount: u64,        // amount the liqee got
    pub sell_amount: u64,       // amount the liqee paid (including fees)
    pub maker_fee: u64,         // in native units of sell token (included in sell amount)
    pub taker_fee: u64, // in native units of sell token (deducted from the sell amount the liqor received)
    pub buy_token_price: i128, // I80F48
    pub sell_token_price: i128, // I80F48
    pub closed: bool,
}

#[event]
pub struct TokenConditionalSwapTriggerLogV2 {
    pub mango_group: Pubkey,
    pub liqee: Pubkey,
    pub liqor: Pubkey,
    pub token_conditional_swap_id: u64,
    pub buy_token_index: u16,
    pub sell_token_index: u16,
    pub buy_amount: u64,        // amount the liqee got
    pub sell_amount: u64,       // amount the liqee paid (including fees)
    pub maker_fee: u64,         // in native units of sell token (included in sell amount)
    pub taker_fee: u64, // in native units of sell token (deducted from the sell amount the liqor received)
    pub buy_token_price: i128, // I80F48
    pub sell_token_price: i128, // I80F48
    pub closed: bool,
    pub display_price_style: u8,
    pub intention: u8,
}

#[event]
pub struct TokenConditionalSwapTriggerLogV3 {
    pub mango_group: Pubkey,
    pub liqee: Pubkey,
    pub liqor: Pubkey,
    pub token_conditional_swap_id: u64,
    pub buy_token_index: u16,
    pub sell_token_index: u16,
    pub buy_amount: u64,        // amount the liqee got
    pub sell_amount: u64,       // amount the liqee paid (including fees)
    pub maker_fee: u64,         // in native units of sell token (included in sell amount)
    pub taker_fee: u64, // in native units of sell token (deducted from the sell amount the liqor received)
    pub buy_token_price: i128, // I80F48
    pub sell_token_price: i128, // I80F48
    pub closed: bool,
    pub display_price_style: u8,
    pub intention: u8,
    pub tcs_type: u8,
    pub start_timestamp: u64,
}

#[event]
pub struct TokenConditionalSwapCancelLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub id: u64,
}

#[event]
pub struct TokenConditionalSwapStartLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub caller: Pubkey,
    pub token_conditional_swap_id: u64,
    pub incentive_token_index: u16,
    pub incentive_amount: u64,
}

#[event]
pub struct TokenCollateralFeeLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_index: u16,
    pub asset_usage_fraction: i128,
    pub fee: i128,
    pub price: i128,
}

#[event]
pub struct ForceWithdrawLog {
    pub mango_group: Pubkey,
    pub mango_account: Pubkey,
    pub token_index: u16,
    pub quantity: u64,
    pub price: i128, // I80F48
    pub to_token_account: Pubkey,
}