@drift-labs/sdk 2.108.0-beta.13 → 2.108.0-beta.15
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/VERSION +1 -1
- package/lib/browser/constants/spotMarkets.js +12 -0
- package/lib/browser/dlob/DLOB.d.ts +6 -2
- package/lib/browser/dlob/DLOB.js +31 -23
- package/lib/browser/dlob/DLOBNode.d.ts +10 -7
- package/lib/browser/dlob/DLOBNode.js +25 -12
- package/lib/browser/dlob/NodeList.d.ts +1 -1
- package/lib/browser/dlob/NodeList.js +2 -2
- package/lib/node/constants/spotMarkets.js +12 -0
- package/lib/node/dlob/DLOB.d.ts +6 -2
- package/lib/node/dlob/DLOB.js +31 -23
- package/lib/node/dlob/DLOBNode.d.ts +10 -7
- package/lib/node/dlob/DLOBNode.js +25 -12
- package/lib/node/dlob/NodeList.d.ts +1 -1
- package/lib/node/dlob/NodeList.js +2 -2
- package/package.json +1 -1
- package/src/constants/spotMarkets.ts +13 -0
- package/src/dlob/DLOB.ts +53 -58
- package/src/dlob/DLOBNode.ts +46 -23
- package/src/dlob/NodeList.ts +4 -2
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.108.0-beta.
|
|
1
|
+
2.108.0-beta.15
|
|
@@ -568,6 +568,18 @@ exports.MainnetSpotMarkets = [
|
|
|
568
568
|
pythFeedId: '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
|
|
569
569
|
launchTs: 1737360280000,
|
|
570
570
|
},
|
|
571
|
+
{
|
|
572
|
+
symbol: 'AUSD',
|
|
573
|
+
marketIndex: 38,
|
|
574
|
+
poolId: 0,
|
|
575
|
+
oracle: new web3_js_1.PublicKey('8FZhpiM8n3mpgvENWLcEvHsKB1bBhYBAyL4Ypr4gptLZ'),
|
|
576
|
+
oracleSource: __1.OracleSource.PYTH_STABLE_COIN_PULL,
|
|
577
|
+
mint: new web3_js_1.PublicKey('AUSD1jCcCyPLybk1YnvPWsHQSrZ46dxwoMniN4N2UEB9'),
|
|
578
|
+
precision: new __1.BN(10).pow(numericConstants_1.SIX),
|
|
579
|
+
precisionExp: numericConstants_1.SIX,
|
|
580
|
+
pythFeedId: '0xd9912df360b5b7f21a122f15bdd5e27f62ce5e72bd316c291f7c86620e07fb2a',
|
|
581
|
+
launchTs: 1738255943000,
|
|
582
|
+
},
|
|
571
583
|
];
|
|
572
584
|
exports.SpotMarkets = {
|
|
573
585
|
devnet: exports.DevnetSpotMarkets,
|
|
@@ -17,6 +17,10 @@ export type MarketNodeLists = {
|
|
|
17
17
|
ask: NodeList<'floatingLimit'>;
|
|
18
18
|
bid: NodeList<'floatingLimit'>;
|
|
19
19
|
};
|
|
20
|
+
protectedFloatingLimit: {
|
|
21
|
+
ask: NodeList<'protectedFloatingLimit'>;
|
|
22
|
+
bid: NodeList<'protectedFloatingLimit'>;
|
|
23
|
+
};
|
|
20
24
|
takingLimit: {
|
|
21
25
|
ask: NodeList<'takingLimit'>;
|
|
22
26
|
bid: NodeList<'takingLimit'>;
|
|
@@ -67,8 +71,8 @@ export declare class DLOB {
|
|
|
67
71
|
insertOrder(order: Order, userAccount: string, slot: number, isUserProtectedMaker: boolean, onInsert?: OrderBookCallback): void;
|
|
68
72
|
insertSwiftOrder(order: Order, userAccount: string, isUserProtectedMaker: boolean, onInsert?: OrderBookCallback): void;
|
|
69
73
|
addOrderList(marketType: MarketTypeStr, marketIndex: number): void;
|
|
70
|
-
delete(order: Order, userAccount: PublicKey, slot: number, onDelete?: OrderBookCallback): void;
|
|
71
|
-
getListForOnChainOrder(order: Order, slot: number): NodeList<any> | undefined;
|
|
74
|
+
delete(order: Order, userAccount: PublicKey, slot: number, isUserProtectedMaker: boolean, onDelete?: OrderBookCallback): void;
|
|
75
|
+
getListForOnChainOrder(order: Order, slot: number, isProtectedMaker: boolean): NodeList<any> | undefined;
|
|
72
76
|
updateRestingLimitOrders(slot: number): void;
|
|
73
77
|
updateRestingLimitOrdersForMarketType(slot: number, marketTypeStr: MarketTypeStr): void;
|
|
74
78
|
getOrder(orderId: number, userAccount: PublicKey): Order | undefined;
|
package/lib/browser/dlob/DLOB.js
CHANGED
|
@@ -88,7 +88,7 @@ class DLOB {
|
|
|
88
88
|
.get(marketType)
|
|
89
89
|
.add((0, NodeList_1.getOrderSignature)(order.orderId, userAccount));
|
|
90
90
|
}
|
|
91
|
-
(_a = this.getListForOnChainOrder(order, slot)) === null || _a === void 0 ? void 0 : _a.insert(order, marketType, userAccount, isUserProtectedMaker);
|
|
91
|
+
(_a = this.getListForOnChainOrder(order, slot, isUserProtectedMaker)) === null || _a === void 0 ? void 0 : _a.insert(order, marketType, userAccount, isUserProtectedMaker, this.protectedMakerView);
|
|
92
92
|
if (onInsert) {
|
|
93
93
|
onInsert();
|
|
94
94
|
}
|
|
@@ -106,7 +106,7 @@ class DLOB {
|
|
|
106
106
|
this.orderLists
|
|
107
107
|
.get(marketType)
|
|
108
108
|
.get(marketIndex)
|
|
109
|
-
.swift[bidOrAsk].insert(order, marketType, userAccount, isUserProtectedMaker);
|
|
109
|
+
.swift[bidOrAsk].insert(order, marketType, userAccount, isUserProtectedMaker, this.protectedMakerView);
|
|
110
110
|
if (onInsert) {
|
|
111
111
|
onInsert();
|
|
112
112
|
}
|
|
@@ -121,6 +121,10 @@ class DLOB {
|
|
|
121
121
|
ask: new NodeList_1.NodeList('floatingLimit', 'asc'),
|
|
122
122
|
bid: new NodeList_1.NodeList('floatingLimit', 'desc'),
|
|
123
123
|
},
|
|
124
|
+
protectedFloatingLimit: {
|
|
125
|
+
ask: new NodeList_1.NodeList('protectedFloatingLimit', 'asc'),
|
|
126
|
+
bid: new NodeList_1.NodeList('protectedFloatingLimit', 'desc'),
|
|
127
|
+
},
|
|
124
128
|
takingLimit: {
|
|
125
129
|
ask: new NodeList_1.NodeList('takingLimit', 'asc'),
|
|
126
130
|
bid: new NodeList_1.NodeList('takingLimit', 'asc'), // always sort ascending for market orders
|
|
@@ -139,18 +143,18 @@ class DLOB {
|
|
|
139
143
|
},
|
|
140
144
|
});
|
|
141
145
|
}
|
|
142
|
-
delete(order, userAccount, slot, onDelete) {
|
|
146
|
+
delete(order, userAccount, slot, isUserProtectedMaker, onDelete) {
|
|
143
147
|
var _a;
|
|
144
148
|
if ((0, __1.isVariant)(order.status, 'init')) {
|
|
145
149
|
return;
|
|
146
150
|
}
|
|
147
151
|
this.updateRestingLimitOrders(slot);
|
|
148
|
-
(_a = this.getListForOnChainOrder(order, slot)) === null || _a === void 0 ? void 0 : _a.remove(order, userAccount.toString());
|
|
152
|
+
(_a = this.getListForOnChainOrder(order, slot, isUserProtectedMaker)) === null || _a === void 0 ? void 0 : _a.remove(order, userAccount.toString());
|
|
149
153
|
if (onDelete) {
|
|
150
154
|
onDelete();
|
|
151
155
|
}
|
|
152
156
|
}
|
|
153
|
-
getListForOnChainOrder(order, slot) {
|
|
157
|
+
getListForOnChainOrder(order, slot, isProtectedMaker) {
|
|
154
158
|
const isInactiveTriggerOrder = (0, __1.mustBeTriggered)(order) && !(0, __1.isTriggered)(order);
|
|
155
159
|
let type;
|
|
156
160
|
if (isInactiveTriggerOrder) {
|
|
@@ -160,7 +164,7 @@ class DLOB {
|
|
|
160
164
|
type = 'market';
|
|
161
165
|
}
|
|
162
166
|
else if (order.oraclePriceOffset !== 0) {
|
|
163
|
-
type = 'floatingLimit';
|
|
167
|
+
type = isProtectedMaker ? 'protectedFloatingLimit' : 'floatingLimit';
|
|
164
168
|
}
|
|
165
169
|
else {
|
|
166
170
|
const isResting = (0, __1.isRestingLimitOrder)(order, slot);
|
|
@@ -211,7 +215,7 @@ class DLOB {
|
|
|
211
215
|
for (const nodeToUpdate of nodesToUpdate) {
|
|
212
216
|
const { side, node } = nodeToUpdate;
|
|
213
217
|
nodeLists.takingLimit[side].remove(node.order, node.userAccount);
|
|
214
|
-
nodeLists.restingLimit[side].insert(node.order, marketTypeStr, node.userAccount);
|
|
218
|
+
nodeLists.restingLimit[side].insert(node.order, marketTypeStr, node.userAccount, node.isProtectedMaker, this.protectedMakerView);
|
|
215
219
|
}
|
|
216
220
|
}
|
|
217
221
|
}
|
|
@@ -374,7 +378,7 @@ class DLOB {
|
|
|
374
378
|
if (sameUser) {
|
|
375
379
|
continue;
|
|
376
380
|
}
|
|
377
|
-
const makerPrice = makerNode.getPrice(oraclePriceData, slot
|
|
381
|
+
const makerPrice = makerNode.getPrice(oraclePriceData, slot);
|
|
378
382
|
const takerPrice = takerNode.getPrice(oraclePriceData, slot);
|
|
379
383
|
const ordersCross = doesCross(takerPrice, makerPrice);
|
|
380
384
|
if (!ordersCross) {
|
|
@@ -394,11 +398,11 @@ class DLOB {
|
|
|
394
398
|
const newMakerOrder = { ...makerOrder };
|
|
395
399
|
newMakerOrder.baseAssetAmountFilled =
|
|
396
400
|
makerOrder.baseAssetAmountFilled.add(baseFilled);
|
|
397
|
-
this.getListForOnChainOrder(newMakerOrder, slot).update(newMakerOrder, makerNode.userAccount);
|
|
401
|
+
this.getListForOnChainOrder(newMakerOrder, slot, makerNode.isProtectedMaker).update(newMakerOrder, makerNode.userAccount);
|
|
398
402
|
const newTakerOrder = { ...takerOrder };
|
|
399
403
|
newTakerOrder.baseAssetAmountFilled =
|
|
400
404
|
takerOrder.baseAssetAmountFilled.add(baseFilled);
|
|
401
|
-
this.getListForOnChainOrder(newTakerOrder, slot).update(newTakerOrder, takerNode.userAccount);
|
|
405
|
+
this.getListForOnChainOrder(newTakerOrder, slot, takerNode.isProtectedMaker).update(newTakerOrder, takerNode.userAccount);
|
|
402
406
|
if (newTakerOrder.baseAssetAmountFilled.eq(takerOrder.baseAssetAmount)) {
|
|
403
407
|
break;
|
|
404
408
|
}
|
|
@@ -572,8 +576,8 @@ class DLOB {
|
|
|
572
576
|
];
|
|
573
577
|
yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
|
|
574
578
|
return bestNode
|
|
575
|
-
.getPrice(oraclePriceData, slot
|
|
576
|
-
.lt(currentNode.getPrice(oraclePriceData, slot
|
|
579
|
+
.getPrice(oraclePriceData, slot)
|
|
580
|
+
.lt(currentNode.getPrice(oraclePriceData, slot));
|
|
577
581
|
}, filterFcn);
|
|
578
582
|
}
|
|
579
583
|
*getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData, filterFcn) {
|
|
@@ -592,8 +596,8 @@ class DLOB {
|
|
|
592
596
|
];
|
|
593
597
|
yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
|
|
594
598
|
return bestNode
|
|
595
|
-
.getPrice(oraclePriceData, slot
|
|
596
|
-
.gt(currentNode.getPrice(oraclePriceData, slot
|
|
599
|
+
.getPrice(oraclePriceData, slot)
|
|
600
|
+
.gt(currentNode.getPrice(oraclePriceData, slot));
|
|
597
601
|
}, filterFcn);
|
|
598
602
|
}
|
|
599
603
|
/**
|
|
@@ -615,8 +619,8 @@ class DLOB {
|
|
|
615
619
|
];
|
|
616
620
|
yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
|
|
617
621
|
var _a, _b;
|
|
618
|
-
const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot
|
|
619
|
-
const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot
|
|
622
|
+
const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.ZERO;
|
|
623
|
+
const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.ZERO;
|
|
620
624
|
if (bestNodePrice.eq(currentNodePrice)) {
|
|
621
625
|
return bestNode.order.slot.lt(currentNode.order.slot);
|
|
622
626
|
}
|
|
@@ -642,8 +646,8 @@ class DLOB {
|
|
|
642
646
|
];
|
|
643
647
|
yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
|
|
644
648
|
var _a, _b;
|
|
645
|
-
const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot
|
|
646
|
-
const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot
|
|
649
|
+
const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.BN_MAX;
|
|
650
|
+
const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.BN_MAX;
|
|
647
651
|
if (bestNodePrice.eq(currentNodePrice)) {
|
|
648
652
|
return bestNode.order.slot.lt(currentNode.order.slot);
|
|
649
653
|
}
|
|
@@ -655,8 +659,8 @@ class DLOB {
|
|
|
655
659
|
for (const askNode of this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
|
|
656
660
|
const bidGenerator = this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData);
|
|
657
661
|
for (const bidNode of bidGenerator) {
|
|
658
|
-
const bidPrice = bidNode.getPrice(oraclePriceData, slot
|
|
659
|
-
const askPrice = askNode.getPrice(oraclePriceData, slot
|
|
662
|
+
const bidPrice = bidNode.getPrice(oraclePriceData, slot);
|
|
663
|
+
const askPrice = askNode.getPrice(oraclePriceData, slot);
|
|
660
664
|
// orders don't cross
|
|
661
665
|
if (bidPrice.lt(askPrice)) {
|
|
662
666
|
break;
|
|
@@ -680,12 +684,12 @@ class DLOB {
|
|
|
680
684
|
const newBidOrder = { ...bidOrder };
|
|
681
685
|
newBidOrder.baseAssetAmountFilled =
|
|
682
686
|
bidOrder.baseAssetAmountFilled.add(baseFilled);
|
|
683
|
-
this.getListForOnChainOrder(newBidOrder, slot).update(newBidOrder, bidNode.userAccount);
|
|
687
|
+
this.getListForOnChainOrder(newBidOrder, slot, bidNode.isProtectedMaker).update(newBidOrder, bidNode.userAccount);
|
|
684
688
|
// ask completely filled
|
|
685
689
|
const newAskOrder = { ...askOrder };
|
|
686
690
|
newAskOrder.baseAssetAmountFilled =
|
|
687
691
|
askOrder.baseAssetAmountFilled.add(baseFilled);
|
|
688
|
-
this.getListForOnChainOrder(newAskOrder, slot).update(newAskOrder, askNode.userAccount);
|
|
692
|
+
this.getListForOnChainOrder(newAskOrder, slot, askNode.isProtectedMaker).update(newAskOrder, askNode.userAccount);
|
|
689
693
|
nodesToFill.push({
|
|
690
694
|
node: takerNode,
|
|
691
695
|
makerNodes: [makerNode],
|
|
@@ -731,7 +735,7 @@ class DLOB {
|
|
|
731
735
|
getBestAsk(marketIndex, slot, marketType, oraclePriceData) {
|
|
732
736
|
const bestAsk = this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData).next().value;
|
|
733
737
|
if (bestAsk) {
|
|
734
|
-
return bestAsk.getPrice(oraclePriceData, slot
|
|
738
|
+
return bestAsk.getPrice(oraclePriceData, slot);
|
|
735
739
|
}
|
|
736
740
|
return undefined;
|
|
737
741
|
}
|
|
@@ -909,6 +913,8 @@ class DLOB {
|
|
|
909
913
|
yield nodeLists.market.ask;
|
|
910
914
|
yield nodeLists.floatingLimit.bid;
|
|
911
915
|
yield nodeLists.floatingLimit.ask;
|
|
916
|
+
yield nodeLists.protectedFloatingLimit.bid;
|
|
917
|
+
yield nodeLists.protectedFloatingLimit.ask;
|
|
912
918
|
yield nodeLists.trigger.above;
|
|
913
919
|
yield nodeLists.trigger.below;
|
|
914
920
|
}
|
|
@@ -921,6 +927,8 @@ class DLOB {
|
|
|
921
927
|
yield nodeLists.market.ask;
|
|
922
928
|
yield nodeLists.floatingLimit.bid;
|
|
923
929
|
yield nodeLists.floatingLimit.ask;
|
|
930
|
+
yield nodeLists.protectedFloatingLimit.bid;
|
|
931
|
+
yield nodeLists.protectedFloatingLimit.ask;
|
|
924
932
|
yield nodeLists.trigger.above;
|
|
925
933
|
yield nodeLists.trigger.below;
|
|
926
934
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { BN, OraclePriceData, Order } from '..';
|
|
3
3
|
export interface DLOBNode {
|
|
4
|
-
getPrice(oraclePriceData: OraclePriceData, slot: number
|
|
4
|
+
getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
|
|
5
5
|
isVammNode(): boolean;
|
|
6
6
|
order: Order | undefined;
|
|
7
7
|
isBaseFilled(): boolean;
|
|
8
8
|
haveFilled: boolean;
|
|
9
9
|
userAccount: string | undefined;
|
|
10
|
-
|
|
10
|
+
isProtectedMaker: boolean;
|
|
11
|
+
applyProtectedMakerOffset: boolean;
|
|
11
12
|
isSwift: boolean | undefined;
|
|
12
13
|
}
|
|
13
14
|
export declare abstract class OrderNode implements DLOBNode {
|
|
@@ -16,12 +17,13 @@ export declare abstract class OrderNode implements DLOBNode {
|
|
|
16
17
|
sortValue: BN;
|
|
17
18
|
haveFilled: boolean;
|
|
18
19
|
haveTrigger: boolean;
|
|
19
|
-
|
|
20
|
+
isProtectedMaker: boolean;
|
|
21
|
+
applyProtectedMakerOffset: boolean;
|
|
20
22
|
isSwift: boolean;
|
|
21
|
-
constructor(order: Order, userAccount: string,
|
|
23
|
+
constructor(order: Order, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean, isSwift?: boolean);
|
|
22
24
|
abstract getSortValue(order: Order): BN;
|
|
23
25
|
getLabel(): string;
|
|
24
|
-
getPrice(oraclePriceData: OraclePriceData, slot: number
|
|
26
|
+
getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
|
|
25
27
|
isBaseFilled(): boolean;
|
|
26
28
|
isVammNode(): boolean;
|
|
27
29
|
}
|
|
@@ -60,9 +62,10 @@ export type DLOBNodeMap = {
|
|
|
60
62
|
restingLimit: RestingLimitOrderNode;
|
|
61
63
|
takingLimit: TakingLimitOrderNode;
|
|
62
64
|
floatingLimit: FloatingLimitOrderNode;
|
|
65
|
+
protectedFloatingLimit: FloatingLimitOrderNode;
|
|
63
66
|
market: MarketOrderNode;
|
|
64
67
|
trigger: TriggerOrderNode;
|
|
65
68
|
swift: SwiftOrderNode;
|
|
66
69
|
};
|
|
67
|
-
export type DLOBNodeType = 'swift' | 'restingLimit' | 'takingLimit' | 'floatingLimit' | 'market' | ('trigger' & keyof DLOBNodeMap);
|
|
68
|
-
export declare function createNode<T extends DLOBNodeType>(nodeType: T, order: Order, userAccount: string,
|
|
70
|
+
export type DLOBNodeType = 'swift' | 'restingLimit' | 'takingLimit' | 'floatingLimit' | 'protectedFloatingLimit' | 'market' | ('trigger' & keyof DLOBNodeMap);
|
|
71
|
+
export declare function createNode<T extends DLOBNodeType>(nodeType: T, order: Order, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean): DLOBNodeMap[T];
|
|
@@ -5,14 +5,15 @@ const __1 = require("..");
|
|
|
5
5
|
// import { PublicKey } from '@solana/web3.js';
|
|
6
6
|
const NodeList_1 = require("./NodeList");
|
|
7
7
|
class OrderNode {
|
|
8
|
-
constructor(order, userAccount,
|
|
8
|
+
constructor(order, userAccount, isProtectedMaker, applyProtectedMakerOffset, isSwift = false) {
|
|
9
9
|
this.haveFilled = false;
|
|
10
10
|
this.haveTrigger = false;
|
|
11
11
|
// Copy the order over to the node
|
|
12
12
|
this.order = { ...order };
|
|
13
13
|
this.userAccount = userAccount;
|
|
14
14
|
this.sortValue = this.getSortValue(order);
|
|
15
|
-
this.
|
|
15
|
+
this.isProtectedMaker = isProtectedMaker;
|
|
16
|
+
this.applyProtectedMakerOffset = applyProtectedMakerOffset;
|
|
16
17
|
this.isSwift = isSwift;
|
|
17
18
|
}
|
|
18
19
|
getLabel() {
|
|
@@ -28,8 +29,8 @@ class OrderNode {
|
|
|
28
29
|
}
|
|
29
30
|
return msg;
|
|
30
31
|
}
|
|
31
|
-
getPrice(oraclePriceData, slot
|
|
32
|
-
return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined,
|
|
32
|
+
getPrice(oraclePriceData, slot) {
|
|
33
|
+
return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined, this.applyProtectedMakerOffset);
|
|
33
34
|
}
|
|
34
35
|
isBaseFilled() {
|
|
35
36
|
return this.order.baseAssetAmountFilled.eq(this.order.baseAssetAmount);
|
|
@@ -47,7 +48,17 @@ class TakingLimitOrderNode extends OrderNode {
|
|
|
47
48
|
exports.TakingLimitOrderNode = TakingLimitOrderNode;
|
|
48
49
|
class RestingLimitOrderNode extends OrderNode {
|
|
49
50
|
getSortValue(order) {
|
|
50
|
-
|
|
51
|
+
let sortValue = order.price;
|
|
52
|
+
if (this.applyProtectedMakerOffset) {
|
|
53
|
+
const offset = sortValue.divn(1000);
|
|
54
|
+
if ((0, __1.isVariant)(order.direction, 'long')) {
|
|
55
|
+
sortValue = sortValue.sub(offset);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
sortValue = sortValue.add(offset);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return sortValue;
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
64
|
exports.RestingLimitOrderNode = RestingLimitOrderNode;
|
|
@@ -72,25 +83,27 @@ exports.TriggerOrderNode = TriggerOrderNode;
|
|
|
72
83
|
// We'll use the swift uuid for the order id since it's not yet on-chain
|
|
73
84
|
class SwiftOrderNode extends OrderNode {
|
|
74
85
|
constructor(order, userAccount) {
|
|
75
|
-
super(order, userAccount, false, true);
|
|
86
|
+
super(order, userAccount, false, false, true);
|
|
76
87
|
}
|
|
77
88
|
getSortValue(order) {
|
|
78
89
|
return order.slot;
|
|
79
90
|
}
|
|
80
91
|
}
|
|
81
92
|
exports.SwiftOrderNode = SwiftOrderNode;
|
|
82
|
-
function createNode(nodeType, order, userAccount,
|
|
93
|
+
function createNode(nodeType, order, userAccount, isProtectedMaker, applyProtectedMakerOffset) {
|
|
83
94
|
switch (nodeType) {
|
|
84
95
|
case 'floatingLimit':
|
|
85
|
-
return new FloatingLimitOrderNode(order, userAccount,
|
|
96
|
+
return new FloatingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
97
|
+
case 'protectedFloatingLimit':
|
|
98
|
+
return new FloatingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
86
99
|
case 'restingLimit':
|
|
87
|
-
return new RestingLimitOrderNode(order, userAccount,
|
|
100
|
+
return new RestingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
88
101
|
case 'takingLimit':
|
|
89
|
-
return new TakingLimitOrderNode(order, userAccount,
|
|
102
|
+
return new TakingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
90
103
|
case 'market':
|
|
91
|
-
return new MarketOrderNode(order, userAccount,
|
|
104
|
+
return new MarketOrderNode(order, userAccount, isProtectedMaker, false);
|
|
92
105
|
case 'trigger':
|
|
93
|
-
return new TriggerOrderNode(order, userAccount,
|
|
106
|
+
return new TriggerOrderNode(order, userAccount, isProtectedMaker, false);
|
|
94
107
|
case 'swift':
|
|
95
108
|
return new SwiftOrderNode(order, userAccount);
|
|
96
109
|
default:
|
|
@@ -13,7 +13,7 @@ export declare class NodeList<NodeType extends keyof DLOBNodeMap> implements DLO
|
|
|
13
13
|
nodeMap: Map<string, DLOBNodeMap[NodeType]>;
|
|
14
14
|
constructor(nodeType: NodeType, sortDirection: SortDirection);
|
|
15
15
|
clear(): void;
|
|
16
|
-
insert(order: Order, marketType: MarketTypeStr, userAccount: string,
|
|
16
|
+
insert(order: Order, marketType: MarketTypeStr, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean): void;
|
|
17
17
|
prependNode(currentNode: DLOBNodeMap[NodeType], newNode: DLOBNodeMap[NodeType]): boolean;
|
|
18
18
|
update(order: Order, userAccount: string): void;
|
|
19
19
|
remove(order: Order, userAccount: string): void;
|
|
@@ -19,11 +19,11 @@ class NodeList {
|
|
|
19
19
|
this.length = 0;
|
|
20
20
|
this.nodeMap.clear();
|
|
21
21
|
}
|
|
22
|
-
insert(order, marketType, userAccount,
|
|
22
|
+
insert(order, marketType, userAccount, isProtectedMaker, applyProtectedMakerOffset) {
|
|
23
23
|
if ((0, __1.isVariant)(order.status, 'init')) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
-
const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, userAccount,
|
|
26
|
+
const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
27
27
|
const orderSignature = getOrderSignature(order.orderId, userAccount);
|
|
28
28
|
if (this.nodeMap.has(orderSignature)) {
|
|
29
29
|
return;
|
|
@@ -568,6 +568,18 @@ exports.MainnetSpotMarkets = [
|
|
|
568
568
|
pythFeedId: '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
|
|
569
569
|
launchTs: 1737360280000,
|
|
570
570
|
},
|
|
571
|
+
{
|
|
572
|
+
symbol: 'AUSD',
|
|
573
|
+
marketIndex: 38,
|
|
574
|
+
poolId: 0,
|
|
575
|
+
oracle: new web3_js_1.PublicKey('8FZhpiM8n3mpgvENWLcEvHsKB1bBhYBAyL4Ypr4gptLZ'),
|
|
576
|
+
oracleSource: __1.OracleSource.PYTH_STABLE_COIN_PULL,
|
|
577
|
+
mint: new web3_js_1.PublicKey('AUSD1jCcCyPLybk1YnvPWsHQSrZ46dxwoMniN4N2UEB9'),
|
|
578
|
+
precision: new __1.BN(10).pow(numericConstants_1.SIX),
|
|
579
|
+
precisionExp: numericConstants_1.SIX,
|
|
580
|
+
pythFeedId: '0xd9912df360b5b7f21a122f15bdd5e27f62ce5e72bd316c291f7c86620e07fb2a',
|
|
581
|
+
launchTs: 1738255943000,
|
|
582
|
+
},
|
|
571
583
|
];
|
|
572
584
|
exports.SpotMarkets = {
|
|
573
585
|
devnet: exports.DevnetSpotMarkets,
|
package/lib/node/dlob/DLOB.d.ts
CHANGED
|
@@ -17,6 +17,10 @@ export type MarketNodeLists = {
|
|
|
17
17
|
ask: NodeList<'floatingLimit'>;
|
|
18
18
|
bid: NodeList<'floatingLimit'>;
|
|
19
19
|
};
|
|
20
|
+
protectedFloatingLimit: {
|
|
21
|
+
ask: NodeList<'protectedFloatingLimit'>;
|
|
22
|
+
bid: NodeList<'protectedFloatingLimit'>;
|
|
23
|
+
};
|
|
20
24
|
takingLimit: {
|
|
21
25
|
ask: NodeList<'takingLimit'>;
|
|
22
26
|
bid: NodeList<'takingLimit'>;
|
|
@@ -67,8 +71,8 @@ export declare class DLOB {
|
|
|
67
71
|
insertOrder(order: Order, userAccount: string, slot: number, isUserProtectedMaker: boolean, onInsert?: OrderBookCallback): void;
|
|
68
72
|
insertSwiftOrder(order: Order, userAccount: string, isUserProtectedMaker: boolean, onInsert?: OrderBookCallback): void;
|
|
69
73
|
addOrderList(marketType: MarketTypeStr, marketIndex: number): void;
|
|
70
|
-
delete(order: Order, userAccount: PublicKey, slot: number, onDelete?: OrderBookCallback): void;
|
|
71
|
-
getListForOnChainOrder(order: Order, slot: number): NodeList<any> | undefined;
|
|
74
|
+
delete(order: Order, userAccount: PublicKey, slot: number, isUserProtectedMaker: boolean, onDelete?: OrderBookCallback): void;
|
|
75
|
+
getListForOnChainOrder(order: Order, slot: number, isProtectedMaker: boolean): NodeList<any> | undefined;
|
|
72
76
|
updateRestingLimitOrders(slot: number): void;
|
|
73
77
|
updateRestingLimitOrdersForMarketType(slot: number, marketTypeStr: MarketTypeStr): void;
|
|
74
78
|
getOrder(orderId: number, userAccount: PublicKey): Order | undefined;
|
package/lib/node/dlob/DLOB.js
CHANGED
|
@@ -88,7 +88,7 @@ class DLOB {
|
|
|
88
88
|
.get(marketType)
|
|
89
89
|
.add((0, NodeList_1.getOrderSignature)(order.orderId, userAccount));
|
|
90
90
|
}
|
|
91
|
-
(_a = this.getListForOnChainOrder(order, slot)) === null || _a === void 0 ? void 0 : _a.insert(order, marketType, userAccount, isUserProtectedMaker);
|
|
91
|
+
(_a = this.getListForOnChainOrder(order, slot, isUserProtectedMaker)) === null || _a === void 0 ? void 0 : _a.insert(order, marketType, userAccount, isUserProtectedMaker, this.protectedMakerView);
|
|
92
92
|
if (onInsert) {
|
|
93
93
|
onInsert();
|
|
94
94
|
}
|
|
@@ -106,7 +106,7 @@ class DLOB {
|
|
|
106
106
|
this.orderLists
|
|
107
107
|
.get(marketType)
|
|
108
108
|
.get(marketIndex)
|
|
109
|
-
.swift[bidOrAsk].insert(order, marketType, userAccount, isUserProtectedMaker);
|
|
109
|
+
.swift[bidOrAsk].insert(order, marketType, userAccount, isUserProtectedMaker, this.protectedMakerView);
|
|
110
110
|
if (onInsert) {
|
|
111
111
|
onInsert();
|
|
112
112
|
}
|
|
@@ -121,6 +121,10 @@ class DLOB {
|
|
|
121
121
|
ask: new NodeList_1.NodeList('floatingLimit', 'asc'),
|
|
122
122
|
bid: new NodeList_1.NodeList('floatingLimit', 'desc'),
|
|
123
123
|
},
|
|
124
|
+
protectedFloatingLimit: {
|
|
125
|
+
ask: new NodeList_1.NodeList('protectedFloatingLimit', 'asc'),
|
|
126
|
+
bid: new NodeList_1.NodeList('protectedFloatingLimit', 'desc'),
|
|
127
|
+
},
|
|
124
128
|
takingLimit: {
|
|
125
129
|
ask: new NodeList_1.NodeList('takingLimit', 'asc'),
|
|
126
130
|
bid: new NodeList_1.NodeList('takingLimit', 'asc'), // always sort ascending for market orders
|
|
@@ -139,18 +143,18 @@ class DLOB {
|
|
|
139
143
|
},
|
|
140
144
|
});
|
|
141
145
|
}
|
|
142
|
-
delete(order, userAccount, slot, onDelete) {
|
|
146
|
+
delete(order, userAccount, slot, isUserProtectedMaker, onDelete) {
|
|
143
147
|
var _a;
|
|
144
148
|
if ((0, __1.isVariant)(order.status, 'init')) {
|
|
145
149
|
return;
|
|
146
150
|
}
|
|
147
151
|
this.updateRestingLimitOrders(slot);
|
|
148
|
-
(_a = this.getListForOnChainOrder(order, slot)) === null || _a === void 0 ? void 0 : _a.remove(order, userAccount.toString());
|
|
152
|
+
(_a = this.getListForOnChainOrder(order, slot, isUserProtectedMaker)) === null || _a === void 0 ? void 0 : _a.remove(order, userAccount.toString());
|
|
149
153
|
if (onDelete) {
|
|
150
154
|
onDelete();
|
|
151
155
|
}
|
|
152
156
|
}
|
|
153
|
-
getListForOnChainOrder(order, slot) {
|
|
157
|
+
getListForOnChainOrder(order, slot, isProtectedMaker) {
|
|
154
158
|
const isInactiveTriggerOrder = (0, __1.mustBeTriggered)(order) && !(0, __1.isTriggered)(order);
|
|
155
159
|
let type;
|
|
156
160
|
if (isInactiveTriggerOrder) {
|
|
@@ -160,7 +164,7 @@ class DLOB {
|
|
|
160
164
|
type = 'market';
|
|
161
165
|
}
|
|
162
166
|
else if (order.oraclePriceOffset !== 0) {
|
|
163
|
-
type = 'floatingLimit';
|
|
167
|
+
type = isProtectedMaker ? 'protectedFloatingLimit' : 'floatingLimit';
|
|
164
168
|
}
|
|
165
169
|
else {
|
|
166
170
|
const isResting = (0, __1.isRestingLimitOrder)(order, slot);
|
|
@@ -211,7 +215,7 @@ class DLOB {
|
|
|
211
215
|
for (const nodeToUpdate of nodesToUpdate) {
|
|
212
216
|
const { side, node } = nodeToUpdate;
|
|
213
217
|
nodeLists.takingLimit[side].remove(node.order, node.userAccount);
|
|
214
|
-
nodeLists.restingLimit[side].insert(node.order, marketTypeStr, node.userAccount);
|
|
218
|
+
nodeLists.restingLimit[side].insert(node.order, marketTypeStr, node.userAccount, node.isProtectedMaker, this.protectedMakerView);
|
|
215
219
|
}
|
|
216
220
|
}
|
|
217
221
|
}
|
|
@@ -374,7 +378,7 @@ class DLOB {
|
|
|
374
378
|
if (sameUser) {
|
|
375
379
|
continue;
|
|
376
380
|
}
|
|
377
|
-
const makerPrice = makerNode.getPrice(oraclePriceData, slot
|
|
381
|
+
const makerPrice = makerNode.getPrice(oraclePriceData, slot);
|
|
378
382
|
const takerPrice = takerNode.getPrice(oraclePriceData, slot);
|
|
379
383
|
const ordersCross = doesCross(takerPrice, makerPrice);
|
|
380
384
|
if (!ordersCross) {
|
|
@@ -394,11 +398,11 @@ class DLOB {
|
|
|
394
398
|
const newMakerOrder = { ...makerOrder };
|
|
395
399
|
newMakerOrder.baseAssetAmountFilled =
|
|
396
400
|
makerOrder.baseAssetAmountFilled.add(baseFilled);
|
|
397
|
-
this.getListForOnChainOrder(newMakerOrder, slot).update(newMakerOrder, makerNode.userAccount);
|
|
401
|
+
this.getListForOnChainOrder(newMakerOrder, slot, makerNode.isProtectedMaker).update(newMakerOrder, makerNode.userAccount);
|
|
398
402
|
const newTakerOrder = { ...takerOrder };
|
|
399
403
|
newTakerOrder.baseAssetAmountFilled =
|
|
400
404
|
takerOrder.baseAssetAmountFilled.add(baseFilled);
|
|
401
|
-
this.getListForOnChainOrder(newTakerOrder, slot).update(newTakerOrder, takerNode.userAccount);
|
|
405
|
+
this.getListForOnChainOrder(newTakerOrder, slot, takerNode.isProtectedMaker).update(newTakerOrder, takerNode.userAccount);
|
|
402
406
|
if (newTakerOrder.baseAssetAmountFilled.eq(takerOrder.baseAssetAmount)) {
|
|
403
407
|
break;
|
|
404
408
|
}
|
|
@@ -572,8 +576,8 @@ class DLOB {
|
|
|
572
576
|
];
|
|
573
577
|
yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
|
|
574
578
|
return bestNode
|
|
575
|
-
.getPrice(oraclePriceData, slot
|
|
576
|
-
.lt(currentNode.getPrice(oraclePriceData, slot
|
|
579
|
+
.getPrice(oraclePriceData, slot)
|
|
580
|
+
.lt(currentNode.getPrice(oraclePriceData, slot));
|
|
577
581
|
}, filterFcn);
|
|
578
582
|
}
|
|
579
583
|
*getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData, filterFcn) {
|
|
@@ -592,8 +596,8 @@ class DLOB {
|
|
|
592
596
|
];
|
|
593
597
|
yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
|
|
594
598
|
return bestNode
|
|
595
|
-
.getPrice(oraclePriceData, slot
|
|
596
|
-
.gt(currentNode.getPrice(oraclePriceData, slot
|
|
599
|
+
.getPrice(oraclePriceData, slot)
|
|
600
|
+
.gt(currentNode.getPrice(oraclePriceData, slot));
|
|
597
601
|
}, filterFcn);
|
|
598
602
|
}
|
|
599
603
|
/**
|
|
@@ -615,8 +619,8 @@ class DLOB {
|
|
|
615
619
|
];
|
|
616
620
|
yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
|
|
617
621
|
var _a, _b;
|
|
618
|
-
const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot
|
|
619
|
-
const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot
|
|
622
|
+
const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.ZERO;
|
|
623
|
+
const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.ZERO;
|
|
620
624
|
if (bestNodePrice.eq(currentNodePrice)) {
|
|
621
625
|
return bestNode.order.slot.lt(currentNode.order.slot);
|
|
622
626
|
}
|
|
@@ -642,8 +646,8 @@ class DLOB {
|
|
|
642
646
|
];
|
|
643
647
|
yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
|
|
644
648
|
var _a, _b;
|
|
645
|
-
const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot
|
|
646
|
-
const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot
|
|
649
|
+
const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.BN_MAX;
|
|
650
|
+
const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.BN_MAX;
|
|
647
651
|
if (bestNodePrice.eq(currentNodePrice)) {
|
|
648
652
|
return bestNode.order.slot.lt(currentNode.order.slot);
|
|
649
653
|
}
|
|
@@ -655,8 +659,8 @@ class DLOB {
|
|
|
655
659
|
for (const askNode of this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
|
|
656
660
|
const bidGenerator = this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData);
|
|
657
661
|
for (const bidNode of bidGenerator) {
|
|
658
|
-
const bidPrice = bidNode.getPrice(oraclePriceData, slot
|
|
659
|
-
const askPrice = askNode.getPrice(oraclePriceData, slot
|
|
662
|
+
const bidPrice = bidNode.getPrice(oraclePriceData, slot);
|
|
663
|
+
const askPrice = askNode.getPrice(oraclePriceData, slot);
|
|
660
664
|
// orders don't cross
|
|
661
665
|
if (bidPrice.lt(askPrice)) {
|
|
662
666
|
break;
|
|
@@ -680,12 +684,12 @@ class DLOB {
|
|
|
680
684
|
const newBidOrder = { ...bidOrder };
|
|
681
685
|
newBidOrder.baseAssetAmountFilled =
|
|
682
686
|
bidOrder.baseAssetAmountFilled.add(baseFilled);
|
|
683
|
-
this.getListForOnChainOrder(newBidOrder, slot).update(newBidOrder, bidNode.userAccount);
|
|
687
|
+
this.getListForOnChainOrder(newBidOrder, slot, bidNode.isProtectedMaker).update(newBidOrder, bidNode.userAccount);
|
|
684
688
|
// ask completely filled
|
|
685
689
|
const newAskOrder = { ...askOrder };
|
|
686
690
|
newAskOrder.baseAssetAmountFilled =
|
|
687
691
|
askOrder.baseAssetAmountFilled.add(baseFilled);
|
|
688
|
-
this.getListForOnChainOrder(newAskOrder, slot).update(newAskOrder, askNode.userAccount);
|
|
692
|
+
this.getListForOnChainOrder(newAskOrder, slot, askNode.isProtectedMaker).update(newAskOrder, askNode.userAccount);
|
|
689
693
|
nodesToFill.push({
|
|
690
694
|
node: takerNode,
|
|
691
695
|
makerNodes: [makerNode],
|
|
@@ -731,7 +735,7 @@ class DLOB {
|
|
|
731
735
|
getBestAsk(marketIndex, slot, marketType, oraclePriceData) {
|
|
732
736
|
const bestAsk = this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData).next().value;
|
|
733
737
|
if (bestAsk) {
|
|
734
|
-
return bestAsk.getPrice(oraclePriceData, slot
|
|
738
|
+
return bestAsk.getPrice(oraclePriceData, slot);
|
|
735
739
|
}
|
|
736
740
|
return undefined;
|
|
737
741
|
}
|
|
@@ -909,6 +913,8 @@ class DLOB {
|
|
|
909
913
|
yield nodeLists.market.ask;
|
|
910
914
|
yield nodeLists.floatingLimit.bid;
|
|
911
915
|
yield nodeLists.floatingLimit.ask;
|
|
916
|
+
yield nodeLists.protectedFloatingLimit.bid;
|
|
917
|
+
yield nodeLists.protectedFloatingLimit.ask;
|
|
912
918
|
yield nodeLists.trigger.above;
|
|
913
919
|
yield nodeLists.trigger.below;
|
|
914
920
|
}
|
|
@@ -921,6 +927,8 @@ class DLOB {
|
|
|
921
927
|
yield nodeLists.market.ask;
|
|
922
928
|
yield nodeLists.floatingLimit.bid;
|
|
923
929
|
yield nodeLists.floatingLimit.ask;
|
|
930
|
+
yield nodeLists.protectedFloatingLimit.bid;
|
|
931
|
+
yield nodeLists.protectedFloatingLimit.ask;
|
|
924
932
|
yield nodeLists.trigger.above;
|
|
925
933
|
yield nodeLists.trigger.below;
|
|
926
934
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/// <reference types="bn.js" />
|
|
2
2
|
import { BN, OraclePriceData, Order } from '..';
|
|
3
3
|
export interface DLOBNode {
|
|
4
|
-
getPrice(oraclePriceData: OraclePriceData, slot: number
|
|
4
|
+
getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
|
|
5
5
|
isVammNode(): boolean;
|
|
6
6
|
order: Order | undefined;
|
|
7
7
|
isBaseFilled(): boolean;
|
|
8
8
|
haveFilled: boolean;
|
|
9
9
|
userAccount: string | undefined;
|
|
10
|
-
|
|
10
|
+
isProtectedMaker: boolean;
|
|
11
|
+
applyProtectedMakerOffset: boolean;
|
|
11
12
|
isSwift: boolean | undefined;
|
|
12
13
|
}
|
|
13
14
|
export declare abstract class OrderNode implements DLOBNode {
|
|
@@ -16,12 +17,13 @@ export declare abstract class OrderNode implements DLOBNode {
|
|
|
16
17
|
sortValue: BN;
|
|
17
18
|
haveFilled: boolean;
|
|
18
19
|
haveTrigger: boolean;
|
|
19
|
-
|
|
20
|
+
isProtectedMaker: boolean;
|
|
21
|
+
applyProtectedMakerOffset: boolean;
|
|
20
22
|
isSwift: boolean;
|
|
21
|
-
constructor(order: Order, userAccount: string,
|
|
23
|
+
constructor(order: Order, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean, isSwift?: boolean);
|
|
22
24
|
abstract getSortValue(order: Order): BN;
|
|
23
25
|
getLabel(): string;
|
|
24
|
-
getPrice(oraclePriceData: OraclePriceData, slot: number
|
|
26
|
+
getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
|
|
25
27
|
isBaseFilled(): boolean;
|
|
26
28
|
isVammNode(): boolean;
|
|
27
29
|
}
|
|
@@ -60,9 +62,10 @@ export type DLOBNodeMap = {
|
|
|
60
62
|
restingLimit: RestingLimitOrderNode;
|
|
61
63
|
takingLimit: TakingLimitOrderNode;
|
|
62
64
|
floatingLimit: FloatingLimitOrderNode;
|
|
65
|
+
protectedFloatingLimit: FloatingLimitOrderNode;
|
|
63
66
|
market: MarketOrderNode;
|
|
64
67
|
trigger: TriggerOrderNode;
|
|
65
68
|
swift: SwiftOrderNode;
|
|
66
69
|
};
|
|
67
|
-
export type DLOBNodeType = 'swift' | 'restingLimit' | 'takingLimit' | 'floatingLimit' | 'market' | ('trigger' & keyof DLOBNodeMap);
|
|
68
|
-
export declare function createNode<T extends DLOBNodeType>(nodeType: T, order: Order, userAccount: string,
|
|
70
|
+
export type DLOBNodeType = 'swift' | 'restingLimit' | 'takingLimit' | 'floatingLimit' | 'protectedFloatingLimit' | 'market' | ('trigger' & keyof DLOBNodeMap);
|
|
71
|
+
export declare function createNode<T extends DLOBNodeType>(nodeType: T, order: Order, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean): DLOBNodeMap[T];
|
|
@@ -5,14 +5,15 @@ const __1 = require("..");
|
|
|
5
5
|
// import { PublicKey } from '@solana/web3.js';
|
|
6
6
|
const NodeList_1 = require("./NodeList");
|
|
7
7
|
class OrderNode {
|
|
8
|
-
constructor(order, userAccount,
|
|
8
|
+
constructor(order, userAccount, isProtectedMaker, applyProtectedMakerOffset, isSwift = false) {
|
|
9
9
|
this.haveFilled = false;
|
|
10
10
|
this.haveTrigger = false;
|
|
11
11
|
// Copy the order over to the node
|
|
12
12
|
this.order = { ...order };
|
|
13
13
|
this.userAccount = userAccount;
|
|
14
14
|
this.sortValue = this.getSortValue(order);
|
|
15
|
-
this.
|
|
15
|
+
this.isProtectedMaker = isProtectedMaker;
|
|
16
|
+
this.applyProtectedMakerOffset = applyProtectedMakerOffset;
|
|
16
17
|
this.isSwift = isSwift;
|
|
17
18
|
}
|
|
18
19
|
getLabel() {
|
|
@@ -28,8 +29,8 @@ class OrderNode {
|
|
|
28
29
|
}
|
|
29
30
|
return msg;
|
|
30
31
|
}
|
|
31
|
-
getPrice(oraclePriceData, slot
|
|
32
|
-
return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined,
|
|
32
|
+
getPrice(oraclePriceData, slot) {
|
|
33
|
+
return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined, this.applyProtectedMakerOffset);
|
|
33
34
|
}
|
|
34
35
|
isBaseFilled() {
|
|
35
36
|
return this.order.baseAssetAmountFilled.eq(this.order.baseAssetAmount);
|
|
@@ -47,7 +48,17 @@ class TakingLimitOrderNode extends OrderNode {
|
|
|
47
48
|
exports.TakingLimitOrderNode = TakingLimitOrderNode;
|
|
48
49
|
class RestingLimitOrderNode extends OrderNode {
|
|
49
50
|
getSortValue(order) {
|
|
50
|
-
|
|
51
|
+
let sortValue = order.price;
|
|
52
|
+
if (this.applyProtectedMakerOffset) {
|
|
53
|
+
const offset = sortValue.divn(1000);
|
|
54
|
+
if ((0, __1.isVariant)(order.direction, 'long')) {
|
|
55
|
+
sortValue = sortValue.sub(offset);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
sortValue = sortValue.add(offset);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return sortValue;
|
|
51
62
|
}
|
|
52
63
|
}
|
|
53
64
|
exports.RestingLimitOrderNode = RestingLimitOrderNode;
|
|
@@ -72,25 +83,27 @@ exports.TriggerOrderNode = TriggerOrderNode;
|
|
|
72
83
|
// We'll use the swift uuid for the order id since it's not yet on-chain
|
|
73
84
|
class SwiftOrderNode extends OrderNode {
|
|
74
85
|
constructor(order, userAccount) {
|
|
75
|
-
super(order, userAccount, false, true);
|
|
86
|
+
super(order, userAccount, false, false, true);
|
|
76
87
|
}
|
|
77
88
|
getSortValue(order) {
|
|
78
89
|
return order.slot;
|
|
79
90
|
}
|
|
80
91
|
}
|
|
81
92
|
exports.SwiftOrderNode = SwiftOrderNode;
|
|
82
|
-
function createNode(nodeType, order, userAccount,
|
|
93
|
+
function createNode(nodeType, order, userAccount, isProtectedMaker, applyProtectedMakerOffset) {
|
|
83
94
|
switch (nodeType) {
|
|
84
95
|
case 'floatingLimit':
|
|
85
|
-
return new FloatingLimitOrderNode(order, userAccount,
|
|
96
|
+
return new FloatingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
97
|
+
case 'protectedFloatingLimit':
|
|
98
|
+
return new FloatingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
86
99
|
case 'restingLimit':
|
|
87
|
-
return new RestingLimitOrderNode(order, userAccount,
|
|
100
|
+
return new RestingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
88
101
|
case 'takingLimit':
|
|
89
|
-
return new TakingLimitOrderNode(order, userAccount,
|
|
102
|
+
return new TakingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
90
103
|
case 'market':
|
|
91
|
-
return new MarketOrderNode(order, userAccount,
|
|
104
|
+
return new MarketOrderNode(order, userAccount, isProtectedMaker, false);
|
|
92
105
|
case 'trigger':
|
|
93
|
-
return new TriggerOrderNode(order, userAccount,
|
|
106
|
+
return new TriggerOrderNode(order, userAccount, isProtectedMaker, false);
|
|
94
107
|
case 'swift':
|
|
95
108
|
return new SwiftOrderNode(order, userAccount);
|
|
96
109
|
default:
|
|
@@ -13,7 +13,7 @@ export declare class NodeList<NodeType extends keyof DLOBNodeMap> implements DLO
|
|
|
13
13
|
nodeMap: Map<string, DLOBNodeMap[NodeType]>;
|
|
14
14
|
constructor(nodeType: NodeType, sortDirection: SortDirection);
|
|
15
15
|
clear(): void;
|
|
16
|
-
insert(order: Order, marketType: MarketTypeStr, userAccount: string,
|
|
16
|
+
insert(order: Order, marketType: MarketTypeStr, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean): void;
|
|
17
17
|
prependNode(currentNode: DLOBNodeMap[NodeType], newNode: DLOBNodeMap[NodeType]): boolean;
|
|
18
18
|
update(order: Order, userAccount: string): void;
|
|
19
19
|
remove(order: Order, userAccount: string): void;
|
|
@@ -19,11 +19,11 @@ class NodeList {
|
|
|
19
19
|
this.length = 0;
|
|
20
20
|
this.nodeMap.clear();
|
|
21
21
|
}
|
|
22
|
-
insert(order, marketType, userAccount,
|
|
22
|
+
insert(order, marketType, userAccount, isProtectedMaker, applyProtectedMakerOffset) {
|
|
23
23
|
if ((0, __1.isVariant)(order.status, 'init')) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
-
const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, userAccount,
|
|
26
|
+
const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
|
|
27
27
|
const orderSignature = getOrderSignature(order.orderId, userAccount);
|
|
28
28
|
if (this.nodeMap.has(orderSignature)) {
|
|
29
29
|
return;
|
package/package.json
CHANGED
|
@@ -673,6 +673,19 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
673
673
|
'0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
|
|
674
674
|
launchTs: 1737360280000,
|
|
675
675
|
},
|
|
676
|
+
{
|
|
677
|
+
symbol: 'AUSD',
|
|
678
|
+
marketIndex: 38,
|
|
679
|
+
poolId: 0,
|
|
680
|
+
oracle: new PublicKey('8FZhpiM8n3mpgvENWLcEvHsKB1bBhYBAyL4Ypr4gptLZ'),
|
|
681
|
+
oracleSource: OracleSource.PYTH_STABLE_COIN_PULL,
|
|
682
|
+
mint: new PublicKey('AUSD1jCcCyPLybk1YnvPWsHQSrZ46dxwoMniN4N2UEB9'),
|
|
683
|
+
precision: new BN(10).pow(SIX),
|
|
684
|
+
precisionExp: SIX,
|
|
685
|
+
pythFeedId:
|
|
686
|
+
'0xd9912df360b5b7f21a122f15bdd5e27f62ce5e72bd316c291f7c86620e07fb2a',
|
|
687
|
+
launchTs: 1738255943000,
|
|
688
|
+
},
|
|
676
689
|
];
|
|
677
690
|
|
|
678
691
|
export const SpotMarkets: { [key in DriftEnv]: SpotMarketConfig[] } = {
|
package/src/dlob/DLOB.ts
CHANGED
|
@@ -57,6 +57,10 @@ export type MarketNodeLists = {
|
|
|
57
57
|
ask: NodeList<'floatingLimit'>;
|
|
58
58
|
bid: NodeList<'floatingLimit'>;
|
|
59
59
|
};
|
|
60
|
+
protectedFloatingLimit: {
|
|
61
|
+
ask: NodeList<'protectedFloatingLimit'>;
|
|
62
|
+
bid: NodeList<'protectedFloatingLimit'>;
|
|
63
|
+
};
|
|
60
64
|
takingLimit: {
|
|
61
65
|
ask: NodeList<'takingLimit'>;
|
|
62
66
|
bid: NodeList<'takingLimit'>;
|
|
@@ -203,11 +207,12 @@ export class DLOB {
|
|
|
203
207
|
.get(marketType)
|
|
204
208
|
.add(getOrderSignature(order.orderId, userAccount));
|
|
205
209
|
}
|
|
206
|
-
this.getListForOnChainOrder(order, slot)?.insert(
|
|
210
|
+
this.getListForOnChainOrder(order, slot, isUserProtectedMaker)?.insert(
|
|
207
211
|
order,
|
|
208
212
|
marketType,
|
|
209
213
|
userAccount,
|
|
210
|
-
isUserProtectedMaker
|
|
214
|
+
isUserProtectedMaker,
|
|
215
|
+
this.protectedMakerView
|
|
211
216
|
);
|
|
212
217
|
|
|
213
218
|
if (onInsert) {
|
|
@@ -237,7 +242,8 @@ export class DLOB {
|
|
|
237
242
|
order,
|
|
238
243
|
marketType,
|
|
239
244
|
userAccount,
|
|
240
|
-
isUserProtectedMaker
|
|
245
|
+
isUserProtectedMaker,
|
|
246
|
+
this.protectedMakerView
|
|
241
247
|
);
|
|
242
248
|
if (onInsert) {
|
|
243
249
|
onInsert();
|
|
@@ -254,6 +260,10 @@ export class DLOB {
|
|
|
254
260
|
ask: new NodeList('floatingLimit', 'asc'),
|
|
255
261
|
bid: new NodeList('floatingLimit', 'desc'),
|
|
256
262
|
},
|
|
263
|
+
protectedFloatingLimit: {
|
|
264
|
+
ask: new NodeList('protectedFloatingLimit', 'asc'),
|
|
265
|
+
bid: new NodeList('protectedFloatingLimit', 'desc'),
|
|
266
|
+
},
|
|
257
267
|
takingLimit: {
|
|
258
268
|
ask: new NodeList('takingLimit', 'asc'),
|
|
259
269
|
bid: new NodeList('takingLimit', 'asc'), // always sort ascending for market orders
|
|
@@ -277,6 +287,7 @@ export class DLOB {
|
|
|
277
287
|
order: Order,
|
|
278
288
|
userAccount: PublicKey,
|
|
279
289
|
slot: number,
|
|
290
|
+
isUserProtectedMaker: boolean,
|
|
280
291
|
onDelete?: OrderBookCallback
|
|
281
292
|
): void {
|
|
282
293
|
if (isVariant(order.status, 'init')) {
|
|
@@ -285,7 +296,7 @@ export class DLOB {
|
|
|
285
296
|
|
|
286
297
|
this.updateRestingLimitOrders(slot);
|
|
287
298
|
|
|
288
|
-
this.getListForOnChainOrder(order, slot)?.remove(
|
|
299
|
+
this.getListForOnChainOrder(order, slot, isUserProtectedMaker)?.remove(
|
|
289
300
|
order,
|
|
290
301
|
userAccount.toString()
|
|
291
302
|
);
|
|
@@ -297,7 +308,8 @@ export class DLOB {
|
|
|
297
308
|
|
|
298
309
|
public getListForOnChainOrder(
|
|
299
310
|
order: Order,
|
|
300
|
-
slot: number
|
|
311
|
+
slot: number,
|
|
312
|
+
isProtectedMaker: boolean
|
|
301
313
|
): NodeList<any> | undefined {
|
|
302
314
|
const isInactiveTriggerOrder =
|
|
303
315
|
mustBeTriggered(order) && !isTriggered(order);
|
|
@@ -310,7 +322,7 @@ export class DLOB {
|
|
|
310
322
|
) {
|
|
311
323
|
type = 'market';
|
|
312
324
|
} else if (order.oraclePriceOffset !== 0) {
|
|
313
|
-
type = 'floatingLimit';
|
|
325
|
+
type = isProtectedMaker ? 'protectedFloatingLimit' : 'floatingLimit';
|
|
314
326
|
} else {
|
|
315
327
|
const isResting = isRestingLimitOrder(order, slot);
|
|
316
328
|
type = isResting ? 'restingLimit' : 'takingLimit';
|
|
@@ -380,7 +392,9 @@ export class DLOB {
|
|
|
380
392
|
nodeLists.restingLimit[side].insert(
|
|
381
393
|
node.order,
|
|
382
394
|
marketTypeStr,
|
|
383
|
-
node.userAccount
|
|
395
|
+
node.userAccount,
|
|
396
|
+
node.isProtectedMaker,
|
|
397
|
+
this.protectedMakerView
|
|
384
398
|
);
|
|
385
399
|
}
|
|
386
400
|
}
|
|
@@ -765,11 +779,7 @@ export class DLOB {
|
|
|
765
779
|
continue;
|
|
766
780
|
}
|
|
767
781
|
|
|
768
|
-
const makerPrice = makerNode.getPrice(
|
|
769
|
-
oraclePriceData,
|
|
770
|
-
slot,
|
|
771
|
-
this.protectedMakerView
|
|
772
|
-
);
|
|
782
|
+
const makerPrice = makerNode.getPrice(oraclePriceData, slot);
|
|
773
783
|
const takerPrice = takerNode.getPrice(oraclePriceData, slot);
|
|
774
784
|
|
|
775
785
|
const ordersCross = doesCross(takerPrice, makerPrice);
|
|
@@ -799,18 +809,20 @@ export class DLOB {
|
|
|
799
809
|
const newMakerOrder = { ...makerOrder };
|
|
800
810
|
newMakerOrder.baseAssetAmountFilled =
|
|
801
811
|
makerOrder.baseAssetAmountFilled.add(baseFilled);
|
|
802
|
-
this.getListForOnChainOrder(
|
|
812
|
+
this.getListForOnChainOrder(
|
|
803
813
|
newMakerOrder,
|
|
804
|
-
|
|
805
|
-
|
|
814
|
+
slot,
|
|
815
|
+
makerNode.isProtectedMaker
|
|
816
|
+
).update(newMakerOrder, makerNode.userAccount);
|
|
806
817
|
|
|
807
818
|
const newTakerOrder = { ...takerOrder };
|
|
808
819
|
newTakerOrder.baseAssetAmountFilled =
|
|
809
820
|
takerOrder.baseAssetAmountFilled.add(baseFilled);
|
|
810
|
-
this.getListForOnChainOrder(
|
|
821
|
+
this.getListForOnChainOrder(
|
|
811
822
|
newTakerOrder,
|
|
812
|
-
|
|
813
|
-
|
|
823
|
+
slot,
|
|
824
|
+
takerNode.isProtectedMaker
|
|
825
|
+
).update(newTakerOrder, takerNode.userAccount);
|
|
814
826
|
|
|
815
827
|
if (
|
|
816
828
|
newTakerOrder.baseAssetAmountFilled.eq(takerOrder.baseAssetAmount)
|
|
@@ -1089,10 +1101,8 @@ export class DLOB {
|
|
|
1089
1101
|
slot,
|
|
1090
1102
|
(bestNode, currentNode, slot, oraclePriceData) => {
|
|
1091
1103
|
return bestNode
|
|
1092
|
-
.getPrice(oraclePriceData, slot
|
|
1093
|
-
.lt(
|
|
1094
|
-
currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)
|
|
1095
|
-
);
|
|
1104
|
+
.getPrice(oraclePriceData, slot)
|
|
1105
|
+
.lt(currentNode.getPrice(oraclePriceData, slot));
|
|
1096
1106
|
},
|
|
1097
1107
|
filterFcn
|
|
1098
1108
|
);
|
|
@@ -1129,10 +1139,8 @@ export class DLOB {
|
|
|
1129
1139
|
slot,
|
|
1130
1140
|
(bestNode, currentNode, slot, oraclePriceData) => {
|
|
1131
1141
|
return bestNode
|
|
1132
|
-
.getPrice(oraclePriceData, slot
|
|
1133
|
-
.gt(
|
|
1134
|
-
currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)
|
|
1135
|
-
);
|
|
1142
|
+
.getPrice(oraclePriceData, slot)
|
|
1143
|
+
.gt(currentNode.getPrice(oraclePriceData, slot));
|
|
1136
1144
|
},
|
|
1137
1145
|
filterFcn
|
|
1138
1146
|
);
|
|
@@ -1169,15 +1177,9 @@ export class DLOB {
|
|
|
1169
1177
|
oraclePriceData,
|
|
1170
1178
|
slot,
|
|
1171
1179
|
(bestNode, currentNode, slot, oraclePriceData) => {
|
|
1172
|
-
const bestNodePrice =
|
|
1173
|
-
bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView) ??
|
|
1174
|
-
ZERO;
|
|
1180
|
+
const bestNodePrice = bestNode.getPrice(oraclePriceData, slot) ?? ZERO;
|
|
1175
1181
|
const currentNodePrice =
|
|
1176
|
-
currentNode.getPrice(
|
|
1177
|
-
oraclePriceData,
|
|
1178
|
-
slot,
|
|
1179
|
-
this.protectedMakerView
|
|
1180
|
-
) ?? ZERO;
|
|
1182
|
+
currentNode.getPrice(oraclePriceData, slot) ?? ZERO;
|
|
1181
1183
|
|
|
1182
1184
|
if (bestNodePrice.eq(currentNodePrice)) {
|
|
1183
1185
|
return bestNode.order.slot.lt(currentNode.order.slot);
|
|
@@ -1221,14 +1223,9 @@ export class DLOB {
|
|
|
1221
1223
|
slot,
|
|
1222
1224
|
(bestNode, currentNode, slot, oraclePriceData) => {
|
|
1223
1225
|
const bestNodePrice =
|
|
1224
|
-
bestNode.getPrice(oraclePriceData, slot
|
|
1225
|
-
BN_MAX;
|
|
1226
|
+
bestNode.getPrice(oraclePriceData, slot) ?? BN_MAX;
|
|
1226
1227
|
const currentNodePrice =
|
|
1227
|
-
currentNode.getPrice(
|
|
1228
|
-
oraclePriceData,
|
|
1229
|
-
slot,
|
|
1230
|
-
this.protectedMakerView
|
|
1231
|
-
) ?? BN_MAX;
|
|
1228
|
+
currentNode.getPrice(oraclePriceData, slot) ?? BN_MAX;
|
|
1232
1229
|
|
|
1233
1230
|
if (bestNodePrice.eq(currentNodePrice)) {
|
|
1234
1231
|
return bestNode.order.slot.lt(currentNode.order.slot);
|
|
@@ -1262,16 +1259,8 @@ export class DLOB {
|
|
|
1262
1259
|
);
|
|
1263
1260
|
|
|
1264
1261
|
for (const bidNode of bidGenerator) {
|
|
1265
|
-
const bidPrice = bidNode.getPrice(
|
|
1266
|
-
|
|
1267
|
-
slot,
|
|
1268
|
-
this.protectedMakerView
|
|
1269
|
-
);
|
|
1270
|
-
const askPrice = askNode.getPrice(
|
|
1271
|
-
oraclePriceData,
|
|
1272
|
-
slot,
|
|
1273
|
-
this.protectedMakerView
|
|
1274
|
-
);
|
|
1262
|
+
const bidPrice = bidNode.getPrice(oraclePriceData, slot);
|
|
1263
|
+
const askPrice = askNode.getPrice(oraclePriceData, slot);
|
|
1275
1264
|
|
|
1276
1265
|
// orders don't cross
|
|
1277
1266
|
if (bidPrice.lt(askPrice)) {
|
|
@@ -1308,19 +1297,21 @@ export class DLOB {
|
|
|
1308
1297
|
const newBidOrder = { ...bidOrder };
|
|
1309
1298
|
newBidOrder.baseAssetAmountFilled =
|
|
1310
1299
|
bidOrder.baseAssetAmountFilled.add(baseFilled);
|
|
1311
|
-
this.getListForOnChainOrder(
|
|
1300
|
+
this.getListForOnChainOrder(
|
|
1312
1301
|
newBidOrder,
|
|
1313
|
-
|
|
1314
|
-
|
|
1302
|
+
slot,
|
|
1303
|
+
bidNode.isProtectedMaker
|
|
1304
|
+
).update(newBidOrder, bidNode.userAccount);
|
|
1315
1305
|
|
|
1316
1306
|
// ask completely filled
|
|
1317
1307
|
const newAskOrder = { ...askOrder };
|
|
1318
1308
|
newAskOrder.baseAssetAmountFilled =
|
|
1319
1309
|
askOrder.baseAssetAmountFilled.add(baseFilled);
|
|
1320
|
-
this.getListForOnChainOrder(
|
|
1310
|
+
this.getListForOnChainOrder(
|
|
1321
1311
|
newAskOrder,
|
|
1322
|
-
|
|
1323
|
-
|
|
1312
|
+
slot,
|
|
1313
|
+
askNode.isProtectedMaker
|
|
1314
|
+
).update(newAskOrder, askNode.userAccount);
|
|
1324
1315
|
|
|
1325
1316
|
nodesToFill.push({
|
|
1326
1317
|
node: takerNode,
|
|
@@ -1386,7 +1377,7 @@ export class DLOB {
|
|
|
1386
1377
|
).next().value;
|
|
1387
1378
|
|
|
1388
1379
|
if (bestAsk) {
|
|
1389
|
-
return bestAsk.getPrice(oraclePriceData, slot
|
|
1380
|
+
return bestAsk.getPrice(oraclePriceData, slot);
|
|
1390
1381
|
}
|
|
1391
1382
|
return undefined;
|
|
1392
1383
|
}
|
|
@@ -1684,6 +1675,8 @@ export class DLOB {
|
|
|
1684
1675
|
yield nodeLists.market.ask;
|
|
1685
1676
|
yield nodeLists.floatingLimit.bid;
|
|
1686
1677
|
yield nodeLists.floatingLimit.ask;
|
|
1678
|
+
yield nodeLists.protectedFloatingLimit.bid;
|
|
1679
|
+
yield nodeLists.protectedFloatingLimit.ask;
|
|
1687
1680
|
yield nodeLists.trigger.above;
|
|
1688
1681
|
yield nodeLists.trigger.below;
|
|
1689
1682
|
}
|
|
@@ -1697,6 +1690,8 @@ export class DLOB {
|
|
|
1697
1690
|
yield nodeLists.market.ask;
|
|
1698
1691
|
yield nodeLists.floatingLimit.bid;
|
|
1699
1692
|
yield nodeLists.floatingLimit.ask;
|
|
1693
|
+
yield nodeLists.protectedFloatingLimit.bid;
|
|
1694
|
+
yield nodeLists.protectedFloatingLimit.ask;
|
|
1700
1695
|
yield nodeLists.trigger.above;
|
|
1701
1696
|
yield nodeLists.trigger.below;
|
|
1702
1697
|
}
|
package/src/dlob/DLOBNode.ts
CHANGED
|
@@ -13,17 +13,14 @@ import {
|
|
|
13
13
|
import { getOrderSignature } from './NodeList';
|
|
14
14
|
|
|
15
15
|
export interface DLOBNode {
|
|
16
|
-
getPrice(
|
|
17
|
-
oraclePriceData: OraclePriceData,
|
|
18
|
-
slot: number,
|
|
19
|
-
protectedMakerView?: boolean
|
|
20
|
-
): BN;
|
|
16
|
+
getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
|
|
21
17
|
isVammNode(): boolean;
|
|
22
18
|
order: Order | undefined;
|
|
23
19
|
isBaseFilled(): boolean;
|
|
24
20
|
haveFilled: boolean;
|
|
25
21
|
userAccount: string | undefined;
|
|
26
|
-
|
|
22
|
+
isProtectedMaker: boolean;
|
|
23
|
+
applyProtectedMakerOffset: boolean;
|
|
27
24
|
isSwift: boolean | undefined;
|
|
28
25
|
}
|
|
29
26
|
|
|
@@ -33,20 +30,23 @@ export abstract class OrderNode implements DLOBNode {
|
|
|
33
30
|
sortValue: BN;
|
|
34
31
|
haveFilled = false;
|
|
35
32
|
haveTrigger = false;
|
|
36
|
-
|
|
33
|
+
isProtectedMaker: boolean;
|
|
34
|
+
applyProtectedMakerOffset: boolean;
|
|
37
35
|
isSwift: boolean;
|
|
38
36
|
|
|
39
37
|
constructor(
|
|
40
38
|
order: Order,
|
|
41
39
|
userAccount: string,
|
|
42
|
-
|
|
40
|
+
isProtectedMaker: boolean,
|
|
41
|
+
applyProtectedMakerOffset: boolean,
|
|
43
42
|
isSwift = false
|
|
44
43
|
) {
|
|
45
44
|
// Copy the order over to the node
|
|
46
45
|
this.order = { ...order };
|
|
47
46
|
this.userAccount = userAccount;
|
|
48
47
|
this.sortValue = this.getSortValue(order);
|
|
49
|
-
this.
|
|
48
|
+
this.isProtectedMaker = isProtectedMaker;
|
|
49
|
+
this.applyProtectedMakerOffset = applyProtectedMakerOffset;
|
|
50
50
|
this.isSwift = isSwift;
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -79,17 +79,13 @@ export abstract class OrderNode implements DLOBNode {
|
|
|
79
79
|
return msg;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
getPrice(
|
|
83
|
-
oraclePriceData: OraclePriceData,
|
|
84
|
-
slot: number,
|
|
85
|
-
protectedMakerView?: boolean
|
|
86
|
-
): BN {
|
|
82
|
+
getPrice(oraclePriceData: OraclePriceData, slot: number): BN {
|
|
87
83
|
return getLimitPrice(
|
|
88
84
|
this.order,
|
|
89
85
|
oraclePriceData,
|
|
90
86
|
slot,
|
|
91
87
|
undefined,
|
|
92
|
-
|
|
88
|
+
this.applyProtectedMakerOffset
|
|
93
89
|
);
|
|
94
90
|
}
|
|
95
91
|
|
|
@@ -116,7 +112,17 @@ export class RestingLimitOrderNode extends OrderNode {
|
|
|
116
112
|
previous?: RestingLimitOrderNode;
|
|
117
113
|
|
|
118
114
|
getSortValue(order: Order): BN {
|
|
119
|
-
|
|
115
|
+
let sortValue = order.price;
|
|
116
|
+
if (this.applyProtectedMakerOffset) {
|
|
117
|
+
const offset = sortValue.divn(1000);
|
|
118
|
+
|
|
119
|
+
if (isVariant(order.direction, 'long')) {
|
|
120
|
+
sortValue = sortValue.sub(offset);
|
|
121
|
+
} else {
|
|
122
|
+
sortValue = sortValue.add(offset);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return sortValue;
|
|
120
126
|
}
|
|
121
127
|
}
|
|
122
128
|
|
|
@@ -153,7 +159,7 @@ export class SwiftOrderNode extends OrderNode {
|
|
|
153
159
|
previous?: SwiftOrderNode;
|
|
154
160
|
|
|
155
161
|
constructor(order: Order, userAccount: string) {
|
|
156
|
-
super(order, userAccount, false, true);
|
|
162
|
+
super(order, userAccount, false, false, true);
|
|
157
163
|
}
|
|
158
164
|
|
|
159
165
|
getSortValue(order: Order): BN {
|
|
@@ -165,6 +171,7 @@ export type DLOBNodeMap = {
|
|
|
165
171
|
restingLimit: RestingLimitOrderNode;
|
|
166
172
|
takingLimit: TakingLimitOrderNode;
|
|
167
173
|
floatingLimit: FloatingLimitOrderNode;
|
|
174
|
+
protectedFloatingLimit: FloatingLimitOrderNode;
|
|
168
175
|
market: MarketOrderNode;
|
|
169
176
|
trigger: TriggerOrderNode;
|
|
170
177
|
swift: SwiftOrderNode;
|
|
@@ -175,6 +182,7 @@ export type DLOBNodeType =
|
|
|
175
182
|
| 'restingLimit'
|
|
176
183
|
| 'takingLimit'
|
|
177
184
|
| 'floatingLimit'
|
|
185
|
+
| 'protectedFloatingLimit'
|
|
178
186
|
| 'market'
|
|
179
187
|
| ('trigger' & keyof DLOBNodeMap);
|
|
180
188
|
|
|
@@ -182,27 +190,42 @@ export function createNode<T extends DLOBNodeType>(
|
|
|
182
190
|
nodeType: T,
|
|
183
191
|
order: Order,
|
|
184
192
|
userAccount: string,
|
|
185
|
-
|
|
193
|
+
isProtectedMaker: boolean,
|
|
194
|
+
applyProtectedMakerOffset: boolean
|
|
186
195
|
): DLOBNodeMap[T] {
|
|
187
196
|
switch (nodeType) {
|
|
188
197
|
case 'floatingLimit':
|
|
189
198
|
return new FloatingLimitOrderNode(
|
|
190
199
|
order,
|
|
191
200
|
userAccount,
|
|
192
|
-
|
|
201
|
+
isProtectedMaker,
|
|
202
|
+
applyProtectedMakerOffset
|
|
203
|
+
);
|
|
204
|
+
case 'protectedFloatingLimit':
|
|
205
|
+
return new FloatingLimitOrderNode(
|
|
206
|
+
order,
|
|
207
|
+
userAccount,
|
|
208
|
+
isProtectedMaker,
|
|
209
|
+
applyProtectedMakerOffset
|
|
193
210
|
);
|
|
194
211
|
case 'restingLimit':
|
|
195
212
|
return new RestingLimitOrderNode(
|
|
196
213
|
order,
|
|
197
214
|
userAccount,
|
|
198
|
-
|
|
215
|
+
isProtectedMaker,
|
|
216
|
+
applyProtectedMakerOffset
|
|
199
217
|
);
|
|
200
218
|
case 'takingLimit':
|
|
201
|
-
return new TakingLimitOrderNode(
|
|
219
|
+
return new TakingLimitOrderNode(
|
|
220
|
+
order,
|
|
221
|
+
userAccount,
|
|
222
|
+
isProtectedMaker,
|
|
223
|
+
applyProtectedMakerOffset
|
|
224
|
+
);
|
|
202
225
|
case 'market':
|
|
203
|
-
return new MarketOrderNode(order, userAccount,
|
|
226
|
+
return new MarketOrderNode(order, userAccount, isProtectedMaker, false);
|
|
204
227
|
case 'trigger':
|
|
205
|
-
return new TriggerOrderNode(order, userAccount,
|
|
228
|
+
return new TriggerOrderNode(order, userAccount, isProtectedMaker, false);
|
|
206
229
|
case 'swift':
|
|
207
230
|
return new SwiftOrderNode(order, userAccount);
|
|
208
231
|
default:
|
package/src/dlob/NodeList.ts
CHANGED
|
@@ -36,7 +36,8 @@ export class NodeList<NodeType extends keyof DLOBNodeMap>
|
|
|
36
36
|
order: Order,
|
|
37
37
|
marketType: MarketTypeStr,
|
|
38
38
|
userAccount: string,
|
|
39
|
-
|
|
39
|
+
isProtectedMaker: boolean,
|
|
40
|
+
applyProtectedMakerOffset: boolean
|
|
40
41
|
): void {
|
|
41
42
|
if (isVariant(order.status, 'init')) {
|
|
42
43
|
return;
|
|
@@ -46,7 +47,8 @@ export class NodeList<NodeType extends keyof DLOBNodeMap>
|
|
|
46
47
|
this.nodeType,
|
|
47
48
|
order,
|
|
48
49
|
userAccount,
|
|
49
|
-
|
|
50
|
+
isProtectedMaker,
|
|
51
|
+
applyProtectedMakerOffset
|
|
50
52
|
);
|
|
51
53
|
|
|
52
54
|
const orderSignature = getOrderSignature(order.orderId, userAccount);
|