@drift-labs/sdk 2.16.0-beta.0 → 2.16.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dlob/DLOB.js +18 -2
- package/lib/driftClient.d.ts +43 -1
- package/lib/driftClient.js +125 -0
- package/lib/idl/drift.json +6 -1
- package/lib/math/margin.js +1 -3
- package/lib/math/spotBalance.js +4 -2
- package/lib/math/utils.d.ts +1 -1
- package/lib/math/utils.js +13 -21
- package/package.json +1 -1
- package/src/dlob/DLOB.ts +21 -2
- package/src/driftClient.ts +179 -0
- package/src/idl/drift.json +6 -1
- package/src/math/margin.ts +1 -5
- package/src/math/spotBalance.ts +12 -7
- package/src/math/utils.ts +13 -27
- package/tests/dlob/test.ts +16 -16
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,7 +1,7 @@
|
|
|
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
6
|
import { Connection, PublicKey, TransactionSignature, ConfirmOptions, Transaction, TransactionInstruction, AccountMeta, Signer } from '@solana/web3.js';
|
|
7
7
|
import { TokenFaucet } from './tokenFaucet';
|
|
@@ -212,6 +212,7 @@ export declare class DriftClient {
|
|
|
212
212
|
closePosition(marketIndex: number, limitPrice?: BN): Promise<TransactionSignature>;
|
|
213
213
|
/**
|
|
214
214
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
215
|
+
* @deprecated use modifyOrder instead
|
|
215
216
|
* @param orderId: The open order to modify
|
|
216
217
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
217
218
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -219,8 +220,29 @@ export declare class DriftClient {
|
|
|
219
220
|
* @returns
|
|
220
221
|
*/
|
|
221
222
|
modifyPerpOrder(orderId: number, newBaseAmount?: BN, newLimitPrice?: BN, newOraclePriceOffset?: number): Promise<TransactionSignature>;
|
|
223
|
+
/**
|
|
224
|
+
* Modifies an open order (spot or perp) by closing it and replacing it with a new order.
|
|
225
|
+
* @param orderId: The open order to modify
|
|
226
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
227
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
228
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
229
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
230
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
231
|
+
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
232
|
+
* @returns
|
|
233
|
+
*/
|
|
234
|
+
modifyOrder({ orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }: {
|
|
235
|
+
orderId: number;
|
|
236
|
+
newBaseAmount?: BN;
|
|
237
|
+
newLimitPrice?: BN;
|
|
238
|
+
newOraclePriceOffset?: number;
|
|
239
|
+
newOrderType?: OrderType;
|
|
240
|
+
newTriggerPrice?: BN;
|
|
241
|
+
isSpot?: boolean;
|
|
242
|
+
}): Promise<TransactionSignature>;
|
|
222
243
|
/**
|
|
223
244
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
245
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
224
246
|
* @param userOrderId: The open order to modify
|
|
225
247
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
226
248
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -228,6 +250,26 @@ export declare class DriftClient {
|
|
|
228
250
|
* @returns
|
|
229
251
|
*/
|
|
230
252
|
modifyPerpOrderByUserOrderId(userOrderId: number, newBaseAmount?: BN, newLimitPrice?: BN, newOraclePriceOffset?: number): Promise<TransactionSignature>;
|
|
253
|
+
/**
|
|
254
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
255
|
+
* @param userOrderId: The open order to modify
|
|
256
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
257
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
258
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
259
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
260
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
261
|
+
* @param isSpot: Set to true if the order is a spot order
|
|
262
|
+
* @returns
|
|
263
|
+
*/
|
|
264
|
+
modifyOrderByUserOrderId({ userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }: {
|
|
265
|
+
userOrderId: number;
|
|
266
|
+
newBaseAmount?: BN;
|
|
267
|
+
newLimitPrice?: BN;
|
|
268
|
+
newOraclePriceOffset?: number;
|
|
269
|
+
newOrderType?: OrderType;
|
|
270
|
+
newTriggerPrice?: BN;
|
|
271
|
+
isSpot?: boolean;
|
|
272
|
+
}): Promise<TransactionSignature>;
|
|
231
273
|
settlePNLs(users: {
|
|
232
274
|
settleeUserAccountPublicKey: PublicKey;
|
|
233
275
|
settleeUserAccount: UserAccount;
|
package/lib/driftClient.js
CHANGED
|
@@ -366,11 +366,16 @@ class DriftClient {
|
|
|
366
366
|
}
|
|
367
367
|
async updateUserMarginTradingEnabled(marginTradingEnabled, subAccountId = 0) {
|
|
368
368
|
const userAccountPublicKey = pda_1.getUserAccountPublicKeySync(this.program.programId, this.wallet.publicKey, subAccountId);
|
|
369
|
+
await this.addUser(subAccountId);
|
|
370
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
371
|
+
userAccounts: [this.getUserAccount(subAccountId)],
|
|
372
|
+
});
|
|
369
373
|
const tx = await this.program.transaction.updateUserMarginTradingEnabled(subAccountId, marginTradingEnabled, {
|
|
370
374
|
accounts: {
|
|
371
375
|
user: userAccountPublicKey,
|
|
372
376
|
authority: this.wallet.publicKey,
|
|
373
377
|
},
|
|
378
|
+
remainingAccounts,
|
|
374
379
|
});
|
|
375
380
|
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
376
381
|
return txSig;
|
|
@@ -1745,6 +1750,7 @@ class DriftClient {
|
|
|
1745
1750
|
}
|
|
1746
1751
|
/**
|
|
1747
1752
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
1753
|
+
* @deprecated use modifyOrder instead
|
|
1748
1754
|
* @param orderId: The open order to modify
|
|
1749
1755
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1750
1756
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -1791,8 +1797,68 @@ class DriftClient {
|
|
|
1791
1797
|
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1792
1798
|
return txSig;
|
|
1793
1799
|
}
|
|
1800
|
+
/**
|
|
1801
|
+
* Modifies an open order (spot or perp) by closing it and replacing it with a new order.
|
|
1802
|
+
* @param orderId: The open order to modify
|
|
1803
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1804
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1805
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1806
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
1807
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
1808
|
+
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
1809
|
+
* @returns
|
|
1810
|
+
*/
|
|
1811
|
+
async modifyOrder({ orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }) {
|
|
1812
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
1813
|
+
throw new Error(`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`);
|
|
1814
|
+
}
|
|
1815
|
+
const openOrder = this.getUser().getOrder(orderId);
|
|
1816
|
+
if (!openOrder) {
|
|
1817
|
+
throw new Error(`No open order with id ${orderId.toString()}`);
|
|
1818
|
+
}
|
|
1819
|
+
const cancelOrderIx = await this.getCancelOrderIx(orderId);
|
|
1820
|
+
const newOrderParams = {
|
|
1821
|
+
orderType: newOrderType || openOrder.orderType,
|
|
1822
|
+
marketType: openOrder.marketType,
|
|
1823
|
+
direction: openOrder.direction,
|
|
1824
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
1825
|
+
price: newLimitPrice || openOrder.price,
|
|
1826
|
+
marketIndex: openOrder.marketIndex,
|
|
1827
|
+
reduceOnly: openOrder.reduceOnly,
|
|
1828
|
+
postOnly: openOrder.postOnly,
|
|
1829
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
1830
|
+
triggerPrice: newTriggerPrice || openOrder.triggerPrice,
|
|
1831
|
+
triggerCondition: openOrder.triggerCondition,
|
|
1832
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
1833
|
+
auctionDuration: openOrder.auctionDuration,
|
|
1834
|
+
maxTs: openOrder.maxTs,
|
|
1835
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
1836
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
1837
|
+
userOrderId: openOrder.userOrderId,
|
|
1838
|
+
};
|
|
1839
|
+
const placeOrderIx = isSpot
|
|
1840
|
+
? await this.getPlaceSpotOrderIx(newOrderParams)
|
|
1841
|
+
: await this.getPlacePerpOrderIx(newOrderParams);
|
|
1842
|
+
const tx = new web3_js_1.Transaction();
|
|
1843
|
+
tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
1844
|
+
units: 1000000,
|
|
1845
|
+
additionalFee: 0,
|
|
1846
|
+
}));
|
|
1847
|
+
tx.add(cancelOrderIx);
|
|
1848
|
+
tx.add(placeOrderIx);
|
|
1849
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
1850
|
+
if (isSpot) {
|
|
1851
|
+
this.spotMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1852
|
+
this.spotMarketLastSlotCache.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, slot);
|
|
1853
|
+
}
|
|
1854
|
+
else {
|
|
1855
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1856
|
+
}
|
|
1857
|
+
return txSig;
|
|
1858
|
+
}
|
|
1794
1859
|
/**
|
|
1795
1860
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
1861
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
1796
1862
|
* @param userOrderId: The open order to modify
|
|
1797
1863
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1798
1864
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -1839,6 +1905,65 @@ class DriftClient {
|
|
|
1839
1905
|
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1840
1906
|
return txSig;
|
|
1841
1907
|
}
|
|
1908
|
+
/**
|
|
1909
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
1910
|
+
* @param userOrderId: The open order to modify
|
|
1911
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1912
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1913
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1914
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
1915
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
1916
|
+
* @param isSpot: Set to true if the order is a spot order
|
|
1917
|
+
* @returns
|
|
1918
|
+
*/
|
|
1919
|
+
async modifyOrderByUserOrderId({ userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }) {
|
|
1920
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
1921
|
+
throw new Error(`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`);
|
|
1922
|
+
}
|
|
1923
|
+
const openOrder = this.getUser().getOrderByUserOrderId(userOrderId);
|
|
1924
|
+
if (!openOrder) {
|
|
1925
|
+
throw new Error(`No open order with user order id ${userOrderId.toString()}`);
|
|
1926
|
+
}
|
|
1927
|
+
const cancelOrderIx = await this.getCancelOrderByUserIdIx(userOrderId);
|
|
1928
|
+
const newOrderParams = {
|
|
1929
|
+
orderType: newOrderType || openOrder.orderType,
|
|
1930
|
+
marketType: openOrder.marketType,
|
|
1931
|
+
direction: openOrder.direction,
|
|
1932
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
1933
|
+
price: newLimitPrice || openOrder.price,
|
|
1934
|
+
marketIndex: openOrder.marketIndex,
|
|
1935
|
+
reduceOnly: openOrder.reduceOnly,
|
|
1936
|
+
postOnly: openOrder.postOnly,
|
|
1937
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
1938
|
+
triggerPrice: newTriggerPrice || openOrder.triggerPrice,
|
|
1939
|
+
triggerCondition: openOrder.triggerCondition,
|
|
1940
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
1941
|
+
auctionDuration: openOrder.auctionDuration,
|
|
1942
|
+
maxTs: openOrder.maxTs,
|
|
1943
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
1944
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
1945
|
+
userOrderId: openOrder.userOrderId,
|
|
1946
|
+
};
|
|
1947
|
+
const placeOrderIx = isSpot
|
|
1948
|
+
? await this.getPlaceSpotOrderIx(newOrderParams)
|
|
1949
|
+
: await this.getPlacePerpOrderIx(newOrderParams);
|
|
1950
|
+
const tx = new web3_js_1.Transaction();
|
|
1951
|
+
tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
1952
|
+
units: 1000000,
|
|
1953
|
+
additionalFee: 0,
|
|
1954
|
+
}));
|
|
1955
|
+
tx.add(cancelOrderIx);
|
|
1956
|
+
tx.add(placeOrderIx);
|
|
1957
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
1958
|
+
if (isSpot) {
|
|
1959
|
+
this.spotMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1960
|
+
this.spotMarketLastSlotCache.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, slot);
|
|
1961
|
+
}
|
|
1962
|
+
else {
|
|
1963
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1964
|
+
}
|
|
1965
|
+
return txSig;
|
|
1966
|
+
}
|
|
1842
1967
|
async settlePNLs(users, marketIndex) {
|
|
1843
1968
|
const ixs = [];
|
|
1844
1969
|
for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
|
package/lib/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.16.0-beta.
|
|
2
|
+
"version": "2.16.0-beta.3",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -8569,6 +8569,11 @@
|
|
|
8569
8569
|
"code": 6225,
|
|
8570
8570
|
"name": "InvalidOracleForSettlePnl",
|
|
8571
8571
|
"msg": "InvalidOracleForSettlePnl"
|
|
8572
|
+
},
|
|
8573
|
+
{
|
|
8574
|
+
"code": 6226,
|
|
8575
|
+
"name": "MarginOrdersOpen",
|
|
8576
|
+
"msg": "MarginOrdersOpen"
|
|
8572
8577
|
}
|
|
8573
8578
|
]
|
|
8574
8579
|
}
|
package/lib/math/margin.js
CHANGED
|
@@ -12,9 +12,7 @@ imfFactor, liabilityWeight, precision) {
|
|
|
12
12
|
return liabilityWeight;
|
|
13
13
|
}
|
|
14
14
|
const sizeSqrt = utils_1.squareRootBN(size.abs().mul(new anchor_1.BN(10)).add(new anchor_1.BN(1))); //1e9 -> 1e10 -> 1e5
|
|
15
|
-
const
|
|
16
|
-
assert_1.assert(denom0.gt(numericConstants_1.ZERO));
|
|
17
|
-
const liabilityWeightNumerator = liabilityWeight.sub(liabilityWeight.div(anchor_1.BN.max(new anchor_1.BN(1), numericConstants_1.SPOT_MARKET_IMF_PRECISION.div(imfFactor))));
|
|
15
|
+
const liabilityWeightNumerator = liabilityWeight.sub(liabilityWeight.div(new anchor_1.BN(5)));
|
|
18
16
|
const denom = new anchor_1.BN(100000).mul(numericConstants_1.SPOT_MARKET_IMF_PRECISION).div(precision);
|
|
19
17
|
assert_1.assert(denom.gt(numericConstants_1.ZERO));
|
|
20
18
|
const sizePremiumLiabilityWeight = liabilityWeightNumerator.add(sizeSqrt // 1e5
|
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;
|
package/package.json
CHANGED
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
|
@@ -612,6 +612,12 @@ export class DriftClient {
|
|
|
612
612
|
this.wallet.publicKey,
|
|
613
613
|
subAccountId
|
|
614
614
|
);
|
|
615
|
+
|
|
616
|
+
await this.addUser(subAccountId);
|
|
617
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
618
|
+
userAccounts: [this.getUserAccount(subAccountId)],
|
|
619
|
+
});
|
|
620
|
+
|
|
615
621
|
const tx = await this.program.transaction.updateUserMarginTradingEnabled(
|
|
616
622
|
subAccountId,
|
|
617
623
|
marginTradingEnabled,
|
|
@@ -620,6 +626,7 @@ export class DriftClient {
|
|
|
620
626
|
user: userAccountPublicKey,
|
|
621
627
|
authority: this.wallet.publicKey,
|
|
622
628
|
},
|
|
629
|
+
remainingAccounts,
|
|
623
630
|
}
|
|
624
631
|
);
|
|
625
632
|
|
|
@@ -3011,6 +3018,7 @@ export class DriftClient {
|
|
|
3011
3018
|
|
|
3012
3019
|
/**
|
|
3013
3020
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
3021
|
+
* @deprecated use modifyOrder instead
|
|
3014
3022
|
* @param orderId: The open order to modify
|
|
3015
3023
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3016
3024
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -3070,8 +3078,93 @@ export class DriftClient {
|
|
|
3070
3078
|
return txSig;
|
|
3071
3079
|
}
|
|
3072
3080
|
|
|
3081
|
+
/**
|
|
3082
|
+
* Modifies an open order (spot or perp) by closing it and replacing it with a new order.
|
|
3083
|
+
* @param orderId: The open order to modify
|
|
3084
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3085
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3086
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3087
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
3088
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
3089
|
+
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
3090
|
+
* @returns
|
|
3091
|
+
*/
|
|
3092
|
+
public async modifyOrder({
|
|
3093
|
+
orderId,
|
|
3094
|
+
newBaseAmount,
|
|
3095
|
+
newLimitPrice,
|
|
3096
|
+
newOraclePriceOffset,
|
|
3097
|
+
newOrderType,
|
|
3098
|
+
newTriggerPrice,
|
|
3099
|
+
isSpot,
|
|
3100
|
+
}: {
|
|
3101
|
+
orderId: number;
|
|
3102
|
+
newBaseAmount?: BN;
|
|
3103
|
+
newLimitPrice?: BN;
|
|
3104
|
+
newOraclePriceOffset?: number;
|
|
3105
|
+
newOrderType?: OrderType;
|
|
3106
|
+
newTriggerPrice?: BN;
|
|
3107
|
+
isSpot?: boolean;
|
|
3108
|
+
}): Promise<TransactionSignature> {
|
|
3109
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
3110
|
+
throw new Error(
|
|
3111
|
+
`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`
|
|
3112
|
+
);
|
|
3113
|
+
}
|
|
3114
|
+
|
|
3115
|
+
const openOrder = this.getUser().getOrder(orderId);
|
|
3116
|
+
if (!openOrder) {
|
|
3117
|
+
throw new Error(`No open order with id ${orderId.toString()}`);
|
|
3118
|
+
}
|
|
3119
|
+
const cancelOrderIx = await this.getCancelOrderIx(orderId);
|
|
3120
|
+
|
|
3121
|
+
const newOrderParams: OptionalOrderParams = {
|
|
3122
|
+
orderType: newOrderType || openOrder.orderType,
|
|
3123
|
+
marketType: openOrder.marketType,
|
|
3124
|
+
direction: openOrder.direction,
|
|
3125
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
3126
|
+
price: newLimitPrice || openOrder.price,
|
|
3127
|
+
marketIndex: openOrder.marketIndex,
|
|
3128
|
+
reduceOnly: openOrder.reduceOnly,
|
|
3129
|
+
postOnly: openOrder.postOnly,
|
|
3130
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
3131
|
+
triggerPrice: newTriggerPrice || openOrder.triggerPrice,
|
|
3132
|
+
triggerCondition: openOrder.triggerCondition,
|
|
3133
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
3134
|
+
auctionDuration: openOrder.auctionDuration,
|
|
3135
|
+
maxTs: openOrder.maxTs,
|
|
3136
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
3137
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
3138
|
+
userOrderId: openOrder.userOrderId,
|
|
3139
|
+
};
|
|
3140
|
+
const placeOrderIx = isSpot
|
|
3141
|
+
? await this.getPlaceSpotOrderIx(newOrderParams)
|
|
3142
|
+
: await this.getPlacePerpOrderIx(newOrderParams);
|
|
3143
|
+
|
|
3144
|
+
const tx = new Transaction();
|
|
3145
|
+
tx.add(
|
|
3146
|
+
ComputeBudgetProgram.requestUnits({
|
|
3147
|
+
units: 1_000_000,
|
|
3148
|
+
additionalFee: 0,
|
|
3149
|
+
})
|
|
3150
|
+
);
|
|
3151
|
+
tx.add(cancelOrderIx);
|
|
3152
|
+
tx.add(placeOrderIx);
|
|
3153
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
3154
|
+
|
|
3155
|
+
if (isSpot) {
|
|
3156
|
+
this.spotMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3157
|
+
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
|
|
3158
|
+
} else {
|
|
3159
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3160
|
+
}
|
|
3161
|
+
|
|
3162
|
+
return txSig;
|
|
3163
|
+
}
|
|
3164
|
+
|
|
3073
3165
|
/**
|
|
3074
3166
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
3167
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
3075
3168
|
* @param userOrderId: The open order to modify
|
|
3076
3169
|
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3077
3170
|
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
@@ -3133,6 +3226,92 @@ export class DriftClient {
|
|
|
3133
3226
|
return txSig;
|
|
3134
3227
|
}
|
|
3135
3228
|
|
|
3229
|
+
/**
|
|
3230
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
3231
|
+
* @param userOrderId: The open order to modify
|
|
3232
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3233
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3234
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3235
|
+
* @param newOrderType: Optional - New order type for the order.
|
|
3236
|
+
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
3237
|
+
* @param isSpot: Set to true if the order is a spot order
|
|
3238
|
+
* @returns
|
|
3239
|
+
*/
|
|
3240
|
+
public async modifyOrderByUserOrderId({
|
|
3241
|
+
userOrderId,
|
|
3242
|
+
newBaseAmount,
|
|
3243
|
+
newLimitPrice,
|
|
3244
|
+
newOraclePriceOffset,
|
|
3245
|
+
newOrderType,
|
|
3246
|
+
newTriggerPrice,
|
|
3247
|
+
isSpot,
|
|
3248
|
+
}: {
|
|
3249
|
+
userOrderId: number;
|
|
3250
|
+
newBaseAmount?: BN;
|
|
3251
|
+
newLimitPrice?: BN;
|
|
3252
|
+
newOraclePriceOffset?: number;
|
|
3253
|
+
newOrderType?: OrderType;
|
|
3254
|
+
newTriggerPrice?: BN;
|
|
3255
|
+
isSpot?: boolean;
|
|
3256
|
+
}): Promise<TransactionSignature> {
|
|
3257
|
+
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
3258
|
+
throw new Error(
|
|
3259
|
+
`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`
|
|
3260
|
+
);
|
|
3261
|
+
}
|
|
3262
|
+
|
|
3263
|
+
const openOrder = this.getUser().getOrderByUserOrderId(userOrderId);
|
|
3264
|
+
if (!openOrder) {
|
|
3265
|
+
throw new Error(
|
|
3266
|
+
`No open order with user order id ${userOrderId.toString()}`
|
|
3267
|
+
);
|
|
3268
|
+
}
|
|
3269
|
+
const cancelOrderIx = await this.getCancelOrderByUserIdIx(userOrderId);
|
|
3270
|
+
|
|
3271
|
+
const newOrderParams: OptionalOrderParams = {
|
|
3272
|
+
orderType: newOrderType || openOrder.orderType,
|
|
3273
|
+
marketType: openOrder.marketType,
|
|
3274
|
+
direction: openOrder.direction,
|
|
3275
|
+
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
3276
|
+
price: newLimitPrice || openOrder.price,
|
|
3277
|
+
marketIndex: openOrder.marketIndex,
|
|
3278
|
+
reduceOnly: openOrder.reduceOnly,
|
|
3279
|
+
postOnly: openOrder.postOnly,
|
|
3280
|
+
immediateOrCancel: openOrder.immediateOrCancel,
|
|
3281
|
+
triggerPrice: newTriggerPrice || openOrder.triggerPrice,
|
|
3282
|
+
triggerCondition: openOrder.triggerCondition,
|
|
3283
|
+
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
3284
|
+
auctionDuration: openOrder.auctionDuration,
|
|
3285
|
+
maxTs: openOrder.maxTs,
|
|
3286
|
+
auctionStartPrice: openOrder.auctionStartPrice,
|
|
3287
|
+
auctionEndPrice: openOrder.auctionEndPrice,
|
|
3288
|
+
userOrderId: openOrder.userOrderId,
|
|
3289
|
+
};
|
|
3290
|
+
const placeOrderIx = isSpot
|
|
3291
|
+
? await this.getPlaceSpotOrderIx(newOrderParams)
|
|
3292
|
+
: await this.getPlacePerpOrderIx(newOrderParams);
|
|
3293
|
+
|
|
3294
|
+
const tx = new Transaction();
|
|
3295
|
+
tx.add(
|
|
3296
|
+
ComputeBudgetProgram.requestUnits({
|
|
3297
|
+
units: 1_000_000,
|
|
3298
|
+
additionalFee: 0,
|
|
3299
|
+
})
|
|
3300
|
+
);
|
|
3301
|
+
tx.add(cancelOrderIx);
|
|
3302
|
+
tx.add(placeOrderIx);
|
|
3303
|
+
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
3304
|
+
|
|
3305
|
+
if (isSpot) {
|
|
3306
|
+
this.spotMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3307
|
+
this.spotMarketLastSlotCache.set(QUOTE_SPOT_MARKET_INDEX, slot);
|
|
3308
|
+
} else {
|
|
3309
|
+
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3310
|
+
}
|
|
3311
|
+
|
|
3312
|
+
return txSig;
|
|
3313
|
+
}
|
|
3314
|
+
|
|
3136
3315
|
public async settlePNLs(
|
|
3137
3316
|
users: {
|
|
3138
3317
|
settleeUserAccountPublicKey: PublicKey;
|
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.16.0-beta.
|
|
2
|
+
"version": "2.16.0-beta.3",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -8569,6 +8569,11 @@
|
|
|
8569
8569
|
"code": 6225,
|
|
8570
8570
|
"name": "InvalidOracleForSettlePnl",
|
|
8571
8571
|
"msg": "InvalidOracleForSettlePnl"
|
|
8572
|
+
},
|
|
8573
|
+
{
|
|
8574
|
+
"code": 6226,
|
|
8575
|
+
"name": "MarginOrdersOpen",
|
|
8576
|
+
"msg": "MarginOrdersOpen"
|
|
8572
8577
|
}
|
|
8573
8578
|
]
|
|
8574
8579
|
}
|
package/src/math/margin.ts
CHANGED
|
@@ -24,12 +24,8 @@ export function calculateSizePremiumLiabilityWeight(
|
|
|
24
24
|
|
|
25
25
|
const sizeSqrt = squareRootBN(size.abs().mul(new BN(10)).add(new BN(1))); //1e9 -> 1e10 -> 1e5
|
|
26
26
|
|
|
27
|
-
const denom0 = BN.max(new BN(1), SPOT_MARKET_IMF_PRECISION.div(imfFactor));
|
|
28
|
-
assert(denom0.gt(ZERO));
|
|
29
27
|
const liabilityWeightNumerator = liabilityWeight.sub(
|
|
30
|
-
liabilityWeight.div(
|
|
31
|
-
BN.max(new BN(1), SPOT_MARKET_IMF_PRECISION.div(imfFactor))
|
|
32
|
-
)
|
|
28
|
+
liabilityWeight.div(new BN(5))
|
|
33
29
|
);
|
|
34
30
|
|
|
35
31
|
const denom = new BN(100_000).mul(SPOT_MARKET_IMF_PRECISION).div(precision);
|
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/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(
|