@drift-labs/sdk 0.1.12 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts +1 -0
- package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts.map +1 -1
- package/lib/accounts/defaultClearingHouseAccountSubscriber.js +17 -0
- package/lib/accounts/defaultUserAccountSubscriber.d.ts +2 -0
- package/lib/accounts/defaultUserAccountSubscriber.d.ts.map +1 -1
- package/lib/accounts/defaultUserAccountSubscriber.js +16 -0
- package/lib/accounts/types.d.ts +3 -21
- package/lib/accounts/types.d.ts.map +1 -1
- package/lib/accounts/webSocketAccountSubscriber.d.ts +2 -0
- package/lib/accounts/webSocketAccountSubscriber.d.ts.map +1 -1
- package/lib/accounts/webSocketAccountSubscriber.js +13 -3
- package/lib/clearingHouse.d.ts +4 -0
- package/lib/clearingHouse.d.ts.map +1 -1
- package/lib/clearingHouse.js +8 -0
- package/lib/clearingHouseUser.d.ts +31 -3
- package/lib/clearingHouseUser.d.ts.map +1 -1
- package/lib/clearingHouseUser.js +213 -47
- package/lib/constants/markets.d.ts.map +1 -1
- package/lib/constants/markets.js +21 -0
- package/lib/constants/numericConstants.d.ts +1 -0
- package/lib/constants/numericConstants.d.ts.map +1 -1
- package/lib/constants/numericConstants.js +2 -1
- package/lib/examples/makeTradeExample.d.ts.map +1 -1
- package/lib/examples/makeTradeExample.js +14 -13
- package/lib/idl/clearing_house.json +94 -42
- package/lib/index.d.ts +4 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4 -1
- package/lib/math/amm.d.ts +26 -1
- package/lib/math/amm.d.ts.map +1 -1
- package/lib/math/amm.js +85 -10
- package/lib/math/funding.d.ts +6 -6
- package/lib/math/funding.d.ts.map +1 -1
- package/lib/math/funding.js +41 -22
- package/lib/math/insuranceFund.d.ts +15 -0
- package/lib/math/insuranceFund.d.ts.map +1 -0
- package/lib/math/insuranceFund.js +36 -0
- package/lib/math/position.d.ts +1 -1
- package/lib/math/position.d.ts.map +1 -1
- package/lib/math/position.js +15 -23
- package/lib/math/trade.d.ts +1 -1
- package/lib/math/trade.d.ts.map +1 -1
- package/lib/math/trade.js +9 -4
- package/lib/types.d.ts +0 -13
- package/lib/types.d.ts.map +1 -1
- package/lib/util/computeUnits.d.ts +3 -0
- package/lib/util/computeUnits.d.ts.map +1 -0
- package/lib/util/computeUnits.js +27 -0
- package/lib/util/tps.d.ts +3 -0
- package/lib/util/tps.d.ts.map +1 -0
- package/lib/util/tps.js +27 -0
- package/lib/wallet.d.ts +10 -0
- package/lib/wallet.d.ts.map +1 -0
- package/lib/wallet.js +35 -0
- package/package.json +3 -13
- package/src/accounts/defaultClearingHouseAccountSubscriber.ts +18 -0
- package/src/accounts/defaultUserAccountSubscriber.ts +18 -0
- package/src/accounts/types.ts +3 -28
- package/src/accounts/webSocketAccountSubscriber.ts +16 -6
- package/src/clearingHouse.ts +9 -3
- package/src/clearingHouseUser.ts +306 -65
- package/src/constants/markets.ts +21 -0
- package/src/constants/numericConstants.ts +2 -0
- package/src/examples/makeTradeExample.ts +2 -1
- package/src/idl/clearing_house.json +94 -42
- package/src/index.ts +4 -1
- package/src/math/amm.ts +120 -13
- package/src/math/funding.ts +47 -25
- package/src/math/insuranceFund.ts +29 -0
- package/src/math/position.ts +16 -28
- package/src/math/trade.ts +9 -5
- package/src/types.ts +0 -14
- package/src/util/computeUnits.ts +21 -0
- package/src/util/tps.ts +27 -0
- package/src/wallet.ts +22 -0
- package/.eslintrc.json +0 -36
- package/.prettierignore +0 -1
- package/.prettierrc.js +0 -9
- package/lib/accounts/defaultHistoryAccountSubscriber.d.ts +0 -29
- package/lib/accounts/defaultHistoryAccountSubscriber.d.ts.map +0 -1
- package/lib/accounts/defaultHistoryAccountSubscriber.js +0 -110
- package/src/accounts/defaultHistoryAccountSubscriber.ts +0 -179
|
@@ -19,3 +19,5 @@ export const AMM_TO_QUOTE_PRECISION_RATIO =
|
|
|
19
19
|
AMM_RESERVE_PRECISION.div(QUOTE_PRECISION); // 10^7
|
|
20
20
|
export const PRICE_TO_QUOTE_PRECISION =
|
|
21
21
|
MARK_PRICE_PRECISION.div(QUOTE_PRECISION);
|
|
22
|
+
export const AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO =
|
|
23
|
+
AMM_RESERVE_PRECISION.mul(PEG_PRECISION).div(QUOTE_PRECISION); // 10^10
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { BN, Provider
|
|
1
|
+
import { BN, Provider } from '@project-serum/anchor';
|
|
2
|
+
import { Wallet } from '..';
|
|
2
3
|
import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
|
|
3
4
|
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
4
5
|
import {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "1.0.0",
|
|
3
3
|
"name": "clearing_house",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -156,11 +156,11 @@
|
|
|
156
156
|
"type": "u64"
|
|
157
157
|
},
|
|
158
158
|
{
|
|
159
|
-
"name": "
|
|
159
|
+
"name": "ammBaseAssetReserve",
|
|
160
160
|
"type": "u128"
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
|
-
"name": "
|
|
163
|
+
"name": "ammQuoteAssetReserve",
|
|
164
164
|
"type": "u128"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
@@ -759,7 +759,59 @@
|
|
|
759
759
|
},
|
|
760
760
|
{
|
|
761
761
|
"name": "authority",
|
|
762
|
+
"isMut": true,
|
|
763
|
+
"isSigner": true
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
"name": "rent",
|
|
767
|
+
"isMut": false,
|
|
768
|
+
"isSigner": false
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
"name": "systemProgram",
|
|
772
|
+
"isMut": false,
|
|
773
|
+
"isSigner": false
|
|
774
|
+
}
|
|
775
|
+
],
|
|
776
|
+
"args": [
|
|
777
|
+
{
|
|
778
|
+
"name": "userNonce",
|
|
779
|
+
"type": "u8"
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
"name": "optionalAccounts",
|
|
783
|
+
"type": {
|
|
784
|
+
"defined": "InitializeUserOptionalAccounts"
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
]
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
"name": "initializeUserWithExplicitPayer",
|
|
791
|
+
"accounts": [
|
|
792
|
+
{
|
|
793
|
+
"name": "user",
|
|
794
|
+
"isMut": true,
|
|
795
|
+
"isSigner": false
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
"name": "state",
|
|
762
799
|
"isMut": false,
|
|
800
|
+
"isSigner": false
|
|
801
|
+
},
|
|
802
|
+
{
|
|
803
|
+
"name": "userPositions",
|
|
804
|
+
"isMut": true,
|
|
805
|
+
"isSigner": true
|
|
806
|
+
},
|
|
807
|
+
{
|
|
808
|
+
"name": "authority",
|
|
809
|
+
"isMut": false,
|
|
810
|
+
"isSigner": true
|
|
811
|
+
},
|
|
812
|
+
{
|
|
813
|
+
"name": "payer",
|
|
814
|
+
"isMut": true,
|
|
763
815
|
"isSigner": true
|
|
764
816
|
},
|
|
765
817
|
{
|
|
@@ -2573,197 +2625,197 @@
|
|
|
2573
2625
|
],
|
|
2574
2626
|
"errors": [
|
|
2575
2627
|
{
|
|
2576
|
-
"code":
|
|
2628
|
+
"code": 6000,
|
|
2577
2629
|
"name": "InvalidCollateralAccountAuthority",
|
|
2578
2630
|
"msg": "Clearing house not collateral account owner"
|
|
2579
2631
|
},
|
|
2580
2632
|
{
|
|
2581
|
-
"code":
|
|
2633
|
+
"code": 6001,
|
|
2582
2634
|
"name": "InvalidInsuranceAccountAuthority",
|
|
2583
2635
|
"msg": "Clearing house not insurance account owner"
|
|
2584
2636
|
},
|
|
2585
2637
|
{
|
|
2586
|
-
"code":
|
|
2638
|
+
"code": 6002,
|
|
2587
2639
|
"name": "InsufficientDeposit",
|
|
2588
2640
|
"msg": "Insufficient deposit"
|
|
2589
2641
|
},
|
|
2590
2642
|
{
|
|
2591
|
-
"code":
|
|
2643
|
+
"code": 6003,
|
|
2592
2644
|
"name": "InsufficientCollateral",
|
|
2593
2645
|
"msg": "Insufficient collateral"
|
|
2594
2646
|
},
|
|
2595
2647
|
{
|
|
2596
|
-
"code":
|
|
2648
|
+
"code": 6004,
|
|
2597
2649
|
"name": "SufficientCollateral",
|
|
2598
2650
|
"msg": "Sufficient collateral"
|
|
2599
2651
|
},
|
|
2600
2652
|
{
|
|
2601
|
-
"code":
|
|
2653
|
+
"code": 6005,
|
|
2602
2654
|
"name": "MaxNumberOfPositions",
|
|
2603
2655
|
"msg": "Max number of positions taken"
|
|
2604
2656
|
},
|
|
2605
2657
|
{
|
|
2606
|
-
"code":
|
|
2658
|
+
"code": 6006,
|
|
2607
2659
|
"name": "AdminControlsPricesDisabled",
|
|
2608
2660
|
"msg": "Admin Controls Prices Disabled"
|
|
2609
2661
|
},
|
|
2610
2662
|
{
|
|
2611
|
-
"code":
|
|
2663
|
+
"code": 6007,
|
|
2612
2664
|
"name": "MarketIndexNotInitialized",
|
|
2613
2665
|
"msg": "Market Index Not Initialized"
|
|
2614
2666
|
},
|
|
2615
2667
|
{
|
|
2616
|
-
"code":
|
|
2668
|
+
"code": 6008,
|
|
2617
2669
|
"name": "MarketIndexAlreadyInitialized",
|
|
2618
2670
|
"msg": "Market Index Already Initialized"
|
|
2619
2671
|
},
|
|
2620
2672
|
{
|
|
2621
|
-
"code":
|
|
2673
|
+
"code": 6009,
|
|
2622
2674
|
"name": "UserAccountAndUserPositionsAccountMismatch",
|
|
2623
2675
|
"msg": "User Account And User Positions Account Mismatch"
|
|
2624
2676
|
},
|
|
2625
2677
|
{
|
|
2626
|
-
"code":
|
|
2678
|
+
"code": 6010,
|
|
2627
2679
|
"name": "UserHasNoPositionInMarket",
|
|
2628
2680
|
"msg": "User Has No Position In Market"
|
|
2629
2681
|
},
|
|
2630
2682
|
{
|
|
2631
|
-
"code":
|
|
2683
|
+
"code": 6011,
|
|
2632
2684
|
"name": "InvalidInitialPeg",
|
|
2633
2685
|
"msg": "Invalid Initial Peg"
|
|
2634
2686
|
},
|
|
2635
2687
|
{
|
|
2636
|
-
"code":
|
|
2688
|
+
"code": 6012,
|
|
2637
2689
|
"name": "InvalidRepegRedundant",
|
|
2638
2690
|
"msg": "AMM repeg already configured with amt given"
|
|
2639
2691
|
},
|
|
2640
2692
|
{
|
|
2641
|
-
"code":
|
|
2693
|
+
"code": 6013,
|
|
2642
2694
|
"name": "InvalidRepegDirection",
|
|
2643
2695
|
"msg": "AMM repeg incorrect repeg direction"
|
|
2644
2696
|
},
|
|
2645
2697
|
{
|
|
2646
|
-
"code":
|
|
2698
|
+
"code": 6014,
|
|
2647
2699
|
"name": "InvalidRepegProfitability",
|
|
2648
2700
|
"msg": "AMM repeg out of bounds pnl"
|
|
2649
2701
|
},
|
|
2650
2702
|
{
|
|
2651
|
-
"code":
|
|
2703
|
+
"code": 6015,
|
|
2652
2704
|
"name": "SlippageOutsideLimit",
|
|
2653
2705
|
"msg": "Slippage Outside Limit Price"
|
|
2654
2706
|
},
|
|
2655
2707
|
{
|
|
2656
|
-
"code":
|
|
2708
|
+
"code": 6016,
|
|
2657
2709
|
"name": "TradeSizeTooSmall",
|
|
2658
2710
|
"msg": "Trade Size Too Small"
|
|
2659
2711
|
},
|
|
2660
2712
|
{
|
|
2661
|
-
"code":
|
|
2713
|
+
"code": 6017,
|
|
2662
2714
|
"name": "InvalidUpdateK",
|
|
2663
2715
|
"msg": "Price change too large when updating K"
|
|
2664
2716
|
},
|
|
2665
2717
|
{
|
|
2666
|
-
"code":
|
|
2718
|
+
"code": 6018,
|
|
2667
2719
|
"name": "AdminWithdrawTooLarge",
|
|
2668
2720
|
"msg": "Admin tried to withdraw amount larger than fees collected"
|
|
2669
2721
|
},
|
|
2670
2722
|
{
|
|
2671
|
-
"code":
|
|
2723
|
+
"code": 6019,
|
|
2672
2724
|
"name": "MathError",
|
|
2673
2725
|
"msg": "Math Error"
|
|
2674
2726
|
},
|
|
2675
2727
|
{
|
|
2676
|
-
"code":
|
|
2728
|
+
"code": 6020,
|
|
2677
2729
|
"name": "BnConversionError",
|
|
2678
2730
|
"msg": "Conversion to u128/u64 failed with an overflow or underflow"
|
|
2679
2731
|
},
|
|
2680
2732
|
{
|
|
2681
|
-
"code":
|
|
2733
|
+
"code": 6021,
|
|
2682
2734
|
"name": "ClockUnavailable",
|
|
2683
2735
|
"msg": "Clock unavailable"
|
|
2684
2736
|
},
|
|
2685
2737
|
{
|
|
2686
|
-
"code":
|
|
2738
|
+
"code": 6022,
|
|
2687
2739
|
"name": "UnableToLoadOracle",
|
|
2688
2740
|
"msg": "Unable To Load Oracles"
|
|
2689
2741
|
},
|
|
2690
2742
|
{
|
|
2691
|
-
"code":
|
|
2743
|
+
"code": 6023,
|
|
2692
2744
|
"name": "OracleMarkSpreadLimit",
|
|
2693
2745
|
"msg": "Oracle/Mark Spread Too Large"
|
|
2694
2746
|
},
|
|
2695
2747
|
{
|
|
2696
|
-
"code":
|
|
2748
|
+
"code": 6024,
|
|
2697
2749
|
"name": "HistoryAlreadyInitialized",
|
|
2698
2750
|
"msg": "Clearing House history already initialized"
|
|
2699
2751
|
},
|
|
2700
2752
|
{
|
|
2701
|
-
"code":
|
|
2753
|
+
"code": 6025,
|
|
2702
2754
|
"name": "ExchangePaused",
|
|
2703
2755
|
"msg": "Exchange is paused"
|
|
2704
2756
|
},
|
|
2705
2757
|
{
|
|
2706
|
-
"code":
|
|
2758
|
+
"code": 6026,
|
|
2707
2759
|
"name": "InvalidWhitelistToken",
|
|
2708
2760
|
"msg": "Invalid whitelist token"
|
|
2709
2761
|
},
|
|
2710
2762
|
{
|
|
2711
|
-
"code":
|
|
2763
|
+
"code": 6027,
|
|
2712
2764
|
"name": "WhitelistTokenNotFound",
|
|
2713
2765
|
"msg": "Whitelist token not found"
|
|
2714
2766
|
},
|
|
2715
2767
|
{
|
|
2716
|
-
"code":
|
|
2768
|
+
"code": 6028,
|
|
2717
2769
|
"name": "InvalidDiscountToken",
|
|
2718
2770
|
"msg": "Invalid discount token"
|
|
2719
2771
|
},
|
|
2720
2772
|
{
|
|
2721
|
-
"code":
|
|
2773
|
+
"code": 6029,
|
|
2722
2774
|
"name": "DiscountTokenNotFound",
|
|
2723
2775
|
"msg": "Discount token not found"
|
|
2724
2776
|
},
|
|
2725
2777
|
{
|
|
2726
|
-
"code":
|
|
2778
|
+
"code": 6030,
|
|
2727
2779
|
"name": "InvalidReferrer",
|
|
2728
2780
|
"msg": "Invalid referrer"
|
|
2729
2781
|
},
|
|
2730
2782
|
{
|
|
2731
|
-
"code":
|
|
2783
|
+
"code": 6031,
|
|
2732
2784
|
"name": "ReferrerNotFound",
|
|
2733
2785
|
"msg": "Referrer not found"
|
|
2734
2786
|
},
|
|
2735
2787
|
{
|
|
2736
|
-
"code":
|
|
2788
|
+
"code": 6032,
|
|
2737
2789
|
"name": "InvalidOracle",
|
|
2738
2790
|
"msg": "InvalidOracle"
|
|
2739
2791
|
},
|
|
2740
2792
|
{
|
|
2741
|
-
"code":
|
|
2793
|
+
"code": 6033,
|
|
2742
2794
|
"name": "OracleNotFound",
|
|
2743
2795
|
"msg": "OracleNotFound"
|
|
2744
2796
|
},
|
|
2745
2797
|
{
|
|
2746
|
-
"code":
|
|
2798
|
+
"code": 6034,
|
|
2747
2799
|
"name": "LiquidationsBlockedByOracle",
|
|
2748
2800
|
"msg": "Liquidations Blocked By Oracle"
|
|
2749
2801
|
},
|
|
2750
2802
|
{
|
|
2751
|
-
"code":
|
|
2803
|
+
"code": 6035,
|
|
2752
2804
|
"name": "UserMaxDeposit",
|
|
2753
2805
|
"msg": "Can not deposit more than max deposit"
|
|
2754
2806
|
},
|
|
2755
2807
|
{
|
|
2756
|
-
"code":
|
|
2808
|
+
"code": 6036,
|
|
2757
2809
|
"name": "CantDeleteUserWithCollateral",
|
|
2758
2810
|
"msg": "Can not delete user that still has collateral"
|
|
2759
2811
|
},
|
|
2760
2812
|
{
|
|
2761
|
-
"code":
|
|
2813
|
+
"code": 6037,
|
|
2762
2814
|
"name": "InvalidFundingProfitability",
|
|
2763
2815
|
"msg": "AMM funding out of bounds pnl"
|
|
2764
2816
|
},
|
|
2765
2817
|
{
|
|
2766
|
-
"code":
|
|
2818
|
+
"code": 6038,
|
|
2767
2819
|
"name": "CastingFailure",
|
|
2768
2820
|
"msg": "Casting Failure"
|
|
2769
2821
|
}
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,6 @@ export * from './mockUSDCFaucet';
|
|
|
4
4
|
export * from './pythClient';
|
|
5
5
|
export * from './types';
|
|
6
6
|
export * from './constants/markets';
|
|
7
|
-
export * from './accounts/defaultHistoryAccountSubscriber';
|
|
8
7
|
export * from './accounts/defaultClearingHouseAccountSubscriber';
|
|
9
8
|
export * from './accounts/types';
|
|
10
9
|
export * from './addresses';
|
|
@@ -13,13 +12,17 @@ export * from './clearingHouseUser';
|
|
|
13
12
|
export * from './clearingHouse';
|
|
14
13
|
export * from './math/conversion';
|
|
15
14
|
export * from './math/funding';
|
|
15
|
+
export * from './math/insuranceFund';
|
|
16
16
|
export * from './math/market';
|
|
17
17
|
export * from './math/position';
|
|
18
18
|
export * from './math/amm';
|
|
19
19
|
export * from './math/trade';
|
|
20
|
+
export * from './wallet';
|
|
20
21
|
export * from './types';
|
|
21
22
|
export * from './math/utils';
|
|
22
23
|
export * from './config';
|
|
23
24
|
export * from './constants/numericConstants';
|
|
25
|
+
export * from './util/computeUnits';
|
|
26
|
+
export * from './util/tps';
|
|
24
27
|
|
|
25
28
|
export { BN };
|
package/src/math/amm.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
2
|
import {
|
|
3
|
+
AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO,
|
|
3
4
|
MARK_PRICE_PRECISION,
|
|
4
|
-
ONE,
|
|
5
5
|
PEG_PRECISION,
|
|
6
6
|
ZERO,
|
|
7
7
|
} from '../constants/numericConstants';
|
|
8
|
-
import {
|
|
8
|
+
import { calculateBaseAssetValue } from './position';
|
|
9
|
+
import { AMM, PositionDirection, SwapDirection, Market } from '../types';
|
|
9
10
|
import { assert } from '../assert/assert';
|
|
11
|
+
import { calculatePositionPNL, calculateMarkPrice, convertToNumber } from '..';
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* Calculates a price given an arbitrary base and quote amount (they must have the same precision)
|
|
@@ -55,17 +57,9 @@ export function calculateAmmReservesAfterSwap(
|
|
|
55
57
|
let newBaseAssetReserve;
|
|
56
58
|
|
|
57
59
|
if (inputAssetType === 'quote') {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
// Because ints round down by default, we need to add 1 back when removing from
|
|
62
|
-
// AMM to avoid giving users extra pnl when they short
|
|
63
|
-
const roundUp =
|
|
64
|
-
swapDirection === SwapDirection.REMOVE &&
|
|
65
|
-
!swapAmountIntermediate.mod(amm.pegMultiplier).eq(ZERO);
|
|
66
|
-
if (roundUp) {
|
|
67
|
-
swapAmount = swapAmount.add(ONE);
|
|
68
|
-
}
|
|
60
|
+
swapAmount = swapAmount
|
|
61
|
+
.mul(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO)
|
|
62
|
+
.div(amm.pegMultiplier);
|
|
69
63
|
|
|
70
64
|
[newQuoteAssetReserve, newBaseAssetReserve] = calculateSwapOutput(
|
|
71
65
|
amm.quoteAssetReserve,
|
|
@@ -136,3 +130,116 @@ export function getSwapDirection(
|
|
|
136
130
|
|
|
137
131
|
return SwapDirection.ADD;
|
|
138
132
|
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Helper function calculating adjust k cost
|
|
136
|
+
* @param market
|
|
137
|
+
* @param marketIndex
|
|
138
|
+
* @param numerator
|
|
139
|
+
* @param denomenator
|
|
140
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
141
|
+
*/
|
|
142
|
+
export function calculateAdjustKCost(
|
|
143
|
+
market: Market,
|
|
144
|
+
marketIndex: BN,
|
|
145
|
+
numerator: BN,
|
|
146
|
+
denomenator: BN
|
|
147
|
+
): BN {
|
|
148
|
+
const netUserPosition = {
|
|
149
|
+
baseAssetAmount: market.baseAssetAmount,
|
|
150
|
+
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
151
|
+
marketIndex: new BN(marketIndex),
|
|
152
|
+
quoteAssetAmount: new BN(0),
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
156
|
+
|
|
157
|
+
const marketNewK = Object.assign({}, market);
|
|
158
|
+
marketNewK.amm = Object.assign({}, market.amm);
|
|
159
|
+
|
|
160
|
+
marketNewK.amm.baseAssetReserve = market.amm.baseAssetReserve
|
|
161
|
+
.mul(numerator)
|
|
162
|
+
.div(denomenator);
|
|
163
|
+
marketNewK.amm.quoteAssetReserve = market.amm.quoteAssetReserve
|
|
164
|
+
.mul(numerator)
|
|
165
|
+
.div(denomenator);
|
|
166
|
+
marketNewK.amm.sqrtK = market.amm.sqrtK.mul(numerator).div(denomenator);
|
|
167
|
+
|
|
168
|
+
netUserPosition.quoteAssetAmount = currentValue;
|
|
169
|
+
|
|
170
|
+
const cost = calculatePositionPNL(marketNewK, netUserPosition);
|
|
171
|
+
|
|
172
|
+
return cost;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Helper function calculating adjust pegMultiplier (repeg) cost
|
|
177
|
+
*
|
|
178
|
+
* @param market
|
|
179
|
+
* @param marketIndex
|
|
180
|
+
* @param newPeg
|
|
181
|
+
* @returns cost : Precision QUOTE_ASSET_PRECISION
|
|
182
|
+
*/
|
|
183
|
+
export function calculateRepegCost(
|
|
184
|
+
market: Market,
|
|
185
|
+
marketIndex: BN,
|
|
186
|
+
newPeg: BN
|
|
187
|
+
): BN {
|
|
188
|
+
const netUserPosition = {
|
|
189
|
+
baseAssetAmount: market.baseAssetAmount,
|
|
190
|
+
lastCumulativeFundingRate: market.amm.cumulativeFundingRate,
|
|
191
|
+
marketIndex: new BN(marketIndex),
|
|
192
|
+
quoteAssetAmount: new BN(0),
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const currentValue = calculateBaseAssetValue(market, netUserPosition);
|
|
196
|
+
netUserPosition.quoteAssetAmount = currentValue;
|
|
197
|
+
const prevMarketPrice = calculateMarkPrice(market);
|
|
198
|
+
const marketNewPeg = Object.assign({}, market);
|
|
199
|
+
marketNewPeg.amm = Object.assign({}, market.amm);
|
|
200
|
+
|
|
201
|
+
// const marketNewPeg = JSON.parse(JSON.stringify(market));
|
|
202
|
+
marketNewPeg.amm.pegMultiplier = newPeg;
|
|
203
|
+
|
|
204
|
+
console.log(
|
|
205
|
+
'Price moves from',
|
|
206
|
+
convertToNumber(prevMarketPrice),
|
|
207
|
+
'to',
|
|
208
|
+
convertToNumber(calculateMarkPrice(marketNewPeg))
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
const cost = calculatePositionPNL(marketNewPeg, netUserPosition);
|
|
212
|
+
|
|
213
|
+
return cost;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Helper function calculating terminal price of amm
|
|
218
|
+
*
|
|
219
|
+
* @param market
|
|
220
|
+
* @returns cost : Precision MARK_PRICE_PRECISION
|
|
221
|
+
*/
|
|
222
|
+
export function calculateTerminalPrice(market: Market) {
|
|
223
|
+
if (!market.initialized) {
|
|
224
|
+
return new BN(0);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const directionToClose = market.baseAssetAmount.gt(ZERO)
|
|
228
|
+
? PositionDirection.SHORT
|
|
229
|
+
: PositionDirection.LONG;
|
|
230
|
+
|
|
231
|
+
const [newQuoteAssetReserve, newBaseAssetReserve] =
|
|
232
|
+
calculateAmmReservesAfterSwap(
|
|
233
|
+
market.amm,
|
|
234
|
+
'base',
|
|
235
|
+
market.baseAssetAmount.abs(),
|
|
236
|
+
getSwapDirection('base', directionToClose)
|
|
237
|
+
);
|
|
238
|
+
const terminalPrice = newQuoteAssetReserve
|
|
239
|
+
.mul(MARK_PRICE_PRECISION)
|
|
240
|
+
.mul(market.amm.pegMultiplier)
|
|
241
|
+
.div(PEG_PRECISION)
|
|
242
|
+
.div(newBaseAssetReserve);
|
|
243
|
+
|
|
244
|
+
return terminalPrice;
|
|
245
|
+
}
|
package/src/math/funding.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
|
+
import { PriceData } from '@pythnetwork/client';
|
|
2
3
|
import {
|
|
3
4
|
AMM_RESERVE_PRECISION,
|
|
4
5
|
MARK_PRICE_PRECISION,
|
|
5
6
|
QUOTE_PRECISION,
|
|
6
7
|
ZERO,
|
|
7
8
|
} from '../constants/numericConstants';
|
|
8
|
-
import { PythClient } from '../pythClient';
|
|
9
9
|
import { Market } from '../types';
|
|
10
10
|
import { calculateMarkPrice } from './market';
|
|
11
11
|
|
|
@@ -18,7 +18,7 @@ import { calculateMarkPrice } from './market';
|
|
|
18
18
|
*/
|
|
19
19
|
export async function calculateAllEstimatedFundingRate(
|
|
20
20
|
market: Market,
|
|
21
|
-
|
|
21
|
+
oraclePriceData: PriceData,
|
|
22
22
|
periodAdjustment: BN = new BN(1)
|
|
23
23
|
): Promise<[BN, BN, BN, BN, BN]> {
|
|
24
24
|
// periodAdjustment
|
|
@@ -64,16 +64,40 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
64
64
|
secondsInHour,
|
|
65
65
|
secondsInHour.sub(timeSinceLastOracleTwapUpdate)
|
|
66
66
|
);
|
|
67
|
-
|
|
67
|
+
|
|
68
|
+
// verify pyth input is positive for live update
|
|
69
|
+
let oracleStablePriceNum = 0;
|
|
70
|
+
let oracleInputCount = 0;
|
|
71
|
+
if (oraclePriceData.price >= 0) {
|
|
72
|
+
oracleStablePriceNum += oraclePriceData.price;
|
|
73
|
+
oracleInputCount += 1;
|
|
74
|
+
}
|
|
75
|
+
if (oraclePriceData.previousPrice >= 0) {
|
|
76
|
+
oracleStablePriceNum += oraclePriceData.previousPrice;
|
|
77
|
+
oracleInputCount += 1;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
oracleStablePriceNum = oracleStablePriceNum / oracleInputCount;
|
|
68
81
|
const oraclePriceStableWithMantissa = new BN(
|
|
69
|
-
|
|
70
|
-
MARK_PRICE_PRECISION.toNumber()
|
|
82
|
+
oracleStablePriceNum * MARK_PRICE_PRECISION.toNumber()
|
|
71
83
|
);
|
|
72
84
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
.
|
|
85
|
+
let oracleTwapWithMantissa = lastOracleTwapWithMantissa;
|
|
86
|
+
|
|
87
|
+
const oracleLiveVsTwap = oraclePriceStableWithMantissa
|
|
88
|
+
.sub(lastOracleTwapWithMantissa)
|
|
89
|
+
.abs()
|
|
90
|
+
.mul(MARK_PRICE_PRECISION)
|
|
91
|
+
.mul(new BN(100))
|
|
92
|
+
.div(lastOracleTwapWithMantissa);
|
|
93
|
+
|
|
94
|
+
// verify pyth live input is within 10% of last twap for live update
|
|
95
|
+
if (oracleLiveVsTwap.lte(MARK_PRICE_PRECISION.mul(new BN(10)))) {
|
|
96
|
+
oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
|
|
97
|
+
.mul(lastOracleTwapWithMantissa)
|
|
98
|
+
.add(timeSinceLastMarkChange.mul(oraclePriceStableWithMantissa))
|
|
99
|
+
.div(timeSinceLastOracleTwapUpdate.add(oracleTwapTimeSinceLastUpdate));
|
|
100
|
+
}
|
|
77
101
|
|
|
78
102
|
const twapSpread = markTwapWithMantissa.sub(oracleTwapWithMantissa);
|
|
79
103
|
|
|
@@ -139,22 +163,20 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
139
163
|
}
|
|
140
164
|
|
|
141
165
|
if (largerSide.gt(ZERO)) {
|
|
142
|
-
|
|
143
|
-
|
|
166
|
+
// funding smaller flow
|
|
167
|
+
cappedAltEst = smallerSide.mul(twapSpread).div(hoursInDay);
|
|
144
168
|
const feePoolTopOff = feePoolSize
|
|
145
169
|
.mul(MARK_PRICE_PRECISION.div(QUOTE_PRECISION))
|
|
146
|
-
.mul(AMM_RESERVE_PRECISION)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
cappedAltEst = cappedAltEst.add(feePoolTopOff);
|
|
170
|
+
.mul(AMM_RESERVE_PRECISION);
|
|
171
|
+
cappedAltEst = cappedAltEst.add(feePoolTopOff).div(largerSide);
|
|
150
172
|
|
|
151
173
|
cappedAltEst = cappedAltEst
|
|
152
174
|
.mul(MARK_PRICE_PRECISION)
|
|
153
175
|
.mul(new BN(100))
|
|
154
176
|
.div(oracleTwapWithMantissa)
|
|
155
|
-
.mul(periodAdjustment)
|
|
156
|
-
|
|
157
|
-
if (cappedAltEst.abs().
|
|
177
|
+
.mul(periodAdjustment);
|
|
178
|
+
|
|
179
|
+
if (cappedAltEst.abs().gte(interpEst.abs())) {
|
|
158
180
|
cappedAltEst = interpEst;
|
|
159
181
|
}
|
|
160
182
|
} else {
|
|
@@ -173,21 +195,21 @@ export async function calculateAllEstimatedFundingRate(
|
|
|
173
195
|
/**
|
|
174
196
|
*
|
|
175
197
|
* @param market
|
|
176
|
-
* @param
|
|
198
|
+
* @param oraclePriceData
|
|
177
199
|
* @param periodAdjustment
|
|
178
200
|
* @param estimationMethod
|
|
179
201
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
180
202
|
*/
|
|
181
203
|
export async function calculateEstimatedFundingRate(
|
|
182
204
|
market: Market,
|
|
183
|
-
|
|
205
|
+
oraclePriceData: PriceData,
|
|
184
206
|
periodAdjustment: BN = new BN(1),
|
|
185
207
|
estimationMethod: 'interpolated' | 'lowerbound' | 'capped'
|
|
186
208
|
): Promise<BN> {
|
|
187
209
|
const [_1, _2, lowerboundEst, cappedAltEst, interpEst] =
|
|
188
210
|
await calculateAllEstimatedFundingRate(
|
|
189
211
|
market,
|
|
190
|
-
|
|
212
|
+
oraclePriceData,
|
|
191
213
|
periodAdjustment
|
|
192
214
|
);
|
|
193
215
|
|
|
@@ -211,13 +233,13 @@ export async function calculateEstimatedFundingRate(
|
|
|
211
233
|
*/
|
|
212
234
|
export async function calculateLongShortFundingRate(
|
|
213
235
|
market: Market,
|
|
214
|
-
|
|
236
|
+
oraclePriceData: PriceData,
|
|
215
237
|
periodAdjustment: BN = new BN(1)
|
|
216
238
|
): Promise<[BN, BN]> {
|
|
217
239
|
const [_1, _2, _, cappedAltEst, interpEst] =
|
|
218
240
|
await calculateAllEstimatedFundingRate(
|
|
219
241
|
market,
|
|
220
|
-
|
|
242
|
+
oraclePriceData,
|
|
221
243
|
periodAdjustment
|
|
222
244
|
);
|
|
223
245
|
|
|
@@ -240,13 +262,13 @@ export async function calculateLongShortFundingRate(
|
|
|
240
262
|
*/
|
|
241
263
|
export async function calculateLongShortFundingRateAndLiveTwaps(
|
|
242
264
|
market: Market,
|
|
243
|
-
|
|
265
|
+
oraclePriceData: PriceData,
|
|
244
266
|
periodAdjustment: BN = new BN(1)
|
|
245
267
|
): Promise<[BN, BN, BN, BN]> {
|
|
246
268
|
const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] =
|
|
247
269
|
await calculateAllEstimatedFundingRate(
|
|
248
270
|
market,
|
|
249
|
-
|
|
271
|
+
oraclePriceData,
|
|
250
272
|
periodAdjustment
|
|
251
273
|
);
|
|
252
274
|
|