@drift-labs/sdk 2.16.0-beta.2 → 2.16.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/config.d.ts +1 -0
- package/lib/config.js +2 -0
- package/lib/dlob/DLOB.js +18 -2
- package/lib/driftClient.d.ts +46 -2
- package/lib/driftClient.js +131 -0
- package/lib/driftClientConfig.d.ts +1 -0
- package/lib/idl/drift.json +1 -1
- package/lib/math/spotBalance.js +4 -2
- package/lib/math/utils.d.ts +1 -1
- package/lib/math/utils.js +13 -21
- package/lib/tx/retryTxSender.d.ts +4 -2
- package/lib/tx/retryTxSender.js +32 -12
- package/lib/tx/types.d.ts +2 -1
- package/package.json +1 -1
- package/src/config.ts +3 -0
- package/src/dlob/DLOB.ts +21 -2
- package/src/driftClient.ts +191 -1
- package/src/driftClientConfig.ts +1 -0
- package/src/idl/drift.json +1 -1
- package/src/math/spotBalance.ts +12 -7
- package/src/math/utils.ts +13 -27
- package/src/tx/retryTxSender.ts +67 -24
- package/src/tx/types.ts +9 -0
- package/tests/dlob/test.ts +16 -16
- package/src/tx/types.js +0 -2
- package/src/tx/utils.js +0 -17
package/lib/config.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ declare type DriftConfig = {
|
|
|
10
10
|
V2_ALPHA_TICKET_MINT_ADDRESS: string;
|
|
11
11
|
PERP_MARKETS: PerpMarketConfig[];
|
|
12
12
|
SPOT_MARKETS: SpotMarketConfig[];
|
|
13
|
+
MARKET_LOOKUP_TABLE: string;
|
|
13
14
|
};
|
|
14
15
|
export declare type DriftEnv = 'devnet' | 'mainnet-beta';
|
|
15
16
|
export declare const configs: {
|
package/lib/config.js
CHANGED
|
@@ -13,6 +13,7 @@ exports.configs = {
|
|
|
13
13
|
V2_ALPHA_TICKET_MINT_ADDRESS: 'DeEiGWfCMP9psnLGkxGrBBMEAW5Jv8bBGMN8DCtFRCyB',
|
|
14
14
|
PERP_MARKETS: perpMarkets_1.DevnetPerpMarkets,
|
|
15
15
|
SPOT_MARKETS: spotMarkets_1.DevnetSpotMarkets,
|
|
16
|
+
MARKET_LOOKUP_TABLE: 'FaMS3U4uBojvGn5FSDEPimddcXsCfwkKsFgMVVnDdxGb',
|
|
16
17
|
},
|
|
17
18
|
'mainnet-beta': {
|
|
18
19
|
ENV: 'mainnet-beta',
|
|
@@ -23,6 +24,7 @@ exports.configs = {
|
|
|
23
24
|
V2_ALPHA_TICKET_MINT_ADDRESS: 'Cmvhycb6LQvvzaShGw4iDHRLzeSSryioAsU98DSSkMNa',
|
|
24
25
|
PERP_MARKETS: perpMarkets_1.MainnetPerpMarkets,
|
|
25
26
|
SPOT_MARKETS: spotMarkets_1.MainnetSpotMarkets,
|
|
27
|
+
MARKET_LOOKUP_TABLE: 'D9cnvzswDikQDf53k4HpQ3KJ9y1Fv3HGGDFYMXnK5T6c',
|
|
26
28
|
},
|
|
27
29
|
};
|
|
28
30
|
let currentConfig = exports.configs.devnet;
|
package/lib/dlob/DLOB.js
CHANGED
|
@@ -289,6 +289,14 @@ class DLOB {
|
|
|
289
289
|
const nodesToFill = new Array();
|
|
290
290
|
let marketOrderGenerator = this.getMarketAsks(marketIndex, marketType);
|
|
291
291
|
const marketAsksCrossingBids = this.findMarketNodesCrossingLimitNodes(marketIndex, slot, marketType, oraclePriceData, marketOrderGenerator, this.getMakerLimitBids.bind(this), (takerPrice, makerPrice) => {
|
|
292
|
+
if (__1.isVariant(marketType, 'spot')) {
|
|
293
|
+
if (takerPrice === undefined) {
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
if (fallbackBid && makerPrice.lt(fallbackBid)) {
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
292
300
|
return takerPrice === undefined || takerPrice.lte(makerPrice);
|
|
293
301
|
}, fallbackAsk);
|
|
294
302
|
for (const marketAskCrossingBid of marketAsksCrossingBids) {
|
|
@@ -304,8 +312,16 @@ class DLOB {
|
|
|
304
312
|
}
|
|
305
313
|
}
|
|
306
314
|
marketOrderGenerator = this.getMarketBids(marketIndex, marketType);
|
|
307
|
-
const marketBidsToFill = this.findMarketNodesCrossingLimitNodes(marketIndex, slot, marketType, oraclePriceData, marketOrderGenerator, this.getMakerLimitAsks.bind(this), (takerPrice,
|
|
308
|
-
|
|
315
|
+
const marketBidsToFill = this.findMarketNodesCrossingLimitNodes(marketIndex, slot, marketType, oraclePriceData, marketOrderGenerator, this.getMakerLimitAsks.bind(this), (takerPrice, makerPrice) => {
|
|
316
|
+
if (__1.isVariant(marketType, 'spot')) {
|
|
317
|
+
if (takerPrice === undefined) {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
if (fallbackAsk && makerPrice.gt(fallbackAsk)) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return takerPrice === undefined || takerPrice.gte(makerPrice);
|
|
309
325
|
}, fallbackBid);
|
|
310
326
|
for (const marketBidToFill of marketBidsToFill) {
|
|
311
327
|
nodesToFill.push(marketBidToFill);
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="bn.js" />
|
|
3
3
|
import { AnchorProvider, BN, Program } from '@project-serum/anchor';
|
|
4
|
-
import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount } from './types';
|
|
4
|
+
import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, OrderType, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount } from './types';
|
|
5
5
|
import * as anchor from '@project-serum/anchor';
|
|
6
|
-
import { Connection, PublicKey, TransactionSignature, ConfirmOptions, Transaction, TransactionInstruction, AccountMeta, Signer } from '@solana/web3.js';
|
|
6
|
+
import { Connection, PublicKey, TransactionSignature, ConfirmOptions, Transaction, TransactionInstruction, AccountMeta, Signer, AddressLookupTableAccount } from '@solana/web3.js';
|
|
7
7
|
import { TokenFaucet } from './tokenFaucet';
|
|
8
8
|
import { EventEmitter } from 'events';
|
|
9
9
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
@@ -43,6 +43,7 @@ export declare class DriftClient {
|
|
|
43
43
|
perpMarketLastSlotCache: Map<number, number>;
|
|
44
44
|
spotMarketLastSlotCache: Map<number, number>;
|
|
45
45
|
authority: PublicKey;
|
|
46
|
+
marketLookupTable: PublicKey;
|
|
46
47
|
get isSubscribed(): boolean;
|
|
47
48
|
set isSubscribed(val: boolean);
|
|
48
49
|
constructor(config: DriftClientConfig);
|
|
@@ -82,6 +83,7 @@ export declare class DriftClient {
|
|
|
82
83
|
getQuoteSpotMarketAccount(): SpotMarketAccount;
|
|
83
84
|
getOraclePriceDataAndSlot(oraclePublicKey: PublicKey): DataAndSlot<OraclePriceData> | undefined;
|
|
84
85
|
getSerumV3FulfillmentConfig(serumMarket: PublicKey): Promise<SerumV3FulfillmentConfigAccount>;
|
|
86
|
+
fetchMarketLookupTableAccount(): Promise<AddressLookupTableAccount>;
|
|
85
87
|
/**
|
|
86
88
|
* Update the wallet to use for drift transactions and linked user account
|
|
87
89
|
* @param newWallet
|
|
@@ -212,6 +214,7 @@ export declare class DriftClient {
|
|
|
212
214
|
closePosition(marketIndex: number, limitPrice?: BN): Promise<TransactionSignature>;
|
|
213
215
|
/**
|
|
214
216
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
217
|
+
* @deprecated use modifyOrder instead
|
|
215
218
|
* @param orderId: The open order to modify
|
|
216
219
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
217
220
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -219,8 +222,29 @@ export declare class DriftClient {
|
|
|
219
222
|
* @returns
|
|
220
223
|
*/
|
|
221
224
|
modifyPerpOrder(orderId: number, newBaseAmount?: BN, newLimitPrice?: BN, newOraclePriceOffset?: number): Promise<TransactionSignature>;
|
|
225
|
+
/**
|
|
226
|
+
* Modifies an open order (spot or perp) by closing it and replacing it with a new order.
|
|
227
|
+
* @param orderId: The open order to modify
|
|
228
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
229
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
230
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
231
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
232
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
233
|
+
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
234
|
+
* @returns
|
|
235
|
+
*/
|
|
236
|
+
modifyOrder({ orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }: {
|
|
237
|
+
orderId: number;
|
|
238
|
+
newBaseAmount?: BN;
|
|
239
|
+
newLimitPrice?: BN;
|
|
240
|
+
newOraclePriceOffset?: number;
|
|
241
|
+
newOrderType?: OrderType;
|
|
242
|
+
newTriggerPrice?: BN;
|
|
243
|
+
isSpot?: boolean;
|
|
244
|
+
}): Promise<TransactionSignature>;
|
|
222
245
|
/**
|
|
223
246
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
247
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
224
248
|
* @param userOrderId: The open order to modify
|
|
225
249
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
226
250
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -228,6 +252,26 @@ export declare class DriftClient {
|
|
|
228
252
|
* @returns
|
|
229
253
|
*/
|
|
230
254
|
modifyPerpOrderByUserOrderId(userOrderId: number, newBaseAmount?: BN, newLimitPrice?: BN, newOraclePriceOffset?: number): Promise<TransactionSignature>;
|
|
255
|
+
/**
|
|
256
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
257
|
+
* @param userOrderId: The open order to modify
|
|
258
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
259
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
260
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
261
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
262
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
263
|
+
* @param isSpot: Set to true if the order is a spot order
|
|
264
|
+
* @returns
|
|
265
|
+
*/
|
|
266
|
+
modifyOrderByUserOrderId({ userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }: {
|
|
267
|
+
userOrderId: number;
|
|
268
|
+
newBaseAmount?: BN;
|
|
269
|
+
newLimitPrice?: BN;
|
|
270
|
+
newOraclePriceOffset?: number;
|
|
271
|
+
newOrderType?: OrderType;
|
|
272
|
+
newTriggerPrice?: BN;
|
|
273
|
+
isSpot?: boolean;
|
|
274
|
+
}): Promise<TransactionSignature>;
|
|
231
275
|
settlePNLs(users: {
|
|
232
276
|
settleeUserAccountPublicKey: PublicKey;
|
|
233
277
|
settleeUserAccount: UserAccount;
|
package/lib/driftClient.js
CHANGED
|
@@ -93,6 +93,10 @@ class DriftClient {
|
|
|
93
93
|
: envSpotMarketIndexes;
|
|
94
94
|
oracleInfos = oracleInfos ? oracleInfos : envOracleInfos;
|
|
95
95
|
}
|
|
96
|
+
this.marketLookupTable = config.marketLookupTable;
|
|
97
|
+
if (config.env && !this.marketLookupTable) {
|
|
98
|
+
this.marketLookupTable = new web3_js_1.PublicKey(config_1.configs[config.env].MARKET_LOOKUP_TABLE);
|
|
99
|
+
}
|
|
96
100
|
if (((_e = config.accountSubscription) === null || _e === void 0 ? void 0 : _e.type) === 'polling') {
|
|
97
101
|
this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, perpMarketIndexes !== null && perpMarketIndexes !== void 0 ? perpMarketIndexes : [], spotMarketIndexes !== null && spotMarketIndexes !== void 0 ? spotMarketIndexes : [], oracleInfos !== null && oracleInfos !== void 0 ? oracleInfos : []);
|
|
98
102
|
}
|
|
@@ -231,6 +235,13 @@ class DriftClient {
|
|
|
231
235
|
const address = await pda_1.getSerumFulfillmentConfigPublicKey(this.program.programId, serumMarket);
|
|
232
236
|
return (await this.program.account.serumV3FulfillmentConfig.fetch(address));
|
|
233
237
|
}
|
|
238
|
+
async fetchMarketLookupTableAccount() {
|
|
239
|
+
if (!this.marketLookupTable) {
|
|
240
|
+
throw Error('Market lookup table address not set');
|
|
241
|
+
}
|
|
242
|
+
return (await this.connection.getAddressLookupTable(this.marketLookupTable))
|
|
243
|
+
.value;
|
|
244
|
+
}
|
|
234
245
|
/**
|
|
235
246
|
* Update the wallet to use for drift transactions and linked user account
|
|
236
247
|
* @param newWallet
|
|
@@ -1750,6 +1761,7 @@ class DriftClient {
|
|
|
1750
1761
|
}
|
|
1751
1762
|
/**
|
|
1752
1763
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
1764
|
+
* @deprecated use modifyOrder instead
|
|
1753
1765
|
* @param orderId: The open order to modify
|
|
1754
1766
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1755
1767
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -1796,8 +1808,68 @@ class DriftClient {
|
|
|
1796
1808
|
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1797
1809
|
return txSig;
|
|
1798
1810
|
}
|
|
1811
|
+
/**
|
|
1812
|
+
* Modifies an open order (spot or perp) by closing it and replacing it with a new order.
|
|
1813
|
+
* @param orderId: The open order to modify
|
|
1814
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1815
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1816
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1817
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
1818
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
1819
|
+
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
1820
|
+
* @returns
|
|
1821
|
+
*/
|
|
1822
|
+
async modifyOrder({ orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }) {
|
|
1823
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
1824
|
+
throw new Error(`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`);
|
|
1825
|
+
}
|
|
1826
|
+
const openOrder = this.getUser().getOrder(orderId);
|
|
1827
|
+
if (!openOrder) {
|
|
1828
|
+
throw new Error(`No open order with id ${orderId.toString()}`);
|
|
1829
|
+
}
|
|
1830
|
+
const cancelOrderIx = await this.getCancelOrderIx(orderId);
|
|
1831
|
+
const newOrderParams = {
|
|
1832
|
+
orderType: newOrderType || openOrder.orderType,
|
|
1833
|
+
marketType: openOrder.marketType,
|
|
1834
|
+
direction: openOrder.direction,
|
|
1835
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
1836
|
+
price: newLimitPrice || openOrder.price,
|
|
1837
|
+
marketIndex: openOrder.marketIndex,
|
|
1838
|
+
reduceOnly: openOrder.reduceOnly,
|
|
1839
|
+
postOnly: openOrder.postOnly,
|
|
1840
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
1841
|
+
triggerPrice: newTriggerPrice || openOrder.triggerPrice,
|
|
1842
|
+
triggerCondition: openOrder.triggerCondition,
|
|
1843
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
1844
|
+
auctionDuration: openOrder.auctionDuration,
|
|
1845
|
+
maxTs: openOrder.maxTs,
|
|
1846
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
1847
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
1848
|
+
userOrderId: openOrder.userOrderId,
|
|
1849
|
+
};
|
|
1850
|
+
const placeOrderIx = isSpot
|
|
1851
|
+
? await this.getPlaceSpotOrderIx(newOrderParams)
|
|
1852
|
+
: await this.getPlacePerpOrderIx(newOrderParams);
|
|
1853
|
+
const tx = new web3_js_1.Transaction();
|
|
1854
|
+
tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
1855
|
+
units: 1000000,
|
|
1856
|
+
additionalFee: 0,
|
|
1857
|
+
}));
|
|
1858
|
+
tx.add(cancelOrderIx);
|
|
1859
|
+
tx.add(placeOrderIx);
|
|
1860
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
1861
|
+
if (isSpot) {
|
|
1862
|
+
this.spotMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1863
|
+
this.spotMarketLastSlotCache.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, slot);
|
|
1864
|
+
}
|
|
1865
|
+
else {
|
|
1866
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1867
|
+
}
|
|
1868
|
+
return txSig;
|
|
1869
|
+
}
|
|
1799
1870
|
/**
|
|
1800
1871
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
1872
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
1801
1873
|
* @param userOrderId: The open order to modify
|
|
1802
1874
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1803
1875
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -1844,6 +1916,65 @@ class DriftClient {
|
|
|
1844
1916
|
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1845
1917
|
return txSig;
|
|
1846
1918
|
}
|
|
1919
|
+
/**
|
|
1920
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
1921
|
+
* @param userOrderId: The open order to modify
|
|
1922
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1923
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1924
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1925
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
1926
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
1927
|
+
* @param isSpot: Set to true if the order is a spot order
|
|
1928
|
+
* @returns
|
|
1929
|
+
*/
|
|
1930
|
+
async modifyOrderByUserOrderId({ userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }) {
|
|
1931
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
1932
|
+
throw new Error(`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`);
|
|
1933
|
+
}
|
|
1934
|
+
const openOrder = this.getUser().getOrderByUserOrderId(userOrderId);
|
|
1935
|
+
if (!openOrder) {
|
|
1936
|
+
throw new Error(`No open order with user order id ${userOrderId.toString()}`);
|
|
1937
|
+
}
|
|
1938
|
+
const cancelOrderIx = await this.getCancelOrderByUserIdIx(userOrderId);
|
|
1939
|
+
const newOrderParams = {
|
|
1940
|
+
orderType: newOrderType || openOrder.orderType,
|
|
1941
|
+
marketType: openOrder.marketType,
|
|
1942
|
+
direction: openOrder.direction,
|
|
1943
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
1944
|
+
price: newLimitPrice || openOrder.price,
|
|
1945
|
+
marketIndex: openOrder.marketIndex,
|
|
1946
|
+
reduceOnly: openOrder.reduceOnly,
|
|
1947
|
+
postOnly: openOrder.postOnly,
|
|
1948
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
1949
|
+
triggerPrice: newTriggerPrice || openOrder.triggerPrice,
|
|
1950
|
+
triggerCondition: openOrder.triggerCondition,
|
|
1951
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
1952
|
+
auctionDuration: openOrder.auctionDuration,
|
|
1953
|
+
maxTs: openOrder.maxTs,
|
|
1954
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
1955
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
1956
|
+
userOrderId: openOrder.userOrderId,
|
|
1957
|
+
};
|
|
1958
|
+
const placeOrderIx = isSpot
|
|
1959
|
+
? await this.getPlaceSpotOrderIx(newOrderParams)
|
|
1960
|
+
: await this.getPlacePerpOrderIx(newOrderParams);
|
|
1961
|
+
const tx = new web3_js_1.Transaction();
|
|
1962
|
+
tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
1963
|
+
units: 1000000,
|
|
1964
|
+
additionalFee: 0,
|
|
1965
|
+
}));
|
|
1966
|
+
tx.add(cancelOrderIx);
|
|
1967
|
+
tx.add(placeOrderIx);
|
|
1968
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
1969
|
+
if (isSpot) {
|
|
1970
|
+
this.spotMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1971
|
+
this.spotMarketLastSlotCache.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, slot);
|
|
1972
|
+
}
|
|
1973
|
+
else {
|
|
1974
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1975
|
+
}
|
|
1976
|
+
return txSig;
|
|
1977
|
+
}
|
|
1847
1978
|
async settlePNLs(users, marketIndex) {
|
|
1848
1979
|
const ixs = [];
|
|
1849
1980
|
for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
|
package/lib/idl/drift.json
CHANGED
package/lib/math/spotBalance.js
CHANGED
|
@@ -201,9 +201,11 @@ function calculateWithdrawLimit(spotMarket, now) {
|
|
|
201
201
|
.add(marketDepositTokenAmount.mul(sinceLast))
|
|
202
202
|
.div(sinceLast.add(sinceStart));
|
|
203
203
|
const maxBorrowTokens = anchor_1.BN.max(spotMarket.withdrawGuardThreshold, anchor_1.BN.min(anchor_1.BN.max(marketDepositTokenAmount.div(new anchor_1.BN(6)), borrowTokenTwapLive.add(borrowTokenTwapLive.div(new anchor_1.BN(5)))), marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new anchor_1.BN(5))))); // between ~15-80% utilization with friction on twap
|
|
204
|
-
const minDepositTokens = depositTokenTwapLive.sub(anchor_1.BN.
|
|
204
|
+
const minDepositTokens = depositTokenTwapLive.sub(anchor_1.BN.max(depositTokenTwapLive.div(new anchor_1.BN(5)), anchor_1.BN.min(spotMarket.withdrawGuardThreshold, depositTokenTwapLive)));
|
|
205
205
|
let withdrawLimit = anchor_1.BN.max(marketDepositTokenAmount.sub(minDepositTokens), numericConstants_1.ZERO);
|
|
206
|
-
let borrowLimit =
|
|
206
|
+
let borrowLimit = maxBorrowTokens.sub(marketBorrowTokenAmount);
|
|
207
|
+
borrowLimit = anchor_1.BN.min(borrowLimit, marketDepositTokenAmount.sub(minDepositTokens));
|
|
208
|
+
borrowLimit = anchor_1.BN.min(borrowLimit, marketDepositTokenAmount.sub(marketBorrowTokenAmount));
|
|
207
209
|
if (borrowLimit.eq(numericConstants_1.ZERO)) {
|
|
208
210
|
withdrawLimit = numericConstants_1.ZERO;
|
|
209
211
|
}
|
package/lib/math/utils.d.ts
CHANGED
package/lib/math/utils.js
CHANGED
|
@@ -6,28 +6,20 @@ function clampBN(x, min, max) {
|
|
|
6
6
|
return __1.BN.max(min, __1.BN.min(x, max));
|
|
7
7
|
}
|
|
8
8
|
exports.clampBN = clampBN;
|
|
9
|
-
const squareRootBN = (n
|
|
10
|
-
if (n.lt(__1.
|
|
11
|
-
throw new Error('
|
|
9
|
+
const squareRootBN = (n) => {
|
|
10
|
+
if (n.lt(new __1.BN(0))) {
|
|
11
|
+
throw new Error('Sqrt only works on non-negtiave inputs');
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
// Calculate more closed x
|
|
24
|
-
root = x.add(n.div(x)).div(TWO);
|
|
25
|
-
// Check for closeness
|
|
26
|
-
if (x.sub(root).abs().lte(closeness))
|
|
27
|
-
break;
|
|
28
|
-
// Update root
|
|
29
|
-
x = root;
|
|
13
|
+
if (n.lt(new __1.BN(2))) {
|
|
14
|
+
return n;
|
|
15
|
+
}
|
|
16
|
+
const smallCand = exports.squareRootBN(n.shrn(2)).shln(1);
|
|
17
|
+
const largeCand = smallCand.add(new __1.BN(1));
|
|
18
|
+
if (largeCand.mul(largeCand).gt(n)) {
|
|
19
|
+
return smallCand;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return largeCand;
|
|
30
23
|
}
|
|
31
|
-
return root;
|
|
32
24
|
};
|
|
33
25
|
exports.squareRootBN = squareRootBN;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { TxSender, TxSigAndSlot } from './types';
|
|
3
|
-
import { Commitment, ConfirmOptions, RpcResponseAndContext, Signer, SignatureResult, Transaction, TransactionSignature, Connection } from '@solana/web3.js';
|
|
3
|
+
import { Commitment, ConfirmOptions, RpcResponseAndContext, Signer, SignatureResult, Transaction, TransactionSignature, Connection, TransactionInstruction, AddressLookupTableAccount } from '@solana/web3.js';
|
|
4
4
|
import { AnchorProvider } from '@project-serum/anchor';
|
|
5
5
|
declare type ResolveReference = {
|
|
6
6
|
resolve?: () => void;
|
|
@@ -13,11 +13,13 @@ export declare class RetryTxSender implements TxSender {
|
|
|
13
13
|
constructor(provider: AnchorProvider, timeout?: number, retrySleep?: number, additionalConnections?: Connection[]);
|
|
14
14
|
send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
|
|
15
15
|
prepareTx(tx: Transaction, additionalSigners: Array<Signer>, opts: ConfirmOptions): Promise<Transaction>;
|
|
16
|
+
sendVersionedTransaction(ixs: TransactionInstruction[], lookupTableAccounts: AddressLookupTableAccount[], additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<TxSigAndSlot>;
|
|
17
|
+
sendRawTransaction(rawTransaction: Buffer | Uint8Array, opts: ConfirmOptions): Promise<TxSigAndSlot>;
|
|
16
18
|
confirmTransaction(signature: TransactionSignature, commitment?: Commitment): Promise<RpcResponseAndContext<SignatureResult>>;
|
|
17
19
|
getTimestamp(): number;
|
|
18
20
|
sleep(reference: ResolveReference): Promise<void>;
|
|
19
21
|
promiseTimeout<T>(promises: Promise<T>[], timeoutMs: number): Promise<T | null>;
|
|
20
|
-
sendToAdditionalConnections(rawTx: Buffer, opts: ConfirmOptions): void;
|
|
22
|
+
sendToAdditionalConnections(rawTx: Buffer | Uint8Array, opts: ConfirmOptions): void;
|
|
21
23
|
addAdditionalConnection(newConnection: Connection): void;
|
|
22
24
|
}
|
|
23
25
|
export {};
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.RetryTxSender = void 0;
|
|
7
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
7
8
|
const assert_1 = __importDefault(require("assert"));
|
|
8
9
|
const bs58_1 = __importDefault(require("bs58"));
|
|
9
10
|
const DEFAULT_TIMEOUT = 35000;
|
|
@@ -25,7 +26,37 @@ class RetryTxSender {
|
|
|
25
26
|
const signedTx = preSigned
|
|
26
27
|
? tx
|
|
27
28
|
: await this.prepareTx(tx, additionalSigners, opts);
|
|
28
|
-
|
|
29
|
+
return this.sendRawTransaction(signedTx.serialize(), opts);
|
|
30
|
+
}
|
|
31
|
+
async prepareTx(tx, additionalSigners, opts) {
|
|
32
|
+
tx.feePayer = this.provider.wallet.publicKey;
|
|
33
|
+
tx.recentBlockhash = (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash;
|
|
34
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
35
|
+
additionalSigners
|
|
36
|
+
.filter((s) => s !== undefined)
|
|
37
|
+
.forEach((kp) => {
|
|
38
|
+
signedTx.partialSign(kp);
|
|
39
|
+
});
|
|
40
|
+
return signedTx;
|
|
41
|
+
}
|
|
42
|
+
async sendVersionedTransaction(ixs, lookupTableAccounts, additionalSigners, opts) {
|
|
43
|
+
if (additionalSigners === undefined) {
|
|
44
|
+
additionalSigners = [];
|
|
45
|
+
}
|
|
46
|
+
if (opts === undefined) {
|
|
47
|
+
opts = this.provider.opts;
|
|
48
|
+
}
|
|
49
|
+
const message = new web3_js_1.TransactionMessage({
|
|
50
|
+
payerKey: this.provider.wallet.publicKey,
|
|
51
|
+
recentBlockhash: (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash,
|
|
52
|
+
instructions: ixs,
|
|
53
|
+
}).compileToV0Message(lookupTableAccounts);
|
|
54
|
+
const tx = new web3_js_1.VersionedTransaction(message);
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
tx.sign(additionalSigners.concat(this.provider.wallet.payer));
|
|
57
|
+
return this.sendRawTransaction(tx.serialize(), opts);
|
|
58
|
+
}
|
|
59
|
+
async sendRawTransaction(rawTransaction, opts) {
|
|
29
60
|
const startTime = this.getTimestamp();
|
|
30
61
|
let txid;
|
|
31
62
|
try {
|
|
@@ -74,17 +105,6 @@ class RetryTxSender {
|
|
|
74
105
|
}
|
|
75
106
|
return { txSig: txid, slot };
|
|
76
107
|
}
|
|
77
|
-
async prepareTx(tx, additionalSigners, opts) {
|
|
78
|
-
tx.feePayer = this.provider.wallet.publicKey;
|
|
79
|
-
tx.recentBlockhash = (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash;
|
|
80
|
-
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
81
|
-
additionalSigners
|
|
82
|
-
.filter((s) => s !== undefined)
|
|
83
|
-
.forEach((kp) => {
|
|
84
|
-
signedTx.partialSign(kp);
|
|
85
|
-
});
|
|
86
|
-
return signedTx;
|
|
87
|
-
}
|
|
88
108
|
async confirmTransaction(signature, commitment) {
|
|
89
109
|
let decodedSignature;
|
|
90
110
|
try {
|
package/lib/tx/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Provider } from '@project-serum/anchor';
|
|
2
|
-
import { ConfirmOptions, Signer, Transaction, TransactionSignature } from '@solana/web3.js';
|
|
2
|
+
import { AddressLookupTableAccount, ConfirmOptions, Signer, Transaction, TransactionInstruction, TransactionSignature } from '@solana/web3.js';
|
|
3
3
|
export declare type TxSigAndSlot = {
|
|
4
4
|
txSig: TransactionSignature;
|
|
5
5
|
slot: number;
|
|
@@ -7,4 +7,5 @@ export declare type TxSigAndSlot = {
|
|
|
7
7
|
export interface TxSender {
|
|
8
8
|
provider: Provider;
|
|
9
9
|
send(tx: Transaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
|
|
10
|
+
sendVersionedTransaction(ixs: TransactionInstruction[], lookupTableAccounts: AddressLookupTableAccount[], additionalSigners?: Array<Signer>, opts?: ConfirmOptions): Promise<TxSigAndSlot>;
|
|
10
11
|
}
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -21,6 +21,7 @@ type DriftConfig = {
|
|
|
21
21
|
V2_ALPHA_TICKET_MINT_ADDRESS: string;
|
|
22
22
|
PERP_MARKETS: PerpMarketConfig[];
|
|
23
23
|
SPOT_MARKETS: SpotMarketConfig[];
|
|
24
|
+
MARKET_LOOKUP_TABLE: string;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
export type DriftEnv = 'devnet' | 'mainnet-beta';
|
|
@@ -36,6 +37,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
36
37
|
'DeEiGWfCMP9psnLGkxGrBBMEAW5Jv8bBGMN8DCtFRCyB',
|
|
37
38
|
PERP_MARKETS: DevnetPerpMarkets,
|
|
38
39
|
SPOT_MARKETS: DevnetSpotMarkets,
|
|
40
|
+
MARKET_LOOKUP_TABLE: 'FaMS3U4uBojvGn5FSDEPimddcXsCfwkKsFgMVVnDdxGb',
|
|
39
41
|
},
|
|
40
42
|
'mainnet-beta': {
|
|
41
43
|
ENV: 'mainnet-beta',
|
|
@@ -47,6 +49,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
|
|
|
47
49
|
'Cmvhycb6LQvvzaShGw4iDHRLzeSSryioAsU98DSSkMNa',
|
|
48
50
|
PERP_MARKETS: MainnetPerpMarkets,
|
|
49
51
|
SPOT_MARKETS: MainnetSpotMarkets,
|
|
52
|
+
MARKET_LOOKUP_TABLE: 'D9cnvzswDikQDf53k4HpQ3KJ9y1Fv3HGGDFYMXnK5T6c',
|
|
50
53
|
},
|
|
51
54
|
};
|
|
52
55
|
|
package/src/dlob/DLOB.ts
CHANGED
|
@@ -521,6 +521,15 @@ export class DLOB {
|
|
|
521
521
|
marketOrderGenerator,
|
|
522
522
|
this.getMakerLimitBids.bind(this),
|
|
523
523
|
(takerPrice, makerPrice) => {
|
|
524
|
+
if (isVariant(marketType, 'spot')) {
|
|
525
|
+
if (takerPrice === undefined) {
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (fallbackBid && makerPrice.lt(fallbackBid)) {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
524
533
|
return takerPrice === undefined || takerPrice.lte(makerPrice);
|
|
525
534
|
},
|
|
526
535
|
fallbackAsk
|
|
@@ -557,8 +566,18 @@ export class DLOB {
|
|
|
557
566
|
oraclePriceData,
|
|
558
567
|
marketOrderGenerator,
|
|
559
568
|
this.getMakerLimitAsks.bind(this),
|
|
560
|
-
(takerPrice,
|
|
561
|
-
|
|
569
|
+
(takerPrice, makerPrice) => {
|
|
570
|
+
if (isVariant(marketType, 'spot')) {
|
|
571
|
+
if (takerPrice === undefined) {
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (fallbackAsk && makerPrice.gt(fallbackAsk)) {
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return takerPrice === undefined || takerPrice.gte(makerPrice);
|
|
562
581
|
},
|
|
563
582
|
fallbackBid
|
|
564
583
|
);
|
package/src/driftClient.ts
CHANGED
|
@@ -42,6 +42,7 @@ import {
|
|
|
42
42
|
Signer,
|
|
43
43
|
SystemProgram,
|
|
44
44
|
ComputeBudgetProgram,
|
|
45
|
+
AddressLookupTableAccount,
|
|
45
46
|
} from '@solana/web3.js';
|
|
46
47
|
|
|
47
48
|
import { TokenFaucet } from './tokenFaucet';
|
|
@@ -77,7 +78,7 @@ import { WebSocketDriftClientAccountSubscriber } from './accounts/webSocketDrift
|
|
|
77
78
|
import { RetryTxSender } from './tx/retryTxSender';
|
|
78
79
|
import { User } from './user';
|
|
79
80
|
import { UserSubscriptionConfig } from './userConfig';
|
|
80
|
-
import { getMarketsAndOraclesForSubscription } from './config';
|
|
81
|
+
import { configs, getMarketsAndOraclesForSubscription } from './config';
|
|
81
82
|
import { WRAPPED_SOL_MINT } from './constants/spotMarkets';
|
|
82
83
|
import { UserStats } from './userStats';
|
|
83
84
|
import { isSpotPositionAvailable } from './math/spotPosition';
|
|
@@ -112,6 +113,7 @@ export class DriftClient {
|
|
|
112
113
|
perpMarketLastSlotCache = new Map<number, number>();
|
|
113
114
|
spotMarketLastSlotCache = new Map<number, number>();
|
|
114
115
|
authority: PublicKey;
|
|
116
|
+
marketLookupTable: PublicKey;
|
|
115
117
|
|
|
116
118
|
public get isSubscribed() {
|
|
117
119
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
@@ -178,6 +180,13 @@ export class DriftClient {
|
|
|
178
180
|
oracleInfos = oracleInfos ? oracleInfos : envOracleInfos;
|
|
179
181
|
}
|
|
180
182
|
|
|
183
|
+
this.marketLookupTable = config.marketLookupTable;
|
|
184
|
+
if (config.env && !this.marketLookupTable) {
|
|
185
|
+
this.marketLookupTable = new PublicKey(
|
|
186
|
+
configs[config.env].MARKET_LOOKUP_TABLE
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
181
190
|
if (config.accountSubscription?.type === 'polling') {
|
|
182
191
|
this.accountSubscriber = new PollingDriftClientAccountSubscriber(
|
|
183
192
|
this.program,
|
|
@@ -387,6 +396,15 @@ export class DriftClient {
|
|
|
387
396
|
)) as SerumV3FulfillmentConfigAccount;
|
|
388
397
|
}
|
|
389
398
|
|
|
399
|
+
public async fetchMarketLookupTableAccount(): Promise<AddressLookupTableAccount> {
|
|
400
|
+
if (!this.marketLookupTable) {
|
|
401
|
+
throw Error('Market lookup table address not set');
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return (await this.connection.getAddressLookupTable(this.marketLookupTable))
|
|
405
|
+
.value;
|
|
406
|
+
}
|
|
407
|
+
|
|
390
408
|
/**
|
|
391
409
|
* Update the wallet to use for drift transactions and linked user account
|
|
392
410
|
* @param newWallet
|
|
@@ -3018,6 +3036,7 @@ export class DriftClient {
|
|
|
3018
3036
|
|
|
3019
3037
|
/**
|
|
3020
3038
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
3039
|
+
* @deprecated use modifyOrder instead
|
|
3021
3040
|
* @param orderId: The open order to modify
|
|
3022
3041
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3023
3042
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -3077,8 +3096,93 @@ export class DriftClient {
|
|
|
3077
3096
|
return txSig;
|
|
3078
3097
|
}
|
|
3079
3098
|
|
|
3099
|
+
/**
|
|
3100
|
+
* Modifies an open order (spot or perp) by closing it and replacing it with a new order.
|
|
3101
|
+
* @param orderId: The open order to modify
|
|
3102
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3103
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3104
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3105
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
3106
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
3107
|
+
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
3108
|
+
* @returns
|
|
3109
|
+
*/
|
|
3110
|
+
public async modifyOrder({
|
|
3111
|
+
orderId,
|
|
3112
|
+
newBaseAmount,
|
|
3113
|
+
newLimitPrice,
|
|
3114
|
+
newOraclePriceOffset,
|
|
3115
|
+
newOrderType,
|
|
3116
|
+
newTriggerPrice,
|
|
3117
|
+
isSpot,
|
|
3118
|
+
}: {
|
|
3119
|
+
orderId: number;
|
|
3120
|
+
newBaseAmount?: BN;
|
|
3121
|
+
newLimitPrice?: BN;
|
|
3122
|
+
newOraclePriceOffset?: number;
|
|
3123
|
+
newOrderType?: OrderType;
|
|
3124
|
+
newTriggerPrice?: BN;
|
|
3125
|
+
isSpot?: boolean;
|
|
3126
|
+
}): Promise<TransactionSignature> {
|
|
3127
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
3128
|
+
throw new Error(
|
|
3129
|
+
`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`
|
|
3130
|
+
);
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
const openOrder = this.getUser().getOrder(orderId);
|
|
3134
|
+
if (!openOrder) {
|
|
3135
|
+
throw new Error(`No open order with id ${orderId.toString()}`);
|
|
3136
|
+
}
|
|
3137
|
+
const cancelOrderIx = await this.getCancelOrderIx(orderId);
|
|
3138
|
+
|
|
3139
|
+
const newOrderParams: OptionalOrderParams = {
|
|
3140
|
+
orderType: newOrderType || openOrder.orderType,
|
|
3141
|
+
marketType: openOrder.marketType,
|
|
3142
|
+
direction: openOrder.direction,
|
|
3143
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
3144
|
+
price: newLimitPrice || openOrder.price,
|
|
3145
|
+
marketIndex: openOrder.marketIndex,
|
|
3146
|
+
reduceOnly: openOrder.reduceOnly,
|
|
3147
|
+
postOnly: openOrder.postOnly,
|
|
3148
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
3149
|
+
triggerPrice: newTriggerPrice || openOrder.triggerPrice,
|
|
3150
|
+
triggerCondition: openOrder.triggerCondition,
|
|
3151
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
3152
|
+
auctionDuration: openOrder.auctionDuration,
|
|
3153
|
+
maxTs: openOrder.maxTs,
|
|
3154
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
3155
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
3156
|
+
userOrderId: openOrder.userOrderId,
|
|
3157
|
+
};
|
|
3158
|
+
const placeOrderIx = isSpot
|
|
3159
|
+
? await this.getPlaceSpotOrderIx(newOrderParams)
|
|
3160
|
+
: await this.getPlacePerpOrderIx(newOrderParams);
|
|
3161
|
+
|
|
3162
|
+
const tx = new Transaction();
|
|
3163
|
+
tx.add(
|
|
3164
|
+
ComputeBudgetProgram.requestUnits({
|
|
3165
|
+
units: 1_000_000,
|
|
3166
|
+
additionalFee: 0,
|
|
3167
|
+
})
|
|
3168
|
+
);
|
|
3169
|
+
tx.add(cancelOrderIx);
|
|
3170
|
+
tx.add(placeOrderIx);
|
|
3171
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
3172
|
+
|
|
3173
|
+
if (isSpot) {
|
|
3174
|
+
this.spotMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3175
|
+
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
|
|
3176
|
+
} else {
|
|
3177
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3178
|
+
}
|
|
3179
|
+
|
|
3180
|
+
return txSig;
|
|
3181
|
+
}
|
|
3182
|
+
|
|
3080
3183
|
/**
|
|
3081
3184
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
3185
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
3082
3186
|
* @param userOrderId: The open order to modify
|
|
3083
3187
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3084
3188
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -3140,6 +3244,92 @@ export class DriftClient {
|
|
|
3140
3244
|
return txSig;
|
|
3141
3245
|
}
|
|
3142
3246
|
|
|
3247
|
+
/**
|
|
3248
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
3249
|
+
* @param userOrderId: The open order to modify
|
|
3250
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3251
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3252
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3253
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
3254
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
3255
|
+
* @param isSpot: Set to true if the order is a spot order
|
|
3256
|
+
* @returns
|
|
3257
|
+
*/
|
|
3258
|
+
public async modifyOrderByUserOrderId({
|
|
3259
|
+
userOrderId,
|
|
3260
|
+
newBaseAmount,
|
|
3261
|
+
newLimitPrice,
|
|
3262
|
+
newOraclePriceOffset,
|
|
3263
|
+
newOrderType,
|
|
3264
|
+
newTriggerPrice,
|
|
3265
|
+
isSpot,
|
|
3266
|
+
}: {
|
|
3267
|
+
userOrderId: number;
|
|
3268
|
+
newBaseAmount?: BN;
|
|
3269
|
+
newLimitPrice?: BN;
|
|
3270
|
+
newOraclePriceOffset?: number;
|
|
3271
|
+
newOrderType?: OrderType;
|
|
3272
|
+
newTriggerPrice?: BN;
|
|
3273
|
+
isSpot?: boolean;
|
|
3274
|
+
}): Promise<TransactionSignature> {
|
|
3275
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
3276
|
+
throw new Error(
|
|
3277
|
+
`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`
|
|
3278
|
+
);
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
const openOrder = this.getUser().getOrderByUserOrderId(userOrderId);
|
|
3282
|
+
if (!openOrder) {
|
|
3283
|
+
throw new Error(
|
|
3284
|
+
`No open order with user order id ${userOrderId.toString()}`
|
|
3285
|
+
);
|
|
3286
|
+
}
|
|
3287
|
+
const cancelOrderIx = await this.getCancelOrderByUserIdIx(userOrderId);
|
|
3288
|
+
|
|
3289
|
+
const newOrderParams: OptionalOrderParams = {
|
|
3290
|
+
orderType: newOrderType || openOrder.orderType,
|
|
3291
|
+
marketType: openOrder.marketType,
|
|
3292
|
+
direction: openOrder.direction,
|
|
3293
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
3294
|
+
price: newLimitPrice || openOrder.price,
|
|
3295
|
+
marketIndex: openOrder.marketIndex,
|
|
3296
|
+
reduceOnly: openOrder.reduceOnly,
|
|
3297
|
+
postOnly: openOrder.postOnly,
|
|
3298
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
3299
|
+
triggerPrice: newTriggerPrice || openOrder.triggerPrice,
|
|
3300
|
+
triggerCondition: openOrder.triggerCondition,
|
|
3301
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
3302
|
+
auctionDuration: openOrder.auctionDuration,
|
|
3303
|
+
maxTs: openOrder.maxTs,
|
|
3304
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
3305
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
3306
|
+
userOrderId: openOrder.userOrderId,
|
|
3307
|
+
};
|
|
3308
|
+
const placeOrderIx = isSpot
|
|
3309
|
+
? await this.getPlaceSpotOrderIx(newOrderParams)
|
|
3310
|
+
: await this.getPlacePerpOrderIx(newOrderParams);
|
|
3311
|
+
|
|
3312
|
+
const tx = new Transaction();
|
|
3313
|
+
tx.add(
|
|
3314
|
+
ComputeBudgetProgram.requestUnits({
|
|
3315
|
+
units: 1_000_000,
|
|
3316
|
+
additionalFee: 0,
|
|
3317
|
+
})
|
|
3318
|
+
);
|
|
3319
|
+
tx.add(cancelOrderIx);
|
|
3320
|
+
tx.add(placeOrderIx);
|
|
3321
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
3322
|
+
|
|
3323
|
+
if (isSpot) {
|
|
3324
|
+
this.spotMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3325
|
+
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
|
|
3326
|
+
} else {
|
|
3327
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
return txSig;
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3143
3333
|
public async settlePNLs(
|
|
3144
3334
|
users: {
|
|
3145
3335
|
settleeUserAccountPublicKey: PublicKey;
|
package/src/driftClientConfig.ts
CHANGED
package/src/idl/drift.json
CHANGED
package/src/math/spotBalance.ts
CHANGED
|
@@ -338,12 +338,9 @@ export function calculateWithdrawLimit(
|
|
|
338
338
|
); // between ~15-80% utilization with friction on twap
|
|
339
339
|
|
|
340
340
|
const minDepositTokens = depositTokenTwapLive.sub(
|
|
341
|
-
BN.
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
spotMarket.withdrawGuardThreshold
|
|
345
|
-
),
|
|
346
|
-
depositTokenTwapLive
|
|
341
|
+
BN.max(
|
|
342
|
+
depositTokenTwapLive.div(new BN(5)),
|
|
343
|
+
BN.min(spotMarket.withdrawGuardThreshold, depositTokenTwapLive)
|
|
347
344
|
)
|
|
348
345
|
);
|
|
349
346
|
|
|
@@ -352,7 +349,15 @@ export function calculateWithdrawLimit(
|
|
|
352
349
|
ZERO
|
|
353
350
|
);
|
|
354
351
|
|
|
355
|
-
let borrowLimit =
|
|
352
|
+
let borrowLimit = maxBorrowTokens.sub(marketBorrowTokenAmount);
|
|
353
|
+
borrowLimit = BN.min(
|
|
354
|
+
borrowLimit,
|
|
355
|
+
marketDepositTokenAmount.sub(minDepositTokens)
|
|
356
|
+
);
|
|
357
|
+
borrowLimit = BN.min(
|
|
358
|
+
borrowLimit,
|
|
359
|
+
marketDepositTokenAmount.sub(marketBorrowTokenAmount)
|
|
360
|
+
);
|
|
356
361
|
|
|
357
362
|
if (borrowLimit.eq(ZERO)) {
|
|
358
363
|
withdrawLimit = ZERO;
|
package/src/math/utils.ts
CHANGED
|
@@ -1,37 +1,23 @@
|
|
|
1
|
-
import { BN
|
|
1
|
+
import { BN } from '../';
|
|
2
2
|
|
|
3
3
|
export function clampBN(x: BN, min: BN, max: BN): BN {
|
|
4
4
|
return BN.max(min, BN.min(x, max));
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export const squareRootBN = (n
|
|
8
|
-
if (n.lt(
|
|
9
|
-
throw new Error('
|
|
7
|
+
export const squareRootBN = (n: BN): BN => {
|
|
8
|
+
if (n.lt(new BN(0))) {
|
|
9
|
+
throw new Error('Sqrt only works on non-negtiave inputs');
|
|
10
|
+
}
|
|
11
|
+
if (n.lt(new BN(2))) {
|
|
12
|
+
return n;
|
|
10
13
|
}
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// The closed guess will be stored in the root
|
|
16
|
-
let root;
|
|
17
|
-
|
|
18
|
-
// To count the number of iterations
|
|
19
|
-
let count = 0;
|
|
20
|
-
const TWO = new BN(2);
|
|
21
|
-
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
23
|
-
while (count < Number.MAX_SAFE_INTEGER) {
|
|
24
|
-
count++;
|
|
25
|
-
|
|
26
|
-
// Calculate more closed x
|
|
27
|
-
root = x.add(n.div(x)).div(TWO);
|
|
28
|
-
|
|
29
|
-
// Check for closeness
|
|
30
|
-
if (x.sub(root).abs().lte(closeness)) break;
|
|
15
|
+
const smallCand = squareRootBN(n.shrn(2)).shln(1);
|
|
16
|
+
const largeCand = smallCand.add(new BN(1));
|
|
31
17
|
|
|
32
|
-
|
|
33
|
-
|
|
18
|
+
if (largeCand.mul(largeCand).gt(n)) {
|
|
19
|
+
return smallCand;
|
|
20
|
+
} else {
|
|
21
|
+
return largeCand;
|
|
34
22
|
}
|
|
35
|
-
|
|
36
|
-
return root;
|
|
37
23
|
};
|
package/src/tx/retryTxSender.ts
CHANGED
|
@@ -9,6 +9,10 @@ import {
|
|
|
9
9
|
Transaction,
|
|
10
10
|
TransactionSignature,
|
|
11
11
|
Connection,
|
|
12
|
+
VersionedTransaction,
|
|
13
|
+
TransactionMessage,
|
|
14
|
+
TransactionInstruction,
|
|
15
|
+
AddressLookupTableAccount,
|
|
12
16
|
} from '@solana/web3.js';
|
|
13
17
|
import { AnchorProvider } from '@project-serum/anchor';
|
|
14
18
|
import assert from 'assert';
|
|
@@ -56,7 +60,65 @@ export class RetryTxSender implements TxSender {
|
|
|
56
60
|
? tx
|
|
57
61
|
: await this.prepareTx(tx, additionalSigners, opts);
|
|
58
62
|
|
|
59
|
-
|
|
63
|
+
return this.sendRawTransaction(signedTx.serialize(), opts);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async prepareTx(
|
|
67
|
+
tx: Transaction,
|
|
68
|
+
additionalSigners: Array<Signer>,
|
|
69
|
+
opts: ConfirmOptions
|
|
70
|
+
): Promise<Transaction> {
|
|
71
|
+
tx.feePayer = this.provider.wallet.publicKey;
|
|
72
|
+
tx.recentBlockhash = (
|
|
73
|
+
await this.provider.connection.getRecentBlockhash(
|
|
74
|
+
opts.preflightCommitment
|
|
75
|
+
)
|
|
76
|
+
).blockhash;
|
|
77
|
+
|
|
78
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
79
|
+
additionalSigners
|
|
80
|
+
.filter((s): s is Signer => s !== undefined)
|
|
81
|
+
.forEach((kp) => {
|
|
82
|
+
signedTx.partialSign(kp);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
return signedTx;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async sendVersionedTransaction(
|
|
89
|
+
ixs: TransactionInstruction[],
|
|
90
|
+
lookupTableAccounts: AddressLookupTableAccount[],
|
|
91
|
+
additionalSigners?: Array<Signer>,
|
|
92
|
+
opts?: ConfirmOptions
|
|
93
|
+
): Promise<TxSigAndSlot> {
|
|
94
|
+
if (additionalSigners === undefined) {
|
|
95
|
+
additionalSigners = [];
|
|
96
|
+
}
|
|
97
|
+
if (opts === undefined) {
|
|
98
|
+
opts = this.provider.opts;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const message = new TransactionMessage({
|
|
102
|
+
payerKey: this.provider.wallet.publicKey,
|
|
103
|
+
recentBlockhash: (
|
|
104
|
+
await this.provider.connection.getRecentBlockhash(
|
|
105
|
+
opts.preflightCommitment
|
|
106
|
+
)
|
|
107
|
+
).blockhash,
|
|
108
|
+
instructions: ixs,
|
|
109
|
+
}).compileToV0Message(lookupTableAccounts);
|
|
110
|
+
|
|
111
|
+
const tx = new VersionedTransaction(message);
|
|
112
|
+
// @ts-ignore
|
|
113
|
+
tx.sign(additionalSigners.concat(this.provider.wallet.payer));
|
|
114
|
+
|
|
115
|
+
return this.sendRawTransaction(tx.serialize(), opts);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async sendRawTransaction(
|
|
119
|
+
rawTransaction: Buffer | Uint8Array,
|
|
120
|
+
opts: ConfirmOptions
|
|
121
|
+
): Promise<TxSigAndSlot> {
|
|
60
122
|
const startTime = this.getTimestamp();
|
|
61
123
|
|
|
62
124
|
let txid: TransactionSignature;
|
|
@@ -111,28 +173,6 @@ export class RetryTxSender implements TxSender {
|
|
|
111
173
|
return { txSig: txid, slot };
|
|
112
174
|
}
|
|
113
175
|
|
|
114
|
-
async prepareTx(
|
|
115
|
-
tx: Transaction,
|
|
116
|
-
additionalSigners: Array<Signer>,
|
|
117
|
-
opts: ConfirmOptions
|
|
118
|
-
): Promise<Transaction> {
|
|
119
|
-
tx.feePayer = this.provider.wallet.publicKey;
|
|
120
|
-
tx.recentBlockhash = (
|
|
121
|
-
await this.provider.connection.getRecentBlockhash(
|
|
122
|
-
opts.preflightCommitment
|
|
123
|
-
)
|
|
124
|
-
).blockhash;
|
|
125
|
-
|
|
126
|
-
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
127
|
-
additionalSigners
|
|
128
|
-
.filter((s): s is Signer => s !== undefined)
|
|
129
|
-
.forEach((kp) => {
|
|
130
|
-
signedTx.partialSign(kp);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
return signedTx;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
176
|
async confirmTransaction(
|
|
137
177
|
signature: TransactionSignature,
|
|
138
178
|
commitment?: Commitment
|
|
@@ -229,7 +269,10 @@ export class RetryTxSender implements TxSender {
|
|
|
229
269
|
);
|
|
230
270
|
}
|
|
231
271
|
|
|
232
|
-
sendToAdditionalConnections(
|
|
272
|
+
sendToAdditionalConnections(
|
|
273
|
+
rawTx: Buffer | Uint8Array,
|
|
274
|
+
opts: ConfirmOptions
|
|
275
|
+
): void {
|
|
233
276
|
this.additionalConnections.map((connection) => {
|
|
234
277
|
connection.sendRawTransaction(rawTx, opts).catch((e) => {
|
|
235
278
|
console.error(
|
package/src/tx/types.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Provider } from '@project-serum/anchor';
|
|
2
2
|
import {
|
|
3
|
+
AddressLookupTableAccount,
|
|
3
4
|
ConfirmOptions,
|
|
4
5
|
Signer,
|
|
5
6
|
Transaction,
|
|
7
|
+
TransactionInstruction,
|
|
6
8
|
TransactionSignature,
|
|
7
9
|
} from '@solana/web3.js';
|
|
8
10
|
|
|
@@ -20,4 +22,11 @@ export interface TxSender {
|
|
|
20
22
|
opts?: ConfirmOptions,
|
|
21
23
|
preSigned?: boolean
|
|
22
24
|
): Promise<TxSigAndSlot>;
|
|
25
|
+
|
|
26
|
+
sendVersionedTransaction(
|
|
27
|
+
ixs: TransactionInstruction[],
|
|
28
|
+
lookupTableAccounts: AddressLookupTableAccount[],
|
|
29
|
+
additionalSigners?: Array<Signer>,
|
|
30
|
+
opts?: ConfirmOptions
|
|
31
|
+
): Promise<TxSigAndSlot>;
|
|
23
32
|
}
|
package/tests/dlob/test.ts
CHANGED
|
@@ -4266,8 +4266,8 @@ describe('DLOB Spot Tests', () => {
|
|
|
4266
4266
|
});
|
|
4267
4267
|
|
|
4268
4268
|
it('Test two market orders to fill one limit order', () => {
|
|
4269
|
-
const
|
|
4270
|
-
const
|
|
4269
|
+
const fallbackAsk = new BN(15);
|
|
4270
|
+
const fallbackBid = new BN(8);
|
|
4271
4271
|
|
|
4272
4272
|
const user0 = Keypair.generate();
|
|
4273
4273
|
const user1 = Keypair.generate();
|
|
@@ -4280,7 +4280,7 @@ describe('DLOB Spot Tests', () => {
|
|
|
4280
4280
|
|
|
4281
4281
|
const slot = 12;
|
|
4282
4282
|
const oracle = {
|
|
4283
|
-
price:
|
|
4283
|
+
price: fallbackBid.add(fallbackAsk).div(new BN(2)),
|
|
4284
4284
|
slot: new BN(slot),
|
|
4285
4285
|
confidence: new BN(1),
|
|
4286
4286
|
hasSufficientNumberOfDataPoints: true,
|
|
@@ -4297,8 +4297,8 @@ describe('DLOB Spot Tests', () => {
|
|
|
4297
4297
|
new BN(14), // price
|
|
4298
4298
|
BASE_PRECISION, // quantity
|
|
4299
4299
|
PositionDirection.SHORT,
|
|
4300
|
-
|
|
4301
|
-
|
|
4300
|
+
fallbackBid,
|
|
4301
|
+
fallbackAsk,
|
|
4302
4302
|
undefined,
|
|
4303
4303
|
undefined,
|
|
4304
4304
|
undefined,
|
|
@@ -4314,8 +4314,8 @@ describe('DLOB Spot Tests', () => {
|
|
|
4314
4314
|
new BN(13), // price
|
|
4315
4315
|
BASE_PRECISION, // quantity
|
|
4316
4316
|
PositionDirection.SHORT,
|
|
4317
|
-
|
|
4318
|
-
|
|
4317
|
+
fallbackBid,
|
|
4318
|
+
fallbackAsk,
|
|
4319
4319
|
undefined,
|
|
4320
4320
|
undefined,
|
|
4321
4321
|
undefined,
|
|
@@ -4331,8 +4331,8 @@ describe('DLOB Spot Tests', () => {
|
|
|
4331
4331
|
new BN(8), // price <-- best price
|
|
4332
4332
|
new BN(3).mul(BASE_PRECISION), // quantity
|
|
4333
4333
|
PositionDirection.SHORT,
|
|
4334
|
-
|
|
4335
|
-
|
|
4334
|
+
fallbackBid,
|
|
4335
|
+
fallbackAsk,
|
|
4336
4336
|
undefined,
|
|
4337
4337
|
undefined,
|
|
4338
4338
|
undefined,
|
|
@@ -4361,11 +4361,11 @@ describe('DLOB Spot Tests', () => {
|
|
|
4361
4361
|
MarketType.SPOT,
|
|
4362
4362
|
4, // orderId
|
|
4363
4363
|
marketIndex,
|
|
4364
|
-
|
|
4364
|
+
fallbackAsk, // price
|
|
4365
4365
|
new BN(1).mul(BASE_PRECISION), // quantity
|
|
4366
4366
|
PositionDirection.LONG,
|
|
4367
|
-
|
|
4368
|
-
|
|
4367
|
+
fallbackBid,
|
|
4368
|
+
fallbackAsk
|
|
4369
4369
|
);
|
|
4370
4370
|
insertOrderToDLOB(
|
|
4371
4371
|
dlob,
|
|
@@ -4374,11 +4374,11 @@ describe('DLOB Spot Tests', () => {
|
|
|
4374
4374
|
MarketType.SPOT,
|
|
4375
4375
|
5, // orderId
|
|
4376
4376
|
marketIndex,
|
|
4377
|
-
|
|
4377
|
+
fallbackAsk, // price
|
|
4378
4378
|
new BN(2).mul(BASE_PRECISION), // quantity
|
|
4379
4379
|
PositionDirection.LONG,
|
|
4380
|
-
|
|
4381
|
-
|
|
4380
|
+
fallbackBid,
|
|
4381
|
+
fallbackAsk
|
|
4382
4382
|
);
|
|
4383
4383
|
|
|
4384
4384
|
const nodesToFillAfter = dlob.findNodesToFill(
|
|
@@ -4399,7 +4399,7 @@ describe('DLOB Spot Tests', () => {
|
|
|
4399
4399
|
);
|
|
4400
4400
|
console.log(`market nodes: ${mktNodes.length}`);
|
|
4401
4401
|
|
|
4402
|
-
printBookState(dlob, marketIndex,
|
|
4402
|
+
printBookState(dlob, marketIndex, fallbackBid, fallbackAsk, slot, oracle);
|
|
4403
4403
|
|
|
4404
4404
|
for (const n of nodesToFillAfter) {
|
|
4405
4405
|
console.log(
|
package/src/tx/types.js
DELETED
package/src/tx/utils.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.wrapInTx = void 0;
|
|
4
|
-
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
-
const COMPUTE_UNITS_DEFAULT = 200000;
|
|
6
|
-
function wrapInTx(instruction, computeUnits = 600000 // TODO, requires less code change
|
|
7
|
-
) {
|
|
8
|
-
const tx = new web3_js_1.Transaction();
|
|
9
|
-
if (computeUnits != COMPUTE_UNITS_DEFAULT) {
|
|
10
|
-
tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
11
|
-
units: computeUnits,
|
|
12
|
-
additionalFee: 0,
|
|
13
|
-
}));
|
|
14
|
-
}
|
|
15
|
-
return tx.add(instruction);
|
|
16
|
-
}
|
|
17
|
-
exports.wrapInTx = wrapInTx;
|