@drift-labs/sdk 2.8.0-beta.2 → 2.9.0-beta.0
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/dlob/DLOB.d.ts +1 -1
- package/lib/dlob/DLOB.js +18 -2
- package/lib/driftClient.d.ts +2 -0
- package/lib/driftClient.js +20 -0
- package/lib/idl/drift.json +27 -1
- package/lib/tx/retryTxSender.js +7 -7
- package/package.json +1 -1
- package/src/dlob/DLOB.ts +31 -2
- package/src/driftClient.ts +34 -0
- package/src/idl/drift.json +27 -1
- package/src/tx/retryTxSender.ts +7 -7
- package/tests/dlob/test.ts +10 -8
package/lib/dlob/DLOB.d.ts
CHANGED
|
@@ -67,7 +67,7 @@ export declare class DLOB {
|
|
|
67
67
|
getLimitBids(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData): Generator<DLOBNode>;
|
|
68
68
|
getAsks(marketIndex: number, fallbackAsk: BN | undefined, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData): Generator<DLOBNode>;
|
|
69
69
|
getBids(marketIndex: number, fallbackBid: BN | undefined, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData): Generator<DLOBNode>;
|
|
70
|
-
findCrossingLimitOrders(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData): NodeToFill[];
|
|
70
|
+
findCrossingLimitOrders(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, fallbackAsk: BN | undefined, fallbackBid: BN | undefined): NodeToFill[];
|
|
71
71
|
determineMakerAndTaker(askNode: DLOBNode, bidNode: DLOBNode): {
|
|
72
72
|
takerNode: DLOBNode;
|
|
73
73
|
makerNode: DLOBNode;
|
package/lib/dlob/DLOB.js
CHANGED
|
@@ -261,7 +261,7 @@ class DLOB {
|
|
|
261
261
|
}
|
|
262
262
|
findLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, fallbackAsk, fallbackBid) {
|
|
263
263
|
const nodesToFill = new Array();
|
|
264
|
-
const crossingNodes = this.findCrossingLimitOrders(marketIndex, slot, marketType, oraclePriceData);
|
|
264
|
+
const crossingNodes = this.findCrossingLimitOrders(marketIndex, slot, marketType, oraclePriceData, fallbackAsk, fallbackBid);
|
|
265
265
|
for (const crossingNode of crossingNodes) {
|
|
266
266
|
nodesToFill.push(crossingNode);
|
|
267
267
|
}
|
|
@@ -584,7 +584,7 @@ class DLOB {
|
|
|
584
584
|
return bestPrice.gt(currentPrice);
|
|
585
585
|
});
|
|
586
586
|
}
|
|
587
|
-
findCrossingLimitOrders(marketIndex, slot, marketType, oraclePriceData) {
|
|
587
|
+
findCrossingLimitOrders(marketIndex, slot, marketType, oraclePriceData, fallbackAsk, fallbackBid) {
|
|
588
588
|
const nodesToFill = new Array();
|
|
589
589
|
for (const askNode of this.getLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
|
|
590
590
|
for (const bidNode of this.getLimitBids(marketIndex, slot, marketType, oraclePriceData)) {
|
|
@@ -602,6 +602,22 @@ class DLOB {
|
|
|
602
602
|
continue;
|
|
603
603
|
}
|
|
604
604
|
const { takerNode, makerNode } = this.determineMakerAndTaker(askNode, bidNode);
|
|
605
|
+
// extra guard against bad fills for limit orders where auction is incomplete
|
|
606
|
+
if (!(0, __1.isAuctionComplete)(takerNode.order, slot)) {
|
|
607
|
+
let bidPrice;
|
|
608
|
+
let askPrice;
|
|
609
|
+
if ((0, __1.isVariant)(takerNode.order.direction, 'long')) {
|
|
610
|
+
bidPrice = __1.BN.min(takerNode.getPrice(oraclePriceData, slot), fallbackAsk || __1.BN_MAX);
|
|
611
|
+
askPrice = makerNode.getPrice(oraclePriceData, slot);
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
bidPrice = makerNode.getPrice(oraclePriceData, slot);
|
|
615
|
+
askPrice = __1.BN.max(takerNode.getPrice(oraclePriceData, slot), fallbackBid || __1.ZERO);
|
|
616
|
+
}
|
|
617
|
+
if (bidPrice.lt(askPrice)) {
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
605
621
|
const bidBaseRemaining = bidOrder.baseAssetAmount.sub(bidOrder.baseAssetAmountFilled);
|
|
606
622
|
const askBaseRemaining = askOrder.baseAssetAmount.sub(askOrder.baseAssetAmountFilled);
|
|
607
623
|
const baseFilled = __1.BN.min(bidBaseRemaining, askBaseRemaining);
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -194,6 +194,8 @@ export declare class DriftClient {
|
|
|
194
194
|
addSerumRemainingAccounts(marketIndex: number, remainingAccounts: AccountMeta[], fulfillmentConfig: SerumV3FulfillmentConfigAccount): void;
|
|
195
195
|
triggerOrder(userAccountPublicKey: PublicKey, user: UserAccount, order: Order): Promise<TransactionSignature>;
|
|
196
196
|
getTriggerOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order): Promise<TransactionInstruction>;
|
|
197
|
+
forceCancelOrders(userAccountPublicKey: PublicKey, user: UserAccount): Promise<TransactionSignature>;
|
|
198
|
+
getForceCancelOrdersIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
|
|
197
199
|
placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
|
|
198
200
|
getPlaceAndTakePerpOrderIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
|
|
199
201
|
placeAndMakePerpOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
|
package/lib/driftClient.js
CHANGED
|
@@ -1484,6 +1484,26 @@ class DriftClient {
|
|
|
1484
1484
|
remainingAccounts,
|
|
1485
1485
|
});
|
|
1486
1486
|
}
|
|
1487
|
+
async forceCancelOrders(userAccountPublicKey, user) {
|
|
1488
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getForceCancelOrdersIx(userAccountPublicKey, user)), [], this.opts);
|
|
1489
|
+
return txSig;
|
|
1490
|
+
}
|
|
1491
|
+
async getForceCancelOrdersIx(userAccountPublicKey, userAccount) {
|
|
1492
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1493
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1494
|
+
userAccounts: [userAccount],
|
|
1495
|
+
writableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
|
|
1496
|
+
});
|
|
1497
|
+
return await this.program.instruction.forceCancelOrders({
|
|
1498
|
+
accounts: {
|
|
1499
|
+
state: await this.getStatePublicKey(),
|
|
1500
|
+
filler: fillerPublicKey,
|
|
1501
|
+
user: userAccountPublicKey,
|
|
1502
|
+
authority: this.wallet.publicKey,
|
|
1503
|
+
},
|
|
1504
|
+
remainingAccounts,
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1487
1507
|
async placeAndTakePerpOrder(orderParams, makerInfo, referrerInfo) {
|
|
1488
1508
|
const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo)), [], this.opts);
|
|
1489
1509
|
this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
package/lib/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.9.0-beta.0",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -946,6 +946,32 @@
|
|
|
946
946
|
}
|
|
947
947
|
]
|
|
948
948
|
},
|
|
949
|
+
{
|
|
950
|
+
"name": "forceCancelOrders",
|
|
951
|
+
"accounts": [
|
|
952
|
+
{
|
|
953
|
+
"name": "state",
|
|
954
|
+
"isMut": false,
|
|
955
|
+
"isSigner": false
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
"name": "authority",
|
|
959
|
+
"isMut": false,
|
|
960
|
+
"isSigner": true
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
"name": "filler",
|
|
964
|
+
"isMut": true,
|
|
965
|
+
"isSigner": false
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
"name": "user",
|
|
969
|
+
"isMut": true,
|
|
970
|
+
"isSigner": false
|
|
971
|
+
}
|
|
972
|
+
],
|
|
973
|
+
"args": []
|
|
974
|
+
},
|
|
949
975
|
{
|
|
950
976
|
"name": "settlePnl",
|
|
951
977
|
"accounts": [
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -22,10 +22,10 @@ class RetryTxSender {
|
|
|
22
22
|
if (opts === undefined) {
|
|
23
23
|
opts = this.provider.opts;
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const rawTransaction =
|
|
25
|
+
const signedTx = preSigned
|
|
26
|
+
? tx
|
|
27
|
+
: await this.prepareTx(tx, additionalSigners, opts);
|
|
28
|
+
const rawTransaction = signedTx.serialize();
|
|
29
29
|
const startTime = this.getTimestamp();
|
|
30
30
|
let txid;
|
|
31
31
|
try {
|
|
@@ -77,13 +77,13 @@ class RetryTxSender {
|
|
|
77
77
|
async prepareTx(tx, additionalSigners, opts) {
|
|
78
78
|
tx.feePayer = this.provider.wallet.publicKey;
|
|
79
79
|
tx.recentBlockhash = (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash;
|
|
80
|
-
await this.provider.wallet.signTransaction(tx);
|
|
80
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
81
81
|
additionalSigners
|
|
82
82
|
.filter((s) => s !== undefined)
|
|
83
83
|
.forEach((kp) => {
|
|
84
|
-
|
|
84
|
+
signedTx.partialSign(kp);
|
|
85
85
|
});
|
|
86
|
-
return
|
|
86
|
+
return signedTx;
|
|
87
87
|
}
|
|
88
88
|
async confirmTransaction(signature, commitment) {
|
|
89
89
|
let decodedSignature;
|
package/package.json
CHANGED
package/src/dlob/DLOB.ts
CHANGED
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
UserMap,
|
|
27
27
|
OrderRecord,
|
|
28
28
|
OrderActionRecord,
|
|
29
|
+
ZERO,
|
|
30
|
+
BN_MAX,
|
|
29
31
|
} from '..';
|
|
30
32
|
import { PublicKey } from '@solana/web3.js';
|
|
31
33
|
import { DLOBNode, DLOBNodeType, TriggerOrderNode } from '..';
|
|
@@ -440,7 +442,9 @@ export class DLOB {
|
|
|
440
442
|
marketIndex,
|
|
441
443
|
slot,
|
|
442
444
|
marketType,
|
|
443
|
-
oraclePriceData
|
|
445
|
+
oraclePriceData,
|
|
446
|
+
fallbackAsk,
|
|
447
|
+
fallbackBid
|
|
444
448
|
);
|
|
445
449
|
|
|
446
450
|
for (const crossingNode of crossingNodes) {
|
|
@@ -1009,7 +1013,9 @@ export class DLOB {
|
|
|
1009
1013
|
marketIndex: number,
|
|
1010
1014
|
slot: number,
|
|
1011
1015
|
marketType: MarketType,
|
|
1012
|
-
oraclePriceData: OraclePriceData
|
|
1016
|
+
oraclePriceData: OraclePriceData,
|
|
1017
|
+
fallbackAsk: BN | undefined,
|
|
1018
|
+
fallbackBid: BN | undefined
|
|
1013
1019
|
): NodeToFill[] {
|
|
1014
1020
|
const nodesToFill = new Array<NodeToFill>();
|
|
1015
1021
|
|
|
@@ -1047,6 +1053,29 @@ export class DLOB {
|
|
|
1047
1053
|
bidNode
|
|
1048
1054
|
);
|
|
1049
1055
|
|
|
1056
|
+
// extra guard against bad fills for limit orders where auction is incomplete
|
|
1057
|
+
if (!isAuctionComplete(takerNode.order, slot)) {
|
|
1058
|
+
let bidPrice: BN;
|
|
1059
|
+
let askPrice: BN;
|
|
1060
|
+
if (isVariant(takerNode.order.direction, 'long')) {
|
|
1061
|
+
bidPrice = BN.min(
|
|
1062
|
+
takerNode.getPrice(oraclePriceData, slot),
|
|
1063
|
+
fallbackAsk || BN_MAX
|
|
1064
|
+
);
|
|
1065
|
+
askPrice = makerNode.getPrice(oraclePriceData, slot);
|
|
1066
|
+
} else {
|
|
1067
|
+
bidPrice = makerNode.getPrice(oraclePriceData, slot);
|
|
1068
|
+
askPrice = BN.max(
|
|
1069
|
+
takerNode.getPrice(oraclePriceData, slot),
|
|
1070
|
+
fallbackBid || ZERO
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
if (bidPrice.lt(askPrice)) {
|
|
1075
|
+
continue;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1050
1079
|
const bidBaseRemaining = bidOrder.baseAssetAmount.sub(
|
|
1051
1080
|
bidOrder.baseAssetAmountFilled
|
|
1052
1081
|
);
|
package/src/driftClient.ts
CHANGED
|
@@ -2470,6 +2470,40 @@ export class DriftClient {
|
|
|
2470
2470
|
});
|
|
2471
2471
|
}
|
|
2472
2472
|
|
|
2473
|
+
public async forceCancelOrders(
|
|
2474
|
+
userAccountPublicKey: PublicKey,
|
|
2475
|
+
user: UserAccount
|
|
2476
|
+
): Promise<TransactionSignature> {
|
|
2477
|
+
const { txSig } = await this.txSender.send(
|
|
2478
|
+
wrapInTx(await this.getForceCancelOrdersIx(userAccountPublicKey, user)),
|
|
2479
|
+
[],
|
|
2480
|
+
this.opts
|
|
2481
|
+
);
|
|
2482
|
+
return txSig;
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
public async getForceCancelOrdersIx(
|
|
2486
|
+
userAccountPublicKey: PublicKey,
|
|
2487
|
+
userAccount: UserAccount
|
|
2488
|
+
): Promise<TransactionInstruction> {
|
|
2489
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
2490
|
+
|
|
2491
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2492
|
+
userAccounts: [userAccount],
|
|
2493
|
+
writableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX],
|
|
2494
|
+
});
|
|
2495
|
+
|
|
2496
|
+
return await this.program.instruction.forceCancelOrders({
|
|
2497
|
+
accounts: {
|
|
2498
|
+
state: await this.getStatePublicKey(),
|
|
2499
|
+
filler: fillerPublicKey,
|
|
2500
|
+
user: userAccountPublicKey,
|
|
2501
|
+
authority: this.wallet.publicKey,
|
|
2502
|
+
},
|
|
2503
|
+
remainingAccounts,
|
|
2504
|
+
});
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2473
2507
|
public async placeAndTakePerpOrder(
|
|
2474
2508
|
orderParams: OptionalOrderParams,
|
|
2475
2509
|
makerInfo?: MakerInfo,
|
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.9.0-beta.0",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -946,6 +946,32 @@
|
|
|
946
946
|
}
|
|
947
947
|
]
|
|
948
948
|
},
|
|
949
|
+
{
|
|
950
|
+
"name": "forceCancelOrders",
|
|
951
|
+
"accounts": [
|
|
952
|
+
{
|
|
953
|
+
"name": "state",
|
|
954
|
+
"isMut": false,
|
|
955
|
+
"isSigner": false
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
"name": "authority",
|
|
959
|
+
"isMut": false,
|
|
960
|
+
"isSigner": true
|
|
961
|
+
},
|
|
962
|
+
{
|
|
963
|
+
"name": "filler",
|
|
964
|
+
"isMut": true,
|
|
965
|
+
"isSigner": false
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
"name": "user",
|
|
969
|
+
"isMut": true,
|
|
970
|
+
"isSigner": false
|
|
971
|
+
}
|
|
972
|
+
],
|
|
973
|
+
"args": []
|
|
974
|
+
},
|
|
949
975
|
{
|
|
950
976
|
"name": "settlePnl",
|
|
951
977
|
"accounts": [
|
package/src/tx/retryTxSender.ts
CHANGED
|
@@ -52,11 +52,11 @@ export class RetryTxSender implements TxSender {
|
|
|
52
52
|
opts = this.provider.opts;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const signedTx = preSigned
|
|
56
|
+
? tx
|
|
57
|
+
: await this.prepareTx(tx, additionalSigners, opts);
|
|
58
58
|
|
|
59
|
-
const rawTransaction =
|
|
59
|
+
const rawTransaction = signedTx.serialize();
|
|
60
60
|
const startTime = this.getTimestamp();
|
|
61
61
|
|
|
62
62
|
let txid: TransactionSignature;
|
|
@@ -123,14 +123,14 @@ export class RetryTxSender implements TxSender {
|
|
|
123
123
|
)
|
|
124
124
|
).blockhash;
|
|
125
125
|
|
|
126
|
-
await this.provider.wallet.signTransaction(tx);
|
|
126
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
127
127
|
additionalSigners
|
|
128
128
|
.filter((s): s is Signer => s !== undefined)
|
|
129
129
|
.forEach((kp) => {
|
|
130
|
-
|
|
130
|
+
signedTx.partialSign(kp);
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
-
return
|
|
133
|
+
return signedTx;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
async confirmTransaction(
|
package/tests/dlob/test.ts
CHANGED
|
@@ -369,14 +369,16 @@ describe('DLOB Tests', () => {
|
|
|
369
369
|
expect(b).to.equal(3);
|
|
370
370
|
|
|
371
371
|
dlob.clear();
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
372
|
+
|
|
373
|
+
const bids1 = dlob.getBids(
|
|
374
|
+
marketIndex,
|
|
375
|
+
undefined,
|
|
376
|
+
0,
|
|
377
|
+
MarketType.PERP,
|
|
378
|
+
oracle
|
|
379
|
+
);
|
|
380
|
+
bids1.next();
|
|
381
|
+
expect(bids1.next().done, 'bid generator should be done').to.equal(true);
|
|
380
382
|
});
|
|
381
383
|
|
|
382
384
|
it('DLOB orders', () => {
|