@drift-labs/sdk 0.1.6 → 0.1.10
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/.eslintrc.json +36 -0
- package/.prettierignore +1 -0
- package/.prettierrc.js +9 -0
- package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts +1 -0
- package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts.map +1 -0
- package/lib/accounts/defaultHistoryAccountSubscriber.d.ts +1 -0
- package/lib/accounts/defaultHistoryAccountSubscriber.d.ts.map +1 -0
- package/lib/accounts/defaultUserAccountSubscriber.d.ts +1 -0
- package/lib/accounts/defaultUserAccountSubscriber.d.ts.map +1 -0
- package/lib/accounts/types.d.ts +1 -0
- package/lib/accounts/types.d.ts.map +1 -0
- package/lib/accounts/webSocketAccountSubscriber.d.ts +1 -0
- package/lib/accounts/webSocketAccountSubscriber.d.ts.map +1 -0
- package/lib/addresses.d.ts +1 -0
- package/lib/addresses.d.ts.map +1 -0
- package/lib/admin.d.ts +2 -1
- package/lib/admin.d.ts.map +1 -0
- package/lib/admin.js +2 -2
- package/lib/assert/assert.d.ts +1 -0
- package/lib/assert/assert.d.ts.map +1 -0
- package/lib/clearingHouse.d.ts +1 -0
- package/lib/clearingHouse.d.ts.map +1 -0
- package/lib/clearingHouseUser.d.ts +2 -1
- package/lib/clearingHouseUser.d.ts.map +1 -0
- package/lib/clearingHouseUser.js +20 -3
- package/lib/config.d.ts +1 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +1 -1
- package/lib/constants/markets.d.ts +1 -0
- package/lib/constants/markets.d.ts.map +1 -0
- package/lib/constants/markets.js +28 -21
- package/lib/constants/numericConstants.d.ts +1 -0
- package/lib/constants/numericConstants.d.ts.map +1 -0
- package/lib/examples/makeTradeExample.d.ts +1 -0
- package/lib/examples/makeTradeExample.d.ts.map +1 -0
- package/lib/idl/clearing_house.json +39 -30
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/math/amm.d.ts +1 -0
- package/lib/math/amm.d.ts.map +1 -0
- package/lib/math/conversion.d.ts +1 -0
- package/lib/math/conversion.d.ts.map +1 -0
- package/lib/math/funding.d.ts +34 -1
- package/lib/math/funding.d.ts.map +1 -0
- package/lib/math/funding.js +152 -15
- package/lib/math/market.d.ts +1 -0
- package/lib/math/market.d.ts.map +1 -0
- package/lib/math/position.d.ts +1 -0
- package/lib/math/position.d.ts.map +1 -0
- package/lib/math/trade.d.ts +5 -3
- package/lib/math/trade.d.ts.map +1 -0
- package/lib/math/trade.js +5 -4
- package/lib/math/utils.d.ts +1 -0
- package/lib/math/utils.d.ts.map +1 -0
- package/lib/mockUSDCFaucet.d.ts +1 -0
- package/lib/mockUSDCFaucet.d.ts.map +1 -0
- package/lib/pythClient.d.ts +1 -0
- package/lib/pythClient.d.ts.map +1 -0
- package/lib/tx/defaultTxSender.d.ts +1 -0
- package/lib/tx/defaultTxSender.d.ts.map +1 -0
- package/lib/tx/types.d.ts +1 -0
- package/lib/tx/types.d.ts.map +1 -0
- package/lib/tx/utils.d.ts +1 -0
- package/lib/tx/utils.d.ts.map +1 -0
- package/lib/types.d.ts +11 -1
- package/lib/types.d.ts.map +1 -0
- package/package.json +12 -2
- package/src/admin.ts +4 -4
- package/src/clearingHouse.ts +12 -12
- package/src/clearingHouseUser.ts +27 -4
- package/src/config.ts +1 -2
- package/src/constants/markets.ts +28 -21
- package/src/idl/clearing_house.json +39 -30
- package/src/math/funding.ts +189 -29
- package/src/math/position.ts +3 -3
- package/src/math/trade.ts +14 -8
- package/src/types.ts +10 -1
- package/tsconfig.json +2 -1
package/src/constants/markets.ts
CHANGED
|
@@ -16,25 +16,32 @@ export const Markets: Market[] = [
|
|
|
16
16
|
devnetPythOracle: 'J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix',
|
|
17
17
|
mainnetPythOracle: 'H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG',
|
|
18
18
|
},
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
19
|
+
{
|
|
20
|
+
symbol: 'BTC-PERP',
|
|
21
|
+
baseAssetSymbol: 'BTC',
|
|
22
|
+
marketIndex: new BN(1),
|
|
23
|
+
devnetPythOracle: 'HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J',
|
|
24
|
+
mainnetPythOracle: 'GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
symbol: 'ETH-PERP',
|
|
28
|
+
baseAssetSymbol: 'ETH',
|
|
29
|
+
marketIndex: new BN(2),
|
|
30
|
+
devnetPythOracle: 'EdVCmQ9FSPcVe5YySXDPCRmc8aDQLKJ9xvYBMZPie1Vw',
|
|
31
|
+
mainnetPythOracle: 'JBu1AL4obBcCMqKBBxhpWCNUt136ijcuMZLFvTP7iWdB',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
symbol: 'LUNA-PERP',
|
|
35
|
+
baseAssetSymbol: 'LUNA',
|
|
36
|
+
marketIndex: new BN(3),
|
|
37
|
+
devnetPythOracle: '8PugCXTAHLM9kfLSQWe2njE5pzAgUdpPk3Nx5zSm7BD3',
|
|
38
|
+
mainnetPythOracle: '5bmWuR1dgP4avtGYMNKLuxumZTVKGgoN2BCMXWDNL9nY',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
symbol: 'AVAX-PERP',
|
|
42
|
+
baseAssetSymbol: 'AVAX',
|
|
43
|
+
marketIndex: new BN(4),
|
|
44
|
+
devnetPythOracle: 'FVb5h1VmHPfVb1RfqZckchq18GxRv4iKt8T4eVTQAqdz',
|
|
45
|
+
mainnetPythOracle: 'Ax9ujW5B9oqcv59N8m6f1BpTBq2rGeGaBcpKjC5UYsXU',
|
|
46
|
+
},
|
|
40
47
|
];
|
|
@@ -1724,6 +1724,34 @@
|
|
|
1724
1724
|
}
|
|
1725
1725
|
],
|
|
1726
1726
|
"types": [
|
|
1727
|
+
{
|
|
1728
|
+
"name": "InitializeUserOptionalAccounts",
|
|
1729
|
+
"type": {
|
|
1730
|
+
"kind": "struct",
|
|
1731
|
+
"fields": [
|
|
1732
|
+
{
|
|
1733
|
+
"name": "whitelistToken",
|
|
1734
|
+
"type": "bool"
|
|
1735
|
+
}
|
|
1736
|
+
]
|
|
1737
|
+
}
|
|
1738
|
+
},
|
|
1739
|
+
{
|
|
1740
|
+
"name": "ManagePositionOptionalAccounts",
|
|
1741
|
+
"type": {
|
|
1742
|
+
"kind": "struct",
|
|
1743
|
+
"fields": [
|
|
1744
|
+
{
|
|
1745
|
+
"name": "discountToken",
|
|
1746
|
+
"type": "bool"
|
|
1747
|
+
},
|
|
1748
|
+
{
|
|
1749
|
+
"name": "referrer",
|
|
1750
|
+
"type": "bool"
|
|
1751
|
+
}
|
|
1752
|
+
]
|
|
1753
|
+
}
|
|
1754
|
+
},
|
|
1727
1755
|
{
|
|
1728
1756
|
"name": "CurveRecord",
|
|
1729
1757
|
"type": {
|
|
@@ -1938,34 +1966,6 @@
|
|
|
1938
1966
|
]
|
|
1939
1967
|
}
|
|
1940
1968
|
},
|
|
1941
|
-
{
|
|
1942
|
-
"name": "InitializeUserOptionalAccounts",
|
|
1943
|
-
"type": {
|
|
1944
|
-
"kind": "struct",
|
|
1945
|
-
"fields": [
|
|
1946
|
-
{
|
|
1947
|
-
"name": "whitelistToken",
|
|
1948
|
-
"type": "bool"
|
|
1949
|
-
}
|
|
1950
|
-
]
|
|
1951
|
-
}
|
|
1952
|
-
},
|
|
1953
|
-
{
|
|
1954
|
-
"name": "ManagePositionOptionalAccounts",
|
|
1955
|
-
"type": {
|
|
1956
|
-
"kind": "struct",
|
|
1957
|
-
"fields": [
|
|
1958
|
-
{
|
|
1959
|
-
"name": "discountToken",
|
|
1960
|
-
"type": "bool"
|
|
1961
|
-
},
|
|
1962
|
-
{
|
|
1963
|
-
"name": "referrer",
|
|
1964
|
-
"type": "bool"
|
|
1965
|
-
}
|
|
1966
|
-
]
|
|
1967
|
-
}
|
|
1968
|
-
},
|
|
1969
1969
|
{
|
|
1970
1970
|
"name": "LiquidationRecord",
|
|
1971
1971
|
"type": {
|
|
@@ -2140,7 +2140,7 @@
|
|
|
2140
2140
|
"type": "i64"
|
|
2141
2141
|
},
|
|
2142
2142
|
{
|
|
2143
|
-
"name": "
|
|
2143
|
+
"name": "lastOraclePriceTwap",
|
|
2144
2144
|
"type": "i128"
|
|
2145
2145
|
},
|
|
2146
2146
|
{
|
|
@@ -2175,9 +2175,13 @@
|
|
|
2175
2175
|
"name": "minimumTradeSize",
|
|
2176
2176
|
"type": "u128"
|
|
2177
2177
|
},
|
|
2178
|
+
{
|
|
2179
|
+
"name": "lastOraclePriceTwapTs",
|
|
2180
|
+
"type": "i64"
|
|
2181
|
+
},
|
|
2178
2182
|
{
|
|
2179
2183
|
"name": "padding0",
|
|
2180
|
-
"type": "
|
|
2184
|
+
"type": "u64"
|
|
2181
2185
|
},
|
|
2182
2186
|
{
|
|
2183
2187
|
"name": "padding1",
|
|
@@ -2757,6 +2761,11 @@
|
|
|
2757
2761
|
"code": 337,
|
|
2758
2762
|
"name": "InvalidFundingProfitability",
|
|
2759
2763
|
"msg": "AMM funding out of bounds pnl"
|
|
2764
|
+
},
|
|
2765
|
+
{
|
|
2766
|
+
"code": 338,
|
|
2767
|
+
"name": "CastingFailure",
|
|
2768
|
+
"msg": "Casting Failure"
|
|
2760
2769
|
}
|
|
2761
2770
|
]
|
|
2762
2771
|
}
|
package/src/math/funding.ts
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
|
+
import {
|
|
3
|
+
AMM_RESERVE_PRECISION,
|
|
4
|
+
MARK_PRICE_PRECISION,
|
|
5
|
+
QUOTE_PRECISION,
|
|
6
|
+
ZERO,
|
|
7
|
+
} from '../constants/numericConstants';
|
|
2
8
|
import { PythClient } from '../pythClient';
|
|
3
|
-
import { MARK_PRICE_PRECISION } from '../constants/numericConstants';
|
|
4
9
|
import { Market } from '../types';
|
|
5
10
|
import { calculateMarkPrice } from './market';
|
|
6
11
|
|
|
7
12
|
/**
|
|
8
|
-
*
|
|
9
|
-
* @param market
|
|
10
|
-
* @param pythClient
|
|
11
|
-
* @param periodAdjustment
|
|
12
|
-
* @param estimationMethod
|
|
13
|
+
*
|
|
14
|
+
* @param market
|
|
15
|
+
* @param pythClient
|
|
16
|
+
* @param periodAdjustment
|
|
13
17
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
14
18
|
*/
|
|
15
|
-
export async function
|
|
19
|
+
export async function calculateAllEstimatedFundingRate(
|
|
16
20
|
market: Market,
|
|
17
21
|
pythClient: PythClient,
|
|
18
|
-
periodAdjustment: BN = new BN(1)
|
|
19
|
-
|
|
20
|
-
): Promise<BN> {
|
|
22
|
+
periodAdjustment: BN = new BN(1)
|
|
23
|
+
): Promise<[BN, BN, BN, BN, BN]> {
|
|
21
24
|
// periodAdjustment
|
|
22
25
|
// 1: hourly
|
|
23
26
|
// 24: daily
|
|
@@ -26,34 +29,43 @@ export async function calculateEstimatedFundingRate(
|
|
|
26
29
|
const hoursInDay = new BN(24);
|
|
27
30
|
|
|
28
31
|
if (!market.initialized) {
|
|
29
|
-
return
|
|
32
|
+
return [ZERO, ZERO, ZERO, ZERO, ZERO];
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
const payFreq = new BN(market.amm.fundingPeriod);
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
const oracleTwapWithMantissa = new BN(
|
|
36
|
-
oraclePriceData.twap.value * MARK_PRICE_PRECISION.toNumber()
|
|
37
|
-
);
|
|
38
|
-
|
|
37
|
+
// todo: sufficiently differs from blockchain timestamp?
|
|
39
38
|
const now = new BN((Date.now() / 1000).toFixed(0));
|
|
40
39
|
const timeSinceLastUpdate = now.sub(market.amm.lastFundingRateTs);
|
|
41
40
|
|
|
41
|
+
// calculate real-time mark twap
|
|
42
42
|
const lastMarkTwapWithMantissa = market.amm.lastMarkPriceTwap;
|
|
43
43
|
const lastMarkPriceTwapTs = market.amm.lastMarkPriceTwapTs;
|
|
44
44
|
|
|
45
45
|
const timeSinceLastMarkChange = now.sub(lastMarkPriceTwapTs);
|
|
46
|
-
const markTwapTimeSinceLastUpdate =
|
|
47
|
-
market.amm.lastFundingRateTs
|
|
48
|
-
);
|
|
49
|
-
|
|
46
|
+
const markTwapTimeSinceLastUpdate = BN.max(secondsInHour, secondsInHour.sub(timeSinceLastMarkChange));
|
|
50
47
|
const baseAssetPriceWithMantissa = calculateMarkPrice(market);
|
|
51
|
-
|
|
48
|
+
|
|
52
49
|
const markTwapWithMantissa = markTwapTimeSinceLastUpdate
|
|
53
50
|
.mul(lastMarkTwapWithMantissa)
|
|
54
51
|
.add(timeSinceLastMarkChange.mul(baseAssetPriceWithMantissa))
|
|
55
52
|
.div(timeSinceLastMarkChange.add(markTwapTimeSinceLastUpdate));
|
|
56
53
|
|
|
54
|
+
// calculate real-time (predicted) oracle twap
|
|
55
|
+
// note: oracle twap depends on `when the chord is struck` (market is trade)
|
|
56
|
+
const lastOracleTwapWithMantissa = market.amm.lastOraclePriceTwap;
|
|
57
|
+
const lastOraclePriceTwapTs = market.amm.lastOraclePriceTwapTs;
|
|
58
|
+
|
|
59
|
+
const timeSinceLastOracleTwapUpdate = now.sub(lastOraclePriceTwapTs);
|
|
60
|
+
const oracleTwapTimeSinceLastUpdate = BN.max(secondsInHour, secondsInHour.sub(timeSinceLastOracleTwapUpdate));
|
|
61
|
+
const oraclePriceData = await pythClient.getPriceData(market.amm.oracle);
|
|
62
|
+
const oraclePriceStableWithMantissa = new BN(((oraclePriceData.price + oraclePriceData.previousPrice)/2) * MARK_PRICE_PRECISION.toNumber());
|
|
63
|
+
|
|
64
|
+
const oracleTwapWithMantissa = oracleTwapTimeSinceLastUpdate
|
|
65
|
+
.mul(lastOracleTwapWithMantissa)
|
|
66
|
+
.add(timeSinceLastMarkChange.mul(oraclePriceStableWithMantissa))
|
|
67
|
+
.div(timeSinceLastOracleTwapUpdate.add(oracleTwapTimeSinceLastUpdate));
|
|
68
|
+
|
|
57
69
|
const twapSpread = markTwapWithMantissa.sub(oracleTwapWithMantissa);
|
|
58
70
|
|
|
59
71
|
const twapSpreadPct = twapSpread
|
|
@@ -61,16 +73,164 @@ export async function calculateEstimatedFundingRate(
|
|
|
61
73
|
.mul(new BN(100))
|
|
62
74
|
.div(oracleTwapWithMantissa);
|
|
63
75
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
const lowerboundEst = twapSpreadPct
|
|
77
|
+
.mul(payFreq)
|
|
78
|
+
.mul(BN.min(secondsInHour, timeSinceLastUpdate))
|
|
79
|
+
.mul(periodAdjustment)
|
|
80
|
+
.div(secondsInHour)
|
|
81
|
+
.div(secondsInHour)
|
|
82
|
+
.div(hoursInDay);
|
|
83
|
+
|
|
84
|
+
const interpEst = twapSpreadPct.mul(periodAdjustment).div(hoursInDay);
|
|
85
|
+
|
|
86
|
+
const interpRateQuote = twapSpreadPct
|
|
87
|
+
.mul(periodAdjustment)
|
|
88
|
+
.div(hoursInDay)
|
|
89
|
+
.div(MARK_PRICE_PRECISION.div(QUOTE_PRECISION));
|
|
90
|
+
let feePoolSize = calculateFundingPool(market);
|
|
91
|
+
if (interpRateQuote.lt(new BN(0))) {
|
|
92
|
+
feePoolSize = feePoolSize.mul(new BN(-1));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let cappedAltEst: BN;
|
|
96
|
+
let largerSide: BN;
|
|
97
|
+
let smallerSide: BN;
|
|
98
|
+
if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())) {
|
|
99
|
+
largerSide = market.baseAssetAmountLong.abs();
|
|
100
|
+
smallerSide = market.baseAssetAmountShort.abs();
|
|
101
|
+
if(twapSpread.gt(new BN(0))) {
|
|
102
|
+
return [markTwapWithMantissa, oracleTwapWithMantissa, lowerboundEst, interpEst, interpEst];
|
|
103
|
+
}
|
|
104
|
+
} else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())) {
|
|
105
|
+
largerSide = market.baseAssetAmountShort.abs();
|
|
106
|
+
smallerSide = market.baseAssetAmountLong.abs();
|
|
107
|
+
if(twapSpread.lt(new BN(0))){
|
|
108
|
+
return [markTwapWithMantissa, oracleTwapWithMantissa, lowerboundEst, interpEst, interpEst];
|
|
109
|
+
}
|
|
110
|
+
} else{
|
|
111
|
+
return [markTwapWithMantissa, oracleTwapWithMantissa, lowerboundEst, interpEst, interpEst];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (largerSide.gt(ZERO)) {
|
|
115
|
+
cappedAltEst = smallerSide.mul(twapSpread).div(largerSide);
|
|
116
|
+
|
|
117
|
+
const feePoolTopOff = feePoolSize
|
|
118
|
+
.mul(MARK_PRICE_PRECISION.div(QUOTE_PRECISION))
|
|
119
|
+
.mul(AMM_RESERVE_PRECISION)
|
|
120
|
+
.div(largerSide);
|
|
121
|
+
|
|
122
|
+
cappedAltEst = cappedAltEst.add(feePoolTopOff);
|
|
123
|
+
|
|
124
|
+
cappedAltEst = cappedAltEst
|
|
125
|
+
.mul(MARK_PRICE_PRECISION)
|
|
126
|
+
.mul(new BN(100))
|
|
127
|
+
.div(oracleTwapWithMantissa)
|
|
69
128
|
.mul(periodAdjustment)
|
|
70
|
-
.div(secondsInHour)
|
|
71
|
-
.div(secondsInHour)
|
|
72
129
|
.div(hoursInDay);
|
|
130
|
+
if (cappedAltEst.abs().gt(interpEst.abs())) {
|
|
131
|
+
cappedAltEst = interpEst;
|
|
132
|
+
}
|
|
73
133
|
} else {
|
|
74
|
-
|
|
134
|
+
cappedAltEst = interpEst;
|
|
75
135
|
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
return [markTwapWithMantissa, oracleTwapWithMantissa, lowerboundEst, cappedAltEst, interpEst];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
*
|
|
143
|
+
* @param market
|
|
144
|
+
* @param pythClient
|
|
145
|
+
* @param periodAdjustment
|
|
146
|
+
* @param estimationMethod
|
|
147
|
+
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
148
|
+
*/
|
|
149
|
+
export async function calculateEstimatedFundingRate(
|
|
150
|
+
market: Market,
|
|
151
|
+
pythClient: PythClient,
|
|
152
|
+
periodAdjustment: BN = new BN(1),
|
|
153
|
+
estimationMethod: 'interpolated' | 'lowerbound' | 'capped'
|
|
154
|
+
): Promise<BN> {
|
|
155
|
+
const [_1, _2, lowerboundEst, cappedAltEst, interpEst] =
|
|
156
|
+
await calculateAllEstimatedFundingRate(
|
|
157
|
+
market,
|
|
158
|
+
pythClient,
|
|
159
|
+
periodAdjustment
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
if (estimationMethod == 'lowerbound') {
|
|
163
|
+
//assuming remaining funding period has no gap
|
|
164
|
+
return lowerboundEst;
|
|
165
|
+
} else if (estimationMethod == 'capped') {
|
|
166
|
+
return cappedAltEst;
|
|
167
|
+
} else {
|
|
168
|
+
return interpEst;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
*
|
|
174
|
+
* @param market
|
|
175
|
+
* @param pythClient
|
|
176
|
+
* @param periodAdjustment
|
|
177
|
+
* @param estimationMethod
|
|
178
|
+
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
179
|
+
*/
|
|
180
|
+
export async function calculateLongShortFundingRate(
|
|
181
|
+
market: Market,
|
|
182
|
+
pythClient: PythClient,
|
|
183
|
+
periodAdjustment: BN = new BN(1)
|
|
184
|
+
): Promise<[BN, BN]> {
|
|
185
|
+
const [_1, _2, _, cappedAltEst, interpEst] = await calculateAllEstimatedFundingRate(
|
|
186
|
+
market,
|
|
187
|
+
pythClient,
|
|
188
|
+
periodAdjustment
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort)) {
|
|
192
|
+
return [cappedAltEst, interpEst];
|
|
193
|
+
} else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort)) {
|
|
194
|
+
return [interpEst, cappedAltEst];
|
|
195
|
+
} else {
|
|
196
|
+
return [interpEst, interpEst];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
*
|
|
202
|
+
* @param market
|
|
203
|
+
* @param pythClient
|
|
204
|
+
* @param periodAdjustment
|
|
205
|
+
* @param estimationMethod
|
|
206
|
+
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
207
|
+
*/
|
|
208
|
+
export async function calculateLongShortFundingRateAndLiveTwaps(
|
|
209
|
+
market: Market,
|
|
210
|
+
pythClient: PythClient,
|
|
211
|
+
periodAdjustment: BN = new BN(1),
|
|
212
|
+
): Promise<[BN, BN, BN, BN]> {
|
|
213
|
+
const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] =
|
|
214
|
+
await calculateAllEstimatedFundingRate(market, pythClient, periodAdjustment);
|
|
215
|
+
|
|
216
|
+
if(market.baseAssetAmountLong.gt(market.baseAssetAmountShort.abs())){
|
|
217
|
+
return [markTwapLive, oracleTwapLive, cappedAltEst, interpEst];
|
|
218
|
+
} else if(market.baseAssetAmountLong.lt(market.baseAssetAmountShort.abs())){
|
|
219
|
+
return [markTwapLive, oracleTwapLive, interpEst, cappedAltEst];
|
|
220
|
+
} else{
|
|
221
|
+
return [markTwapLive, oracleTwapLive, interpEst, interpEst];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
*
|
|
228
|
+
* @param market
|
|
229
|
+
* @returns Estimated fee pool size
|
|
230
|
+
*/
|
|
231
|
+
export function calculateFundingPool(market: Market): BN {
|
|
232
|
+
// todo
|
|
233
|
+
const totalFeeLB = market.amm.totalFee.div(new BN(2));
|
|
234
|
+
const feePool = market.amm.totalFeeMinusDistributions.sub(totalFeeLB);
|
|
235
|
+
return feePool;
|
|
76
236
|
}
|
package/src/math/position.ts
CHANGED
|
@@ -102,9 +102,9 @@ export function calculatePositionPNL(
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
*
|
|
106
|
-
* @param market
|
|
107
|
-
* @param marketPosition
|
|
105
|
+
*
|
|
106
|
+
* @param market
|
|
107
|
+
* @param marketPosition
|
|
108
108
|
* @returns // TODO-PRECISION
|
|
109
109
|
*/
|
|
110
110
|
export function calculatePositionFundingPNL(
|
package/src/math/trade.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
calculateAmmReservesAfterSwap,
|
|
13
13
|
calculatePrice,
|
|
14
14
|
getSwapDirection,
|
|
15
|
+
AssetType,
|
|
15
16
|
} from './amm';
|
|
16
17
|
import { squareRootBN } from './utils';
|
|
17
18
|
|
|
@@ -27,7 +28,8 @@ export type PriceImpactUnit =
|
|
|
27
28
|
| 'quoteAssetAmount'
|
|
28
29
|
| 'quoteAssetAmountPeg'
|
|
29
30
|
| 'acquiredBaseAssetAmount'
|
|
30
|
-
| 'acquiredQuoteAssetAmount'
|
|
31
|
+
| 'acquiredQuoteAssetAmount'
|
|
32
|
+
| 'all';
|
|
31
33
|
|
|
32
34
|
/**
|
|
33
35
|
* Calculates avg/max slippage (price impact) for candidate trade
|
|
@@ -47,7 +49,8 @@ export type PriceImpactUnit =
|
|
|
47
49
|
export function calculateTradeSlippage(
|
|
48
50
|
direction: PositionDirection,
|
|
49
51
|
amount: BN,
|
|
50
|
-
market: Market
|
|
52
|
+
market: Market,
|
|
53
|
+
inputAssetType: AssetType = 'quote'
|
|
51
54
|
): [BN, BN, BN, BN] {
|
|
52
55
|
const oldPrice = calculateMarkPrice(market);
|
|
53
56
|
if (amount.eq(ZERO)) {
|
|
@@ -56,7 +59,8 @@ export function calculateTradeSlippage(
|
|
|
56
59
|
const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(
|
|
57
60
|
direction,
|
|
58
61
|
amount,
|
|
59
|
-
market
|
|
62
|
+
market,
|
|
63
|
+
inputAssetType
|
|
60
64
|
);
|
|
61
65
|
|
|
62
66
|
const entryPrice = calculatePrice(
|
|
@@ -103,7 +107,8 @@ export function calculateTradeSlippage(
|
|
|
103
107
|
export function calculateTradeAcquiredAmounts(
|
|
104
108
|
direction: PositionDirection,
|
|
105
109
|
amount: BN,
|
|
106
|
-
market: Market
|
|
110
|
+
market: Market,
|
|
111
|
+
inputAssetType: AssetType = 'quote'
|
|
107
112
|
): [BN, BN] {
|
|
108
113
|
if (amount.eq(ZERO)) {
|
|
109
114
|
return [ZERO, ZERO];
|
|
@@ -112,9 +117,9 @@ export function calculateTradeAcquiredAmounts(
|
|
|
112
117
|
const [newQuoteAssetReserve, newBaseAssetReserve] =
|
|
113
118
|
calculateAmmReservesAfterSwap(
|
|
114
119
|
market.amm,
|
|
115
|
-
|
|
120
|
+
inputAssetType,
|
|
116
121
|
amount,
|
|
117
|
-
getSwapDirection(
|
|
122
|
+
getSwapDirection(inputAssetType, direction)
|
|
118
123
|
);
|
|
119
124
|
|
|
120
125
|
const acquiredBase = market.amm.baseAssetReserve.sub(newBaseAssetReserve);
|
|
@@ -129,8 +134,8 @@ export function calculateTradeAcquiredAmounts(
|
|
|
129
134
|
* @param market
|
|
130
135
|
* @param targetPrice
|
|
131
136
|
* @param pct optional default is 100% gap filling, can set smaller.
|
|
132
|
-
* @returns trade direction/size in order to push price to a targetPrice,
|
|
133
|
-
*
|
|
137
|
+
* @returns trade direction/size in order to push price to a targetPrice,
|
|
138
|
+
*
|
|
134
139
|
* [
|
|
135
140
|
* direction => direction of trade required, TODO-PRECISION
|
|
136
141
|
* tradeSize => size of trade required, TODO-PRECISION
|
|
@@ -236,6 +241,7 @@ export function calculateTargetPriceTrade(
|
|
|
236
241
|
|
|
237
242
|
const entryPrice = tradeSize
|
|
238
243
|
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
244
|
+
.mul(MARK_PRICE_PRECISION)
|
|
239
245
|
.div(baseSize.abs());
|
|
240
246
|
|
|
241
247
|
assert(tp1.sub(tp2).lte(originalDiff), 'Target Price Calculation incorrect');
|
package/src/types.ts
CHANGED
|
@@ -221,6 +221,8 @@ export type AMM = {
|
|
|
221
221
|
lastFundingRateTs: BN;
|
|
222
222
|
lastMarkPriceTwap: BN;
|
|
223
223
|
lastMarkPriceTwapTs: BN;
|
|
224
|
+
lastOraclePriceTwap: BN;
|
|
225
|
+
lastOraclePriceTwapTs: BN;
|
|
224
226
|
oracle: PublicKey;
|
|
225
227
|
oracleSource: OracleSource;
|
|
226
228
|
fundingPeriod: BN;
|
|
@@ -264,7 +266,9 @@ export interface Trade {
|
|
|
264
266
|
afterPrice: number;
|
|
265
267
|
side: TradeSide;
|
|
266
268
|
size: number;
|
|
269
|
+
quoteSize: number;
|
|
267
270
|
ts: number;
|
|
271
|
+
fee: number;
|
|
268
272
|
marketIndex: number;
|
|
269
273
|
chainTs: number;
|
|
270
274
|
}
|
|
@@ -299,9 +303,14 @@ export type Candle = {
|
|
|
299
303
|
};
|
|
300
304
|
export interface FundingPayment {
|
|
301
305
|
userPublicKey: string;
|
|
302
|
-
|
|
306
|
+
serverTs: number;
|
|
303
307
|
marketIndex: number;
|
|
304
308
|
amount: string;
|
|
309
|
+
blockchainTs: number;
|
|
310
|
+
baseAssetAmount: string;
|
|
311
|
+
userLastCumulativeFunding: string;
|
|
312
|
+
userLastFundingRateTs: string;
|
|
313
|
+
rate: number;
|
|
305
314
|
}
|
|
306
315
|
|
|
307
316
|
// # Misc Types
|