@drift-labs/sdk 0.1.7 → 0.1.11
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 +34 -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 +11 -1
- package/lib/math/funding.d.ts.map +1 -0
- package/lib/math/funding.js +84 -19
- package/lib/math/market.d.ts +1 -0
- package/lib/math/market.d.ts.map +1 -0
- package/lib/math/position.d.ts +7 -0
- package/lib/math/position.d.ts.map +1 -0
- package/lib/math/position.js +17 -1
- package/lib/math/trade.d.ts +5 -3
- package/lib/math/trade.d.ts.map +1 -0
- package/lib/math/trade.js +4 -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 +10 -1
- package/lib/types.d.ts.map +1 -0
- package/package.json +12 -2
- package/src/admin.ts +4 -4
- package/src/clearingHouseUser.ts +27 -4
- package/src/config.ts +1 -1
- package/src/constants/markets.ts +28 -21
- package/src/idl/clearing_house.json +34 -30
- package/src/math/funding.ts +120 -48
- package/src/math/position.ts +19 -0
- package/src/math/trade.ts +11 -6
- package/src/types.ts +9 -1
- package/tsconfig.json +2 -1
|
@@ -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",
|
package/src/math/funding.ts
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
2
|
import {
|
|
3
|
-
AMM_RESERVE_PRECISION,
|
|
3
|
+
AMM_RESERVE_PRECISION,
|
|
4
|
+
MARK_PRICE_PRECISION,
|
|
5
|
+
QUOTE_PRECISION,
|
|
6
|
+
ZERO,
|
|
4
7
|
} from '../constants/numericConstants';
|
|
5
8
|
import { PythClient } from '../pythClient';
|
|
6
9
|
import { Market } from '../types';
|
|
7
10
|
import { calculateMarkPrice } from './market';
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @param market
|
|
12
|
-
* @param pythClient
|
|
13
|
-
* @param periodAdjustment
|
|
13
|
+
*
|
|
14
|
+
* @param market
|
|
15
|
+
* @param pythClient
|
|
16
|
+
* @param periodAdjustment
|
|
14
17
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
15
18
|
*/
|
|
16
|
-
|
|
19
|
+
export async function calculateAllEstimatedFundingRate(
|
|
17
20
|
market: Market,
|
|
18
21
|
pythClient: PythClient,
|
|
19
|
-
periodAdjustment: BN = new BN(1)
|
|
20
|
-
): Promise<[BN, BN, 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 @@ import { calculateMarkPrice } from './market';
|
|
|
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,7 +73,6 @@ import { calculateMarkPrice } from './market';
|
|
|
61
73
|
.mul(new BN(100))
|
|
62
74
|
.div(oracleTwapWithMantissa);
|
|
63
75
|
|
|
64
|
-
|
|
65
76
|
const lowerboundEst = twapSpreadPct
|
|
66
77
|
.mul(payFreq)
|
|
67
78
|
.mul(BN.min(secondsInHour, timeSinceLastUpdate))
|
|
@@ -72,30 +83,59 @@ import { calculateMarkPrice } from './market';
|
|
|
72
83
|
|
|
73
84
|
const interpEst = twapSpreadPct.mul(periodAdjustment).div(hoursInDay);
|
|
74
85
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
}
|
|
79
94
|
|
|
80
95
|
let cappedAltEst: BN;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
+
}
|
|
94
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)
|
|
128
|
+
.mul(periodAdjustment)
|
|
129
|
+
.div(hoursInDay);
|
|
130
|
+
if (cappedAltEst.abs().gt(interpEst.abs())) {
|
|
131
|
+
cappedAltEst = interpEst;
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
95
134
|
cappedAltEst = interpEst;
|
|
96
135
|
}
|
|
97
136
|
|
|
98
|
-
|
|
137
|
+
|
|
138
|
+
return [markTwapWithMantissa, oracleTwapWithMantissa, lowerboundEst, cappedAltEst, interpEst];
|
|
99
139
|
}
|
|
100
140
|
|
|
101
141
|
/**
|
|
@@ -112,8 +152,12 @@ export async function calculateEstimatedFundingRate(
|
|
|
112
152
|
periodAdjustment: BN = new BN(1),
|
|
113
153
|
estimationMethod: 'interpolated' | 'lowerbound' | 'capped'
|
|
114
154
|
): Promise<BN> {
|
|
115
|
-
const [lowerboundEst, cappedAltEst, interpEst] =
|
|
116
|
-
await calculateAllEstimatedFundingRate(
|
|
155
|
+
const [_1, _2, lowerboundEst, cappedAltEst, interpEst] =
|
|
156
|
+
await calculateAllEstimatedFundingRate(
|
|
157
|
+
market,
|
|
158
|
+
pythClient,
|
|
159
|
+
periodAdjustment
|
|
160
|
+
);
|
|
117
161
|
|
|
118
162
|
if (estimationMethod == 'lowerbound') {
|
|
119
163
|
//assuming remaining funding period has no gap
|
|
@@ -125,6 +169,33 @@ export async function calculateEstimatedFundingRate(
|
|
|
125
169
|
}
|
|
126
170
|
}
|
|
127
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
|
+
}
|
|
128
199
|
|
|
129
200
|
/**
|
|
130
201
|
*
|
|
@@ -134,20 +205,20 @@ export async function calculateEstimatedFundingRate(
|
|
|
134
205
|
* @param estimationMethod
|
|
135
206
|
* @returns Estimated funding rate. : Precision //TODO-PRECISION
|
|
136
207
|
*/
|
|
137
|
-
export async function
|
|
208
|
+
export async function calculateLongShortFundingRateAndLiveTwaps(
|
|
138
209
|
market: Market,
|
|
139
210
|
pythClient: PythClient,
|
|
140
211
|
periodAdjustment: BN = new BN(1),
|
|
141
|
-
): Promise<[BN, BN]> {
|
|
142
|
-
const [
|
|
212
|
+
): Promise<[BN, BN, BN, BN]> {
|
|
213
|
+
const [markTwapLive, oracleTwapLive, _2, cappedAltEst, interpEst] =
|
|
143
214
|
await calculateAllEstimatedFundingRate(market, pythClient, periodAdjustment);
|
|
144
215
|
|
|
145
|
-
if(market.baseAssetAmountLong.gt(market.baseAssetAmountShort)){
|
|
146
|
-
return [cappedAltEst, interpEst];
|
|
147
|
-
} else if(market.baseAssetAmountLong.lt(market.baseAssetAmountShort)){
|
|
148
|
-
return [interpEst, cappedAltEst];
|
|
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];
|
|
149
220
|
} else{
|
|
150
|
-
return [interpEst, interpEst];
|
|
221
|
+
return [markTwapLive, oracleTwapLive, interpEst, interpEst];
|
|
151
222
|
}
|
|
152
223
|
|
|
153
224
|
}
|
|
@@ -158,6 +229,7 @@ export async function calculateEstimatedFundingRate(
|
|
|
158
229
|
* @returns Estimated fee pool size
|
|
159
230
|
*/
|
|
160
231
|
export function calculateFundingPool(market: Market): BN {
|
|
232
|
+
// todo
|
|
161
233
|
const totalFeeLB = market.amm.totalFee.div(new BN(2));
|
|
162
234
|
const feePool = market.amm.totalFeeMinusDistributions.sub(totalFeeLB);
|
|
163
235
|
return feePool;
|
package/src/math/position.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Market, PositionDirection, UserPosition } from '../types';
|
|
2
2
|
import {
|
|
3
3
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
4
|
+
MARK_PRICE_PRECISION,
|
|
4
5
|
PEG_PRECISION,
|
|
6
|
+
QUOTE_PRECISION,
|
|
5
7
|
ZERO,
|
|
6
8
|
} from '../constants/numericConstants';
|
|
7
9
|
import BN from 'bn.js';
|
|
@@ -131,3 +133,20 @@ export function calculatePositionFundingPNL(
|
|
|
131
133
|
|
|
132
134
|
return perPositionFundingRate;
|
|
133
135
|
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
* @param userPosition
|
|
140
|
+
* @returns Precision: MARK_PRICE_PRECISION (10^10)
|
|
141
|
+
*/
|
|
142
|
+
export function calculateEntryPrice(userPosition: UserPosition): BN {
|
|
143
|
+
if (userPosition.baseAssetAmount.eq(ZERO)) {
|
|
144
|
+
return ZERO;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return userPosition.quoteAssetAmount
|
|
148
|
+
.mul(MARK_PRICE_PRECISION)
|
|
149
|
+
.mul(AMM_TO_QUOTE_PRECISION_RATIO)
|
|
150
|
+
.div(userPosition.baseAssetAmount)
|
|
151
|
+
.abs();
|
|
152
|
+
}
|
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);
|
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,6 +266,7 @@ export interface Trade {
|
|
|
264
266
|
afterPrice: number;
|
|
265
267
|
side: TradeSide;
|
|
266
268
|
size: number;
|
|
269
|
+
quoteSize: number;
|
|
267
270
|
ts: number;
|
|
268
271
|
fee: number;
|
|
269
272
|
marketIndex: number;
|
|
@@ -300,9 +303,14 @@ export type Candle = {
|
|
|
300
303
|
};
|
|
301
304
|
export interface FundingPayment {
|
|
302
305
|
userPublicKey: string;
|
|
303
|
-
|
|
306
|
+
serverTs: number;
|
|
304
307
|
marketIndex: number;
|
|
305
308
|
amount: string;
|
|
309
|
+
blockchainTs: number;
|
|
310
|
+
baseAssetAmount: string;
|
|
311
|
+
userLastCumulativeFunding: string;
|
|
312
|
+
userLastFundingRateTs: string;
|
|
313
|
+
rate: number;
|
|
306
314
|
}
|
|
307
315
|
|
|
308
316
|
// # Misc Types
|