@drift-labs/sdk 2.31.0-beta.4 → 2.31.0-beta.6
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/config.js +2 -2
- package/lib/dlob/orderBookLevels.d.ts +1 -1
- package/lib/dlob/orderBookLevels.js +7 -4
- package/lib/idl/drift.json +1 -1
- package/lib/math/trade.d.ts +9 -0
- package/lib/math/trade.js +59 -1
- package/lib/memcmp.d.ts +1 -0
- package/lib/memcmp.js +10 -1
- package/lib/tx/retryTxSender.js +13 -4
- package/lib/user.d.ts +1 -1
- package/lib/user.js +10 -11
- package/package.json +1 -1
- package/src/config.ts +6 -3
- package/src/dlob/orderBookLevels.ts +13 -4
- package/src/idl/drift.json +1 -1
- package/src/math/trade.ts +88 -0
- package/src/memcmp.ts +9 -0
- package/src/tx/retryTxSender.ts +14 -7
- package/src/user.ts +17 -15
package/lib/config.js
CHANGED
|
@@ -78,8 +78,8 @@ async function findAllMarketAndOracles(program) {
|
|
|
78
78
|
const perpMarketIndexes = [];
|
|
79
79
|
const spotMarketIndexes = [];
|
|
80
80
|
const oracleInfos = new Map();
|
|
81
|
-
const perpMarketProgramAccounts = await program.account.perpMarket.all();
|
|
82
|
-
const spotMarketProgramAccounts = await program.account.spotMarket.all();
|
|
81
|
+
const perpMarketProgramAccounts = (await program.account.perpMarket.all());
|
|
82
|
+
const spotMarketProgramAccounts = (await program.account.spotMarket.all());
|
|
83
83
|
for (const perpMarketProgramAccount of perpMarketProgramAccounts) {
|
|
84
84
|
const perpMarket = perpMarketProgramAccount.account;
|
|
85
85
|
perpMarketIndexes.push(perpMarket.marketIndex);
|
|
@@ -41,5 +41,5 @@ export declare function getVammL2Generator({ marketAccount, oraclePriceData, num
|
|
|
41
41
|
numOrders: number;
|
|
42
42
|
now?: BN;
|
|
43
43
|
}): L2OrderBookGenerator;
|
|
44
|
-
export declare function groupL2(l2: L2OrderBook, grouping: BN): L2OrderBook;
|
|
44
|
+
export declare function groupL2(l2: L2OrderBook, grouping: BN, depth: number): L2OrderBook;
|
|
45
45
|
export {};
|
|
@@ -135,14 +135,14 @@ function getVammL2Generator({ marketAccount, oraclePriceData, numOrders, now, })
|
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
137
|
exports.getVammL2Generator = getVammL2Generator;
|
|
138
|
-
function groupL2(l2, grouping) {
|
|
138
|
+
function groupL2(l2, grouping, depth) {
|
|
139
139
|
return {
|
|
140
|
-
bids: groupL2Levels(l2.bids, grouping, __1.PositionDirection.LONG),
|
|
141
|
-
asks: groupL2Levels(l2.asks, grouping, __1.PositionDirection.SHORT),
|
|
140
|
+
bids: groupL2Levels(l2.bids, grouping, __1.PositionDirection.LONG, depth),
|
|
141
|
+
asks: groupL2Levels(l2.asks, grouping, __1.PositionDirection.SHORT, depth),
|
|
142
142
|
};
|
|
143
143
|
}
|
|
144
144
|
exports.groupL2 = groupL2;
|
|
145
|
-
function groupL2Levels(levels, grouping, direction) {
|
|
145
|
+
function groupL2Levels(levels, grouping, direction, depth) {
|
|
146
146
|
const groupedLevels = [];
|
|
147
147
|
for (const level of levels) {
|
|
148
148
|
const price = (0, __1.standardizePrice)(level.price, grouping, direction);
|
|
@@ -168,6 +168,9 @@ function groupL2Levels(levels, grouping, direction) {
|
|
|
168
168
|
};
|
|
169
169
|
groupedLevels.push(groupedLevel);
|
|
170
170
|
}
|
|
171
|
+
if (groupedLevels.length === depth) {
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
171
174
|
}
|
|
172
175
|
return groupedLevels;
|
|
173
176
|
}
|
package/lib/idl/drift.json
CHANGED
package/lib/math/trade.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { OraclePriceData } from '../oracles/types';
|
|
|
5
5
|
import { DLOB } from '../dlob/DLOB';
|
|
6
6
|
import { PublicKey } from '@solana/web3.js';
|
|
7
7
|
import { Orderbook } from '@project-serum/serum';
|
|
8
|
+
import { L2OrderBook } from '../dlob/orderBookLevels';
|
|
8
9
|
export type PriceImpactUnit = 'entryPrice' | 'maxPrice' | 'priceDelta' | 'priceDeltaAsNumber' | 'pctAvg' | 'pctMax' | 'quoteAssetAmount' | 'quoteAssetAmountPeg' | 'acquiredBaseAssetAmount' | 'acquiredQuoteAssetAmount' | 'all';
|
|
9
10
|
/**
|
|
10
11
|
* Calculates avg/max slippage (price impact) for candidate trade
|
|
@@ -104,3 +105,11 @@ export declare function calculateEstimatedSpotEntryPrice(assetType: AssetType, a
|
|
|
104
105
|
baseFilled: BN;
|
|
105
106
|
quoteFilled: BN;
|
|
106
107
|
};
|
|
108
|
+
export declare function calculateEstimatedEntryPriceWithL2(assetType: AssetType, amount: BN, direction: PositionDirection, basePrecision: BN, l2: L2OrderBook): {
|
|
109
|
+
entryPrice: BN;
|
|
110
|
+
priceImpact: BN;
|
|
111
|
+
bestPrice: BN;
|
|
112
|
+
worstPrice: BN;
|
|
113
|
+
baseFilled: BN;
|
|
114
|
+
quoteFilled: BN;
|
|
115
|
+
};
|
package/lib/math/trade.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.calculateEstimatedSpotEntryPrice = exports.calculateEstimatedPerpEntryPrice = exports.calculateTargetPriceTrade = exports.calculateTradeAcquiredAmounts = exports.calculateTradeSlippage = void 0;
|
|
3
|
+
exports.calculateEstimatedEntryPriceWithL2 = exports.calculateEstimatedSpotEntryPrice = exports.calculateEstimatedPerpEntryPrice = exports.calculateTargetPriceTrade = exports.calculateTradeAcquiredAmounts = exports.calculateTradeSlippage = void 0;
|
|
4
4
|
const types_1 = require("../types");
|
|
5
5
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
6
6
|
const assert_1 = require("../assert/assert");
|
|
@@ -571,3 +571,61 @@ function calculateEstimatedSpotEntryPrice(assetType, amount, direction, market,
|
|
|
571
571
|
};
|
|
572
572
|
}
|
|
573
573
|
exports.calculateEstimatedSpotEntryPrice = calculateEstimatedSpotEntryPrice;
|
|
574
|
+
function calculateEstimatedEntryPriceWithL2(assetType, amount, direction, basePrecision, l2) {
|
|
575
|
+
const takerIsLong = (0, types_2.isVariant)(direction, 'long');
|
|
576
|
+
let cumulativeBaseFilled = numericConstants_1.ZERO;
|
|
577
|
+
let cumulativeQuoteFilled = numericConstants_1.ZERO;
|
|
578
|
+
const levels = [...(takerIsLong ? l2.asks : l2.bids)];
|
|
579
|
+
let nextLevel = levels.shift();
|
|
580
|
+
let bestPrice;
|
|
581
|
+
let worstPrice;
|
|
582
|
+
if (nextLevel) {
|
|
583
|
+
bestPrice = nextLevel.price;
|
|
584
|
+
worstPrice = nextLevel.price;
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
bestPrice = takerIsLong ? numericConstants_1.BN_MAX : numericConstants_1.ZERO;
|
|
588
|
+
worstPrice = bestPrice;
|
|
589
|
+
}
|
|
590
|
+
if (assetType === 'base') {
|
|
591
|
+
while (!cumulativeBaseFilled.eq(amount) && nextLevel) {
|
|
592
|
+
const price = nextLevel.price;
|
|
593
|
+
const size = nextLevel.size;
|
|
594
|
+
worstPrice = price;
|
|
595
|
+
const baseFilled = anchor_1.BN.min(size, amount.sub(cumulativeBaseFilled));
|
|
596
|
+
const quoteFilled = baseFilled.mul(price).div(basePrecision);
|
|
597
|
+
cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
|
|
598
|
+
cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
|
|
599
|
+
nextLevel = levels.shift();
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
while (!cumulativeQuoteFilled.eq(amount) && nextLevel) {
|
|
604
|
+
const price = nextLevel.price;
|
|
605
|
+
const size = nextLevel.size;
|
|
606
|
+
worstPrice = price;
|
|
607
|
+
const quoteFilled = anchor_1.BN.min(size.mul(price).div(basePrecision), amount.sub(cumulativeQuoteFilled));
|
|
608
|
+
const baseFilled = quoteFilled.mul(basePrecision).div(price);
|
|
609
|
+
cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
|
|
610
|
+
cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
|
|
611
|
+
nextLevel = levels.shift();
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
const entryPrice = cumulativeQuoteFilled
|
|
615
|
+
.mul(basePrecision)
|
|
616
|
+
.div(cumulativeBaseFilled);
|
|
617
|
+
const priceImpact = entryPrice
|
|
618
|
+
.sub(bestPrice)
|
|
619
|
+
.mul(numericConstants_1.PRICE_PRECISION)
|
|
620
|
+
.div(bestPrice)
|
|
621
|
+
.abs();
|
|
622
|
+
return {
|
|
623
|
+
entryPrice,
|
|
624
|
+
priceImpact,
|
|
625
|
+
bestPrice,
|
|
626
|
+
worstPrice,
|
|
627
|
+
baseFilled: cumulativeBaseFilled,
|
|
628
|
+
quoteFilled: cumulativeQuoteFilled,
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
exports.calculateEstimatedEntryPriceWithL2 = calculateEstimatedEntryPriceWithL2;
|
package/lib/memcmp.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export declare function getUserFilter(): MemcmpFilter;
|
|
|
3
3
|
export declare function getNonIdleUserFilter(): MemcmpFilter;
|
|
4
4
|
export declare function getUserWithOrderFilter(): MemcmpFilter;
|
|
5
5
|
export declare function getUserWithAuctionFilter(): MemcmpFilter;
|
|
6
|
+
export declare function getUserThatHasBeenLP(): MemcmpFilter;
|
package/lib/memcmp.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getUserWithAuctionFilter = exports.getUserWithOrderFilter = exports.getNonIdleUserFilter = exports.getUserFilter = void 0;
|
|
6
|
+
exports.getUserThatHasBeenLP = exports.getUserWithAuctionFilter = exports.getUserWithOrderFilter = exports.getNonIdleUserFilter = exports.getUserFilter = void 0;
|
|
7
7
|
const bs58_1 = __importDefault(require("bs58"));
|
|
8
8
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
9
9
|
function getUserFilter() {
|
|
@@ -42,3 +42,12 @@ function getUserWithAuctionFilter() {
|
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
44
|
exports.getUserWithAuctionFilter = getUserWithAuctionFilter;
|
|
45
|
+
function getUserThatHasBeenLP() {
|
|
46
|
+
return {
|
|
47
|
+
memcmp: {
|
|
48
|
+
offset: 4267,
|
|
49
|
+
bytes: bs58_1.default.encode(Uint8Array.from([99])),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
exports.getUserThatHasBeenLP = getUserThatHasBeenLP;
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -55,11 +55,20 @@ class RetryTxSender {
|
|
|
55
55
|
return tx;
|
|
56
56
|
}
|
|
57
57
|
async sendVersionedTransaction(tx, additionalSigners, opts) {
|
|
58
|
-
|
|
59
|
-
tx.sign([kp]);
|
|
60
|
-
});
|
|
58
|
+
let signedTx;
|
|
61
59
|
// @ts-ignore
|
|
62
|
-
|
|
60
|
+
if (this.provider.wallet.payer) {
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
tx.sign((additionalSigners !== null && additionalSigners !== void 0 ? additionalSigners : []).concat(this.provider.wallet.payer));
|
|
63
|
+
signedTx = tx;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
additionalSigners === null || additionalSigners === void 0 ? void 0 : additionalSigners.filter((s) => s !== undefined).forEach((kp) => {
|
|
67
|
+
tx.sign([kp]);
|
|
68
|
+
});
|
|
69
|
+
// @ts-ignore
|
|
70
|
+
signedTx = await this.provider.wallet.signTransaction(tx);
|
|
71
|
+
}
|
|
63
72
|
if (opts === undefined) {
|
|
64
73
|
opts = this.provider.opts;
|
|
65
74
|
}
|
package/lib/user.d.ts
CHANGED
|
@@ -82,7 +82,7 @@ export declare class User {
|
|
|
82
82
|
* @returns : the dust base asset amount (ie, < stepsize)
|
|
83
83
|
* @returns : pnl from settle
|
|
84
84
|
*/
|
|
85
|
-
|
|
85
|
+
getPerpPositionWithLPSettle(marketIndex: number, originalPosition?: PerpPosition): [PerpPosition, BN, BN];
|
|
86
86
|
/**
|
|
87
87
|
* calculates Buying Power = free collateral / initial margin ratio
|
|
88
88
|
* @returns : Precision QUOTE_PRECISION
|
package/lib/user.js
CHANGED
|
@@ -175,12 +175,12 @@ class User {
|
|
|
175
175
|
* @returns : the dust base asset amount (ie, < stepsize)
|
|
176
176
|
* @returns : pnl from settle
|
|
177
177
|
*/
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return [position, numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
178
|
+
getPerpPositionWithLPSettle(marketIndex, originalPosition) {
|
|
179
|
+
originalPosition = originalPosition !== null && originalPosition !== void 0 ? originalPosition : this.getPerpPosition(marketIndex);
|
|
180
|
+
if (originalPosition.lpShares.eq(numericConstants_1.ZERO)) {
|
|
181
|
+
return [originalPosition, numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
183
182
|
}
|
|
183
|
+
const position = this.getClonedPosition(originalPosition);
|
|
184
184
|
const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
|
|
185
185
|
const nShares = position.lpShares;
|
|
186
186
|
const deltaBaa = market.amm.baseAssetAmountPerLp
|
|
@@ -192,11 +192,10 @@ class User {
|
|
|
192
192
|
.mul(nShares)
|
|
193
193
|
.div(numericConstants_1.AMM_RESERVE_PRECISION);
|
|
194
194
|
function sign(v) {
|
|
195
|
-
|
|
196
|
-
return sign;
|
|
195
|
+
return v.isNeg() ? new _1.BN(-1) : new _1.BN(1);
|
|
197
196
|
}
|
|
198
|
-
function standardize(amount,
|
|
199
|
-
const remainder = amount.abs().mod(
|
|
197
|
+
function standardize(amount, stepSize) {
|
|
198
|
+
const remainder = amount.abs().mod(stepSize).mul(sign(amount));
|
|
200
199
|
const standardizedAmount = amount.sub(remainder);
|
|
201
200
|
return [standardizedAmount, remainder];
|
|
202
201
|
}
|
|
@@ -319,7 +318,7 @@ class User {
|
|
|
319
318
|
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(market.quoteSpotMarketIndex);
|
|
320
319
|
const quoteOraclePriceData = this.getOracleDataForSpotMarket(market.quoteSpotMarketIndex);
|
|
321
320
|
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
322
|
-
perpPosition = this.
|
|
321
|
+
perpPosition = this.getPerpPositionWithLPSettle(perpPosition.marketIndex)[0];
|
|
323
322
|
}
|
|
324
323
|
let positionUnrealizedPnl = (0, _1.calculatePositionPNL)(market, perpPosition, withFunding, oraclePriceData);
|
|
325
324
|
let quotePrice;
|
|
@@ -546,7 +545,7 @@ class User {
|
|
|
546
545
|
// clone so we dont mutate the position
|
|
547
546
|
perpPosition = this.getClonedPosition(perpPosition);
|
|
548
547
|
// settle position
|
|
549
|
-
const [settledPosition, dustBaa, _] = this.
|
|
548
|
+
const [settledPosition, dustBaa, _] = this.getPerpPositionWithLPSettle(market.marketIndex);
|
|
550
549
|
perpPosition.baseAssetAmount =
|
|
551
550
|
settledPosition.baseAssetAmount.add(dustBaa);
|
|
552
551
|
perpPosition.quoteAssetAmount = settledPosition.quoteAssetAmount;
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PerpMarketAccount, SpotMarketAccount } from '.';
|
|
1
2
|
import {
|
|
2
3
|
DevnetPerpMarkets,
|
|
3
4
|
MainnetPerpMarkets,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
MainnetSpotMarkets,
|
|
12
13
|
} from './constants/spotMarkets';
|
|
13
14
|
import { OracleInfo } from './oracles/types';
|
|
14
|
-
import { Program } from '@coral-xyz/anchor';
|
|
15
|
+
import { Program, ProgramAccount } from '@coral-xyz/anchor';
|
|
15
16
|
|
|
16
17
|
type DriftConfig = {
|
|
17
18
|
ENV: DriftEnv;
|
|
@@ -124,8 +125,10 @@ export async function findAllMarketAndOracles(program: Program): Promise<{
|
|
|
124
125
|
const spotMarketIndexes = [];
|
|
125
126
|
const oracleInfos = new Map<string, OracleInfo>();
|
|
126
127
|
|
|
127
|
-
const perpMarketProgramAccounts =
|
|
128
|
-
|
|
128
|
+
const perpMarketProgramAccounts =
|
|
129
|
+
(await program.account.perpMarket.all()) as ProgramAccount<PerpMarketAccount>[];
|
|
130
|
+
const spotMarketProgramAccounts =
|
|
131
|
+
(await program.account.spotMarket.all()) as ProgramAccount<SpotMarketAccount>[];
|
|
129
132
|
|
|
130
133
|
for (const perpMarketProgramAccount of perpMarketProgramAccounts) {
|
|
131
134
|
const perpMarket = perpMarketProgramAccount.account;
|
|
@@ -244,17 +244,22 @@ export function getVammL2Generator({
|
|
|
244
244
|
};
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
export function groupL2(
|
|
247
|
+
export function groupL2(
|
|
248
|
+
l2: L2OrderBook,
|
|
249
|
+
grouping: BN,
|
|
250
|
+
depth: number
|
|
251
|
+
): L2OrderBook {
|
|
248
252
|
return {
|
|
249
|
-
bids: groupL2Levels(l2.bids, grouping, PositionDirection.LONG),
|
|
250
|
-
asks: groupL2Levels(l2.asks, grouping, PositionDirection.SHORT),
|
|
253
|
+
bids: groupL2Levels(l2.bids, grouping, PositionDirection.LONG, depth),
|
|
254
|
+
asks: groupL2Levels(l2.asks, grouping, PositionDirection.SHORT, depth),
|
|
251
255
|
};
|
|
252
256
|
}
|
|
253
257
|
|
|
254
258
|
function groupL2Levels(
|
|
255
259
|
levels: L2Level[],
|
|
256
260
|
grouping: BN,
|
|
257
|
-
direction: PositionDirection
|
|
261
|
+
direction: PositionDirection,
|
|
262
|
+
depth: number
|
|
258
263
|
): L2Level[] {
|
|
259
264
|
const groupedLevels = [];
|
|
260
265
|
for (const level of levels) {
|
|
@@ -281,6 +286,10 @@ function groupL2Levels(
|
|
|
281
286
|
};
|
|
282
287
|
groupedLevels.push(groupedLevel);
|
|
283
288
|
}
|
|
289
|
+
|
|
290
|
+
if (groupedLevels.length === depth) {
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
284
293
|
}
|
|
285
294
|
return groupedLevels;
|
|
286
295
|
}
|
package/src/idl/drift.json
CHANGED
package/src/math/trade.ts
CHANGED
|
@@ -34,6 +34,7 @@ import { OraclePriceData } from '../oracles/types';
|
|
|
34
34
|
import { DLOB } from '../dlob/DLOB';
|
|
35
35
|
import { PublicKey } from '@solana/web3.js';
|
|
36
36
|
import { Orderbook } from '@project-serum/serum';
|
|
37
|
+
import { L2OrderBook } from '../dlob/orderBookLevels';
|
|
37
38
|
|
|
38
39
|
const MAXPCT = new BN(1000); //percentage units are [0,1000] => [0,1]
|
|
39
40
|
|
|
@@ -884,3 +885,90 @@ export function calculateEstimatedSpotEntryPrice(
|
|
|
884
885
|
quoteFilled: cumulativeQuoteFilled,
|
|
885
886
|
};
|
|
886
887
|
}
|
|
888
|
+
|
|
889
|
+
export function calculateEstimatedEntryPriceWithL2(
|
|
890
|
+
assetType: AssetType,
|
|
891
|
+
amount: BN,
|
|
892
|
+
direction: PositionDirection,
|
|
893
|
+
basePrecision: BN,
|
|
894
|
+
l2: L2OrderBook
|
|
895
|
+
): {
|
|
896
|
+
entryPrice: BN;
|
|
897
|
+
priceImpact: BN;
|
|
898
|
+
bestPrice: BN;
|
|
899
|
+
worstPrice: BN;
|
|
900
|
+
baseFilled: BN;
|
|
901
|
+
quoteFilled: BN;
|
|
902
|
+
} {
|
|
903
|
+
const takerIsLong = isVariant(direction, 'long');
|
|
904
|
+
|
|
905
|
+
let cumulativeBaseFilled = ZERO;
|
|
906
|
+
let cumulativeQuoteFilled = ZERO;
|
|
907
|
+
|
|
908
|
+
const levels = [...(takerIsLong ? l2.asks : l2.bids)];
|
|
909
|
+
let nextLevel = levels.shift();
|
|
910
|
+
|
|
911
|
+
let bestPrice;
|
|
912
|
+
let worstPrice;
|
|
913
|
+
if (nextLevel) {
|
|
914
|
+
bestPrice = nextLevel.price;
|
|
915
|
+
worstPrice = nextLevel.price;
|
|
916
|
+
} else {
|
|
917
|
+
bestPrice = takerIsLong ? BN_MAX : ZERO;
|
|
918
|
+
worstPrice = bestPrice;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
if (assetType === 'base') {
|
|
922
|
+
while (!cumulativeBaseFilled.eq(amount) && nextLevel) {
|
|
923
|
+
const price = nextLevel.price;
|
|
924
|
+
const size = nextLevel.size;
|
|
925
|
+
|
|
926
|
+
worstPrice = price;
|
|
927
|
+
|
|
928
|
+
const baseFilled = BN.min(size, amount.sub(cumulativeBaseFilled));
|
|
929
|
+
const quoteFilled = baseFilled.mul(price).div(basePrecision);
|
|
930
|
+
|
|
931
|
+
cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
|
|
932
|
+
cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
|
|
933
|
+
|
|
934
|
+
nextLevel = levels.shift();
|
|
935
|
+
}
|
|
936
|
+
} else {
|
|
937
|
+
while (!cumulativeQuoteFilled.eq(amount) && nextLevel) {
|
|
938
|
+
const price = nextLevel.price;
|
|
939
|
+
const size = nextLevel.size;
|
|
940
|
+
|
|
941
|
+
worstPrice = price;
|
|
942
|
+
|
|
943
|
+
const quoteFilled = BN.min(
|
|
944
|
+
size.mul(price).div(basePrecision),
|
|
945
|
+
amount.sub(cumulativeQuoteFilled)
|
|
946
|
+
);
|
|
947
|
+
const baseFilled = quoteFilled.mul(basePrecision).div(price);
|
|
948
|
+
|
|
949
|
+
cumulativeBaseFilled = cumulativeBaseFilled.add(baseFilled);
|
|
950
|
+
cumulativeQuoteFilled = cumulativeQuoteFilled.add(quoteFilled);
|
|
951
|
+
|
|
952
|
+
nextLevel = levels.shift();
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
const entryPrice = cumulativeQuoteFilled
|
|
957
|
+
.mul(basePrecision)
|
|
958
|
+
.div(cumulativeBaseFilled);
|
|
959
|
+
|
|
960
|
+
const priceImpact = entryPrice
|
|
961
|
+
.sub(bestPrice)
|
|
962
|
+
.mul(PRICE_PRECISION)
|
|
963
|
+
.div(bestPrice)
|
|
964
|
+
.abs();
|
|
965
|
+
|
|
966
|
+
return {
|
|
967
|
+
entryPrice,
|
|
968
|
+
priceImpact,
|
|
969
|
+
bestPrice,
|
|
970
|
+
worstPrice,
|
|
971
|
+
baseFilled: cumulativeBaseFilled,
|
|
972
|
+
quoteFilled: cumulativeQuoteFilled,
|
|
973
|
+
};
|
|
974
|
+
}
|
package/src/memcmp.ts
CHANGED
package/src/tx/retryTxSender.ts
CHANGED
|
@@ -119,14 +119,21 @@ export class RetryTxSender implements TxSender {
|
|
|
119
119
|
additionalSigners?: Array<Signer>,
|
|
120
120
|
opts?: ConfirmOptions
|
|
121
121
|
): Promise<TxSigAndSlot> {
|
|
122
|
-
|
|
123
|
-
?.filter((s): s is Signer => s !== undefined)
|
|
124
|
-
.forEach((kp) => {
|
|
125
|
-
tx.sign([kp]);
|
|
126
|
-
});
|
|
127
|
-
|
|
122
|
+
let signedTx;
|
|
128
123
|
// @ts-ignore
|
|
129
|
-
|
|
124
|
+
if (this.provider.wallet.payer) {
|
|
125
|
+
// @ts-ignore
|
|
126
|
+
tx.sign((additionalSigners ?? []).concat(this.provider.wallet.payer));
|
|
127
|
+
signedTx = tx;
|
|
128
|
+
} else {
|
|
129
|
+
additionalSigners
|
|
130
|
+
?.filter((s): s is Signer => s !== undefined)
|
|
131
|
+
.forEach((kp) => {
|
|
132
|
+
tx.sign([kp]);
|
|
133
|
+
});
|
|
134
|
+
// @ts-ignore
|
|
135
|
+
signedTx = await this.provider.wallet.signTransaction(tx);
|
|
136
|
+
}
|
|
130
137
|
|
|
131
138
|
if (opts === undefined) {
|
|
132
139
|
opts = this.provider.opts;
|
package/src/user.ts
CHANGED
|
@@ -297,14 +297,18 @@ export class User {
|
|
|
297
297
|
* @returns : the dust base asset amount (ie, < stepsize)
|
|
298
298
|
* @returns : pnl from settle
|
|
299
299
|
*/
|
|
300
|
-
public
|
|
301
|
-
|
|
302
|
-
|
|
300
|
+
public getPerpPositionWithLPSettle(
|
|
301
|
+
marketIndex: number,
|
|
302
|
+
originalPosition?: PerpPosition
|
|
303
|
+
): [PerpPosition, BN, BN] {
|
|
304
|
+
originalPosition = originalPosition ?? this.getPerpPosition(marketIndex);
|
|
303
305
|
|
|
304
|
-
if (
|
|
305
|
-
return [
|
|
306
|
+
if (originalPosition.lpShares.eq(ZERO)) {
|
|
307
|
+
return [originalPosition, ZERO, ZERO];
|
|
306
308
|
}
|
|
307
309
|
|
|
310
|
+
const position = this.getClonedPosition(originalPosition);
|
|
311
|
+
|
|
308
312
|
const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
|
|
309
313
|
const nShares = position.lpShares;
|
|
310
314
|
|
|
@@ -318,14 +322,11 @@ export class User {
|
|
|
318
322
|
.div(AMM_RESERVE_PRECISION);
|
|
319
323
|
|
|
320
324
|
function sign(v: BN) {
|
|
321
|
-
|
|
322
|
-
v.gte(ZERO).toString()
|
|
323
|
-
];
|
|
324
|
-
return sign;
|
|
325
|
+
return v.isNeg() ? new BN(-1) : new BN(1);
|
|
325
326
|
}
|
|
326
327
|
|
|
327
|
-
function standardize(amount: BN,
|
|
328
|
-
const remainder = amount.abs().mod(
|
|
328
|
+
function standardize(amount: BN, stepSize: BN) {
|
|
329
|
+
const remainder = amount.abs().mod(stepSize).mul(sign(amount));
|
|
329
330
|
const standardizedAmount = amount.sub(remainder);
|
|
330
331
|
return [standardizedAmount, remainder];
|
|
331
332
|
}
|
|
@@ -517,7 +518,9 @@ export class User {
|
|
|
517
518
|
);
|
|
518
519
|
|
|
519
520
|
if (perpPosition.lpShares.gt(ZERO)) {
|
|
520
|
-
perpPosition = this.
|
|
521
|
+
perpPosition = this.getPerpPositionWithLPSettle(
|
|
522
|
+
perpPosition.marketIndex
|
|
523
|
+
)[0];
|
|
521
524
|
}
|
|
522
525
|
|
|
523
526
|
let positionUnrealizedPnl = calculatePositionPNL(
|
|
@@ -1022,9 +1025,8 @@ export class User {
|
|
|
1022
1025
|
perpPosition = this.getClonedPosition(perpPosition);
|
|
1023
1026
|
|
|
1024
1027
|
// settle position
|
|
1025
|
-
const [settledPosition, dustBaa, _] =
|
|
1026
|
-
market.marketIndex
|
|
1027
|
-
);
|
|
1028
|
+
const [settledPosition, dustBaa, _] =
|
|
1029
|
+
this.getPerpPositionWithLPSettle(market.marketIndex);
|
|
1028
1030
|
perpPosition.baseAssetAmount =
|
|
1029
1031
|
settledPosition.baseAssetAmount.add(dustBaa);
|
|
1030
1032
|
perpPosition.quoteAssetAmount = settledPosition.quoteAssetAmount;
|