@drift-labs/sdk 0.1.7 → 0.1.8
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/lib/admin.d.ts +1 -1
- package/lib/admin.js +2 -2
- package/lib/clearingHouseUser.d.ts +1 -1
- package/lib/clearingHouseUser.js +19 -2
- package/lib/config.js +1 -1
- package/lib/constants/markets.js +14 -14
- package/lib/idl/clearing_house.json +28 -28
- package/lib/math/funding.js +33 -9
- package/lib/math/trade.d.ts +3 -2
- package/lib/math/trade.js +4 -4
- package/package.json +1 -1
- package/src/admin.ts +4 -4
- package/src/clearingHouseUser.ts +23 -3
- package/src/config.ts +1 -1
- package/src/constants/markets.ts +14 -14
- package/src/idl/clearing_house.json +28 -28
- package/src/math/funding.ts +37 -12
- package/src/math/trade.ts +9 -5
package/lib/admin.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { ClearingHouse } from './clearingHouse';
|
|
|
6
6
|
export declare class Admin extends ClearingHouse {
|
|
7
7
|
static from(connection: Connection, wallet: IWallet, clearingHouseProgramId: PublicKey, opts?: ConfirmOptions): Admin;
|
|
8
8
|
initialize(usdcMint: PublicKey, adminControlsPrices: boolean): Promise<[TransactionSignature, TransactionSignature]>;
|
|
9
|
-
initializeMarket(marketIndex: BN, priceOracle: PublicKey,
|
|
9
|
+
initializeMarket(marketIndex: BN, priceOracle: PublicKey, baseAssetReserve: BN, quoteAssetReserve: BN, periodicity: BN, pegMultiplier?: BN): Promise<TransactionSignature>;
|
|
10
10
|
moveAmmPrice(baseAssetReserve: BN, quoteAssetReserve: BN, marketIndex: BN): Promise<TransactionSignature>;
|
|
11
11
|
updateK(sqrtK: BN, marketIndex: BN): Promise<TransactionSignature>;
|
|
12
12
|
moveAmmToPrice(marketIndex: BN, targetPrice: BN): Promise<TransactionSignature>;
|
package/lib/admin.js
CHANGED
|
@@ -122,12 +122,12 @@ class Admin extends clearingHouse_1.ClearingHouse {
|
|
|
122
122
|
return [initializeTxSig, initializeHistoryTxSig];
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
|
-
initializeMarket(marketIndex, priceOracle,
|
|
125
|
+
initializeMarket(marketIndex, priceOracle, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier = numericConstants_1.PEG_PRECISION) {
|
|
126
126
|
return __awaiter(this, void 0, void 0, function* () {
|
|
127
127
|
if (this.getMarketsAccount().markets[marketIndex.toNumber()].initialized) {
|
|
128
128
|
throw Error(`MarketIndex ${marketIndex.toNumber()} already initialized`);
|
|
129
129
|
}
|
|
130
|
-
const initializeMarketTx = yield this.program.transaction.initializeMarket(marketIndex,
|
|
130
|
+
const initializeMarketTx = yield this.program.transaction.initializeMarket(marketIndex, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier, {
|
|
131
131
|
accounts: {
|
|
132
132
|
state: yield this.getStatePublicKey(),
|
|
133
133
|
admin: this.wallet.publicKey,
|
|
@@ -72,7 +72,7 @@ export declare class ClearingHouseUser {
|
|
|
72
72
|
* calculates average exit price for closing 100% of position
|
|
73
73
|
* @returns : Precision MARK_PRICE_PRECISION
|
|
74
74
|
*/
|
|
75
|
-
getPositionEstimatedExitPrice(position: UserPosition): BN;
|
|
75
|
+
getPositionEstimatedExitPrice(position: UserPosition, amountToClose?: BN): BN;
|
|
76
76
|
/**
|
|
77
77
|
* calculates current user leverage across all positions
|
|
78
78
|
* @returns : Precision TEN_THOUSAND
|
package/lib/clearingHouseUser.js
CHANGED
|
@@ -60,7 +60,13 @@ class ClearingHouseUser {
|
|
|
60
60
|
* @returns userPosition
|
|
61
61
|
*/
|
|
62
62
|
getUserPosition(marketIndex) {
|
|
63
|
-
|
|
63
|
+
var _a;
|
|
64
|
+
return ((_a = this.getUserPositionsAccount().positions.find((position) => position.marketIndex.eq(marketIndex))) !== null && _a !== void 0 ? _a : {
|
|
65
|
+
baseAssetAmount: numericConstants_1.ZERO,
|
|
66
|
+
lastCumulativeFundingRate: numericConstants_1.ZERO,
|
|
67
|
+
marketIndex,
|
|
68
|
+
quoteAssetAmount: numericConstants_1.ZERO,
|
|
69
|
+
});
|
|
64
70
|
}
|
|
65
71
|
getUserAccountPublicKey() {
|
|
66
72
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -158,8 +164,19 @@ class ClearingHouseUser {
|
|
|
158
164
|
* calculates average exit price for closing 100% of position
|
|
159
165
|
* @returns : Precision MARK_PRICE_PRECISION
|
|
160
166
|
*/
|
|
161
|
-
getPositionEstimatedExitPrice(position) {
|
|
167
|
+
getPositionEstimatedExitPrice(position, amountToClose) {
|
|
162
168
|
const market = this.clearingHouse.getMarket(position.marketIndex);
|
|
169
|
+
if (amountToClose) {
|
|
170
|
+
if (amountToClose.eq(numericConstants_1.ZERO)) {
|
|
171
|
+
return _1.calculateMarkPrice(market);
|
|
172
|
+
}
|
|
173
|
+
position = {
|
|
174
|
+
baseAssetAmount: amountToClose,
|
|
175
|
+
lastCumulativeFundingRate: position.lastCumulativeFundingRate,
|
|
176
|
+
marketIndex: position.marketIndex,
|
|
177
|
+
quoteAssetAmount: position.quoteAssetAmount,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
163
180
|
const baseAssetValue = _1.calculateBaseAssetValue(market, position);
|
|
164
181
|
if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
165
182
|
return numericConstants_1.ZERO;
|
package/lib/config.js
CHANGED
|
@@ -5,7 +5,7 @@ exports.configs = {
|
|
|
5
5
|
devnet: {
|
|
6
6
|
ENV: 'devnet',
|
|
7
7
|
PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
|
|
8
|
-
CLEARING_HOUSE_PROGRAM_ID: '
|
|
8
|
+
CLEARING_HOUSE_PROGRAM_ID: 'AsW7LnXB9UA1uec9wi9MctYTgTz7YH9snhxd16GsFaGX',
|
|
9
9
|
USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
|
|
10
10
|
},
|
|
11
11
|
'mainnet-beta': {
|
package/lib/constants/markets.js
CHANGED
|
@@ -13,20 +13,20 @@ exports.Markets = [
|
|
|
13
13
|
devnetPythOracle: 'J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix',
|
|
14
14
|
mainnetPythOracle: 'H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG',
|
|
15
15
|
},
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
16
|
+
{
|
|
17
|
+
symbol: 'BTC-PERP',
|
|
18
|
+
baseAssetSymbol: 'BTC',
|
|
19
|
+
marketIndex: new bn_js_1.default(1),
|
|
20
|
+
devnetPythOracle: 'HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J',
|
|
21
|
+
mainnetPythOracle: 'GVXRSBjFk6e6J3NbVPXohDJetcTjaeeuykUpbQF8UoMU',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
symbol: 'ETH-PERP',
|
|
25
|
+
baseAssetSymbol: 'ETH',
|
|
26
|
+
marketIndex: new bn_js_1.default(2),
|
|
27
|
+
devnetPythOracle: 'EdVCmQ9FSPcVe5YySXDPCRmc8aDQLKJ9xvYBMZPie1Vw',
|
|
28
|
+
mainnetPythOracle: 'JBu1AL4obBcCMqKBBxhpWCNUt136ijcuMZLFvTP7iWdB',
|
|
29
|
+
},
|
|
30
30
|
// {
|
|
31
31
|
// symbol: 'COPE-PERP',
|
|
32
32
|
// baseAssetSymbol: 'COPE',
|
|
@@ -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": {
|
package/lib/math/funding.js
CHANGED
|
@@ -60,19 +60,42 @@ function calculateAllEstimatedFundingRate(market, pythClient, periodAdjustment =
|
|
|
60
60
|
const interpEst = twapSpreadPct.mul(periodAdjustment).div(hoursInDay);
|
|
61
61
|
const interpRateQuote = twapSpreadPct.mul(periodAdjustment).div(hoursInDay)
|
|
62
62
|
.div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.QUOTE_PRECISION));
|
|
63
|
-
|
|
63
|
+
let feePoolSize = calculateFundingPool(market);
|
|
64
|
+
if (interpRateQuote.lt(new anchor_1.BN(0))) {
|
|
65
|
+
feePoolSize = feePoolSize.mul(new anchor_1.BN(-1));
|
|
66
|
+
}
|
|
64
67
|
let cappedAltEst;
|
|
68
|
+
let largerSide;
|
|
69
|
+
let smallerSide;
|
|
65
70
|
if (market.baseAssetAmountLong.gt(market.baseAssetAmountShort)) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
largerSide = market.baseAssetAmountLong.abs();
|
|
72
|
+
smallerSide = market.baseAssetAmountShort.abs();
|
|
73
|
+
if (twapSpread.gt(new anchor_1.BN(0))) {
|
|
74
|
+
return [lowerboundEst, interpEst, interpEst];
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
else if (market.baseAssetAmountLong.lt(market.baseAssetAmountShort)) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
largerSide = market.baseAssetAmountShort.abs();
|
|
79
|
+
smallerSide = market.baseAssetAmountLong.abs();
|
|
80
|
+
if (twapSpread.lt(new anchor_1.BN(0))) {
|
|
81
|
+
return [lowerboundEst, interpEst, interpEst];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
return [lowerboundEst, interpEst, interpEst];
|
|
86
|
+
}
|
|
87
|
+
if (largerSide.gt(numericConstants_1.ZERO)) {
|
|
88
|
+
cappedAltEst = smallerSide.mul(twapSpread).div(largerSide);
|
|
89
|
+
const feePoolTopOff = feePoolSize.mul(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.QUOTE_PRECISION))
|
|
90
|
+
.mul(numericConstants_1.AMM_RESERVE_PRECISION).div(largerSide);
|
|
91
|
+
cappedAltEst = cappedAltEst.add(feePoolTopOff);
|
|
92
|
+
cappedAltEst = cappedAltEst.mul(numericConstants_1.MARK_PRICE_PRECISION)
|
|
93
|
+
.mul(new anchor_1.BN(100))
|
|
94
|
+
.div(oracleTwapWithMantissa)
|
|
95
|
+
.mul(periodAdjustment).div(hoursInDay);
|
|
96
|
+
if (cappedAltEst.abs().gt(interpEst.abs())) {
|
|
97
|
+
cappedAltEst = interpEst;
|
|
98
|
+
}
|
|
76
99
|
}
|
|
77
100
|
else {
|
|
78
101
|
cappedAltEst = interpEst;
|
|
@@ -136,6 +159,7 @@ exports.calculateLongShortFundingRate = calculateLongShortFundingRate;
|
|
|
136
159
|
function calculateFundingPool(market) {
|
|
137
160
|
const totalFeeLB = market.amm.totalFee.div(new anchor_1.BN(2));
|
|
138
161
|
const feePool = market.amm.totalFeeMinusDistributions.sub(totalFeeLB);
|
|
162
|
+
// return new BN(QUOTE_PRECISION.mul(new BN(2400)));
|
|
139
163
|
return feePool;
|
|
140
164
|
}
|
|
141
165
|
exports.calculateFundingPool = calculateFundingPool;
|
package/lib/math/trade.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { Market, PositionDirection } from '../types';
|
|
3
3
|
import { BN } from '@project-serum/anchor';
|
|
4
|
+
import { AssetType } from './amm';
|
|
4
5
|
export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' | 'priceDeltaAsNumber' | 'pctAvg' | 'pctMax' | 'quoteAssetAmount' | 'quoteAssetAmountPeg' | 'acquiredBaseAssetAmount' | 'acquiredQuoteAssetAmount';
|
|
5
6
|
/**
|
|
6
7
|
* Calculates avg/max slippage (price impact) for candidate trade
|
|
@@ -17,7 +18,7 @@ export declare type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' |
|
|
|
17
18
|
*
|
|
18
19
|
* 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
|
|
19
20
|
*/
|
|
20
|
-
export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: Market): [BN, BN, BN, BN];
|
|
21
|
+
export declare function calculateTradeSlippage(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType): [BN, BN, BN, BN];
|
|
21
22
|
/**
|
|
22
23
|
* Calculates acquired amounts for trade executed
|
|
23
24
|
* @param direction
|
|
@@ -27,7 +28,7 @@ export declare function calculateTradeSlippage(direction: PositionDirection, amo
|
|
|
27
28
|
* | 'acquiredBase' => positive/negative change in user's base : BN TODO-PRECISION
|
|
28
29
|
* | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
|
|
29
30
|
*/
|
|
30
|
-
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: Market): [BN, BN];
|
|
31
|
+
export declare function calculateTradeAcquiredAmounts(direction: PositionDirection, amount: BN, market: Market, inputAssetType?: AssetType): [BN, BN];
|
|
31
32
|
/**
|
|
32
33
|
* calculateTargetPriceTrade
|
|
33
34
|
* simple function for finding arbitraging trades
|
package/lib/math/trade.js
CHANGED
|
@@ -24,12 +24,12 @@ const MAXPCT = new anchor_1.BN(1000); //percentage units are [0,1000] => [0,1]
|
|
|
24
24
|
*
|
|
25
25
|
* 'newPrice' => the price of the asset after the trade : Precision MARK_PRICE_PRECISION
|
|
26
26
|
*/
|
|
27
|
-
function calculateTradeSlippage(direction, amount, market) {
|
|
27
|
+
function calculateTradeSlippage(direction, amount, market, inputAssetType = 'quote') {
|
|
28
28
|
const oldPrice = market_1.calculateMarkPrice(market);
|
|
29
29
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
30
30
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO, oldPrice, oldPrice];
|
|
31
31
|
}
|
|
32
|
-
const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(direction, amount, market);
|
|
32
|
+
const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType);
|
|
33
33
|
const entryPrice = amm_1.calculatePrice(acquiredBase, acquiredQuote, market.amm.pegMultiplier).mul(new anchor_1.BN(-1));
|
|
34
34
|
const newPrice = amm_1.calculatePrice(market.amm.baseAssetReserve.sub(acquiredBase), market.amm.quoteAssetReserve.sub(acquiredQuote), market.amm.pegMultiplier);
|
|
35
35
|
if (direction == types_1.PositionDirection.SHORT) {
|
|
@@ -60,11 +60,11 @@ exports.calculateTradeSlippage = calculateTradeSlippage;
|
|
|
60
60
|
* | 'acquiredBase' => positive/negative change in user's base : BN TODO-PRECISION
|
|
61
61
|
* | 'acquiredQuote' => positive/negative change in user's quote : BN TODO-PRECISION
|
|
62
62
|
*/
|
|
63
|
-
function calculateTradeAcquiredAmounts(direction, amount, market) {
|
|
63
|
+
function calculateTradeAcquiredAmounts(direction, amount, market, inputAssetType = 'quote') {
|
|
64
64
|
if (amount.eq(numericConstants_1.ZERO)) {
|
|
65
65
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
66
66
|
}
|
|
67
|
-
const [newQuoteAssetReserve, newBaseAssetReserve] = amm_1.calculateAmmReservesAfterSwap(market.amm,
|
|
67
|
+
const [newQuoteAssetReserve, newBaseAssetReserve] = amm_1.calculateAmmReservesAfterSwap(market.amm, inputAssetType, amount, amm_1.getSwapDirection(inputAssetType, direction));
|
|
68
68
|
const acquiredBase = market.amm.baseAssetReserve.sub(newBaseAssetReserve);
|
|
69
69
|
const acquiredQuote = market.amm.quoteAssetReserve.sub(newQuoteAssetReserve);
|
|
70
70
|
return [acquiredBase, acquiredQuote];
|
package/package.json
CHANGED
package/src/admin.ts
CHANGED
|
@@ -178,8 +178,8 @@ export class Admin extends ClearingHouse {
|
|
|
178
178
|
public async initializeMarket(
|
|
179
179
|
marketIndex: BN,
|
|
180
180
|
priceOracle: PublicKey,
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
baseAssetReserve: BN,
|
|
182
|
+
quoteAssetReserve: BN,
|
|
183
183
|
periodicity: BN,
|
|
184
184
|
pegMultiplier: BN = PEG_PRECISION
|
|
185
185
|
): Promise<TransactionSignature> {
|
|
@@ -189,8 +189,8 @@ export class Admin extends ClearingHouse {
|
|
|
189
189
|
|
|
190
190
|
const initializeMarketTx = await this.program.transaction.initializeMarket(
|
|
191
191
|
marketIndex,
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
baseAssetReserve,
|
|
193
|
+
quoteAssetReserve,
|
|
194
194
|
periodicity,
|
|
195
195
|
pegMultiplier,
|
|
196
196
|
{
|
package/src/clearingHouseUser.ts
CHANGED
|
@@ -86,8 +86,15 @@ export class ClearingHouseUser {
|
|
|
86
86
|
* @returns userPosition
|
|
87
87
|
*/
|
|
88
88
|
public getUserPosition(marketIndex: BN): UserPosition {
|
|
89
|
-
return
|
|
90
|
-
|
|
89
|
+
return (
|
|
90
|
+
this.getUserPositionsAccount().positions.find((position) =>
|
|
91
|
+
position.marketIndex.eq(marketIndex)
|
|
92
|
+
) ?? {
|
|
93
|
+
baseAssetAmount: ZERO,
|
|
94
|
+
lastCumulativeFundingRate: ZERO,
|
|
95
|
+
marketIndex,
|
|
96
|
+
quoteAssetAmount: ZERO,
|
|
97
|
+
}
|
|
91
98
|
);
|
|
92
99
|
}
|
|
93
100
|
|
|
@@ -217,8 +224,21 @@ export class ClearingHouseUser {
|
|
|
217
224
|
* calculates average exit price for closing 100% of position
|
|
218
225
|
* @returns : Precision MARK_PRICE_PRECISION
|
|
219
226
|
*/
|
|
220
|
-
public getPositionEstimatedExitPrice(position: UserPosition): BN {
|
|
227
|
+
public getPositionEstimatedExitPrice(position: UserPosition, amountToClose?: BN): BN {
|
|
221
228
|
const market = this.clearingHouse.getMarket(position.marketIndex);
|
|
229
|
+
|
|
230
|
+
if(amountToClose){
|
|
231
|
+
if(amountToClose.eq(ZERO)){
|
|
232
|
+
return calculateMarkPrice(market);
|
|
233
|
+
}
|
|
234
|
+
position = {
|
|
235
|
+
baseAssetAmount: amountToClose,
|
|
236
|
+
lastCumulativeFundingRate: position.lastCumulativeFundingRate,
|
|
237
|
+
marketIndex: position.marketIndex,
|
|
238
|
+
quoteAssetAmount: position.quoteAssetAmount,
|
|
239
|
+
} as UserPosition;
|
|
240
|
+
}
|
|
241
|
+
|
|
222
242
|
const baseAssetValue = calculateBaseAssetValue(market, position);
|
|
223
243
|
if (position.baseAssetAmount.eq(ZERO)) {
|
|
224
244
|
return ZERO;
|
package/src/config.ts
CHANGED
|
@@ -11,7 +11,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
11
11
|
devnet: {
|
|
12
12
|
ENV: 'devnet',
|
|
13
13
|
PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
|
|
14
|
-
CLEARING_HOUSE_PROGRAM_ID: '
|
|
14
|
+
CLEARING_HOUSE_PROGRAM_ID: 'AsW7LnXB9UA1uec9wi9MctYTgTz7YH9snhxd16GsFaGX',
|
|
15
15
|
USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
|
|
16
16
|
},
|
|
17
17
|
'mainnet-beta': {
|
package/src/constants/markets.ts
CHANGED
|
@@ -16,20 +16,20 @@ 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
|
-
|
|
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
33
|
// {
|
|
34
34
|
// symbol: 'COPE-PERP',
|
|
35
35
|
// baseAssetSymbol: 'COPE',
|
|
@@ -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": {
|
package/src/math/funding.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BN } from '@project-serum/anchor';
|
|
2
2
|
import {
|
|
3
|
-
AMM_RESERVE_PRECISION, MARK_PRICE_PRECISION, QUOTE_PRECISION
|
|
3
|
+
AMM_RESERVE_PRECISION, MARK_PRICE_PRECISION, QUOTE_PRECISION, ZERO
|
|
4
4
|
} from '../constants/numericConstants';
|
|
5
5
|
import { PythClient } from '../pythClient';
|
|
6
6
|
import { Market } from '../types';
|
|
@@ -75,26 +75,50 @@ import { calculateMarkPrice } from './market';
|
|
|
75
75
|
|
|
76
76
|
const interpRateQuote = twapSpreadPct.mul(periodAdjustment).div(hoursInDay)
|
|
77
77
|
.div(MARK_PRICE_PRECISION.div(QUOTE_PRECISION));
|
|
78
|
-
|
|
78
|
+
let feePoolSize = calculateFundingPool(market);
|
|
79
|
+
if(interpRateQuote.lt(new BN(0))){
|
|
80
|
+
feePoolSize = feePoolSize.mul(new BN(-1));
|
|
81
|
+
}
|
|
79
82
|
|
|
80
83
|
let cappedAltEst: BN;
|
|
84
|
+
let largerSide: BN;
|
|
85
|
+
let smallerSide: BN;
|
|
81
86
|
|
|
82
87
|
if(market.baseAssetAmountLong.gt(market.baseAssetAmountShort)){
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
largerSide = market.baseAssetAmountLong.abs();
|
|
89
|
+
smallerSide = market.baseAssetAmountShort.abs();
|
|
90
|
+
if(twapSpread.gt(new BN(0))){
|
|
91
|
+
return [lowerboundEst, interpEst, interpEst];
|
|
92
|
+
}
|
|
88
93
|
} else if(market.baseAssetAmountLong.lt(market.baseAssetAmountShort)){
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
largerSide = market.baseAssetAmountShort.abs();
|
|
95
|
+
smallerSide = market.baseAssetAmountLong.abs();
|
|
96
|
+
if(twapSpread.lt(new BN(0))){
|
|
97
|
+
return [lowerboundEst, interpEst, interpEst];
|
|
98
|
+
}
|
|
99
|
+
} else{
|
|
100
|
+
return [lowerboundEst, interpEst, interpEst];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if(largerSide.gt(ZERO)){
|
|
104
|
+
cappedAltEst = smallerSide.mul(twapSpread).div(largerSide);
|
|
105
|
+
const feePoolTopOff = feePoolSize.mul(MARK_PRICE_PRECISION.div(QUOTE_PRECISION))
|
|
106
|
+
.mul(AMM_RESERVE_PRECISION).div(largerSide);
|
|
107
|
+
cappedAltEst = cappedAltEst.add(feePoolTopOff);
|
|
108
|
+
|
|
109
|
+
cappedAltEst = cappedAltEst.mul(MARK_PRICE_PRECISION)
|
|
110
|
+
.mul(new BN(100))
|
|
111
|
+
.div(oracleTwapWithMantissa)
|
|
112
|
+
.mul(periodAdjustment).div(hoursInDay);
|
|
113
|
+
|
|
114
|
+
if(cappedAltEst.abs().gt(interpEst.abs())){
|
|
115
|
+
cappedAltEst = interpEst;
|
|
116
|
+
}
|
|
94
117
|
} else{
|
|
95
118
|
cappedAltEst = interpEst;
|
|
96
119
|
}
|
|
97
120
|
|
|
121
|
+
|
|
98
122
|
return [lowerboundEst, cappedAltEst, interpEst];
|
|
99
123
|
}
|
|
100
124
|
|
|
@@ -160,5 +184,6 @@ export async function calculateEstimatedFundingRate(
|
|
|
160
184
|
export function calculateFundingPool(market: Market): BN {
|
|
161
185
|
const totalFeeLB = market.amm.totalFee.div(new BN(2));
|
|
162
186
|
const feePool = market.amm.totalFeeMinusDistributions.sub(totalFeeLB);
|
|
187
|
+
// return new BN(QUOTE_PRECISION.mul(new BN(2400)));
|
|
163
188
|
return feePool;
|
|
164
189
|
}
|
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
|
|
|
@@ -47,7 +48,8 @@ export type PriceImpactUnit =
|
|
|
47
48
|
export function calculateTradeSlippage(
|
|
48
49
|
direction: PositionDirection,
|
|
49
50
|
amount: BN,
|
|
50
|
-
market: Market
|
|
51
|
+
market: Market,
|
|
52
|
+
inputAssetType: AssetType = 'quote',
|
|
51
53
|
): [BN, BN, BN, BN] {
|
|
52
54
|
const oldPrice = calculateMarkPrice(market);
|
|
53
55
|
if (amount.eq(ZERO)) {
|
|
@@ -56,7 +58,8 @@ export function calculateTradeSlippage(
|
|
|
56
58
|
const [acquiredBase, acquiredQuote] = calculateTradeAcquiredAmounts(
|
|
57
59
|
direction,
|
|
58
60
|
amount,
|
|
59
|
-
market
|
|
61
|
+
market,
|
|
62
|
+
inputAssetType
|
|
60
63
|
);
|
|
61
64
|
|
|
62
65
|
const entryPrice = calculatePrice(
|
|
@@ -103,7 +106,8 @@ export function calculateTradeSlippage(
|
|
|
103
106
|
export function calculateTradeAcquiredAmounts(
|
|
104
107
|
direction: PositionDirection,
|
|
105
108
|
amount: BN,
|
|
106
|
-
market: Market
|
|
109
|
+
market: Market,
|
|
110
|
+
inputAssetType: AssetType = 'quote',
|
|
107
111
|
): [BN, BN] {
|
|
108
112
|
if (amount.eq(ZERO)) {
|
|
109
113
|
return [ZERO, ZERO];
|
|
@@ -112,9 +116,9 @@ export function calculateTradeAcquiredAmounts(
|
|
|
112
116
|
const [newQuoteAssetReserve, newBaseAssetReserve] =
|
|
113
117
|
calculateAmmReservesAfterSwap(
|
|
114
118
|
market.amm,
|
|
115
|
-
|
|
119
|
+
inputAssetType,
|
|
116
120
|
amount,
|
|
117
|
-
getSwapDirection(
|
|
121
|
+
getSwapDirection(inputAssetType, direction)
|
|
118
122
|
);
|
|
119
123
|
|
|
120
124
|
const acquiredBase = market.amm.baseAssetReserve.sub(newBaseAssetReserve);
|