@drift-labs/sdk 2.16.0-beta.3 → 2.17.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config.d.ts +1 -0
- package/lib/config.js +2 -0
- package/lib/driftClient.d.ts +30 -14
- package/lib/driftClient.js +84 -103
- package/lib/driftClientConfig.d.ts +1 -0
- package/lib/idl/drift.json +21 -2
- package/lib/tx/retryTxSender.d.ts +4 -2
- package/lib/tx/retryTxSender.js +32 -12
- package/lib/tx/types.d.ts +2 -1
- package/lib/types.d.ts +12 -1
- package/lib/types.js +8 -2
- package/package.json +4 -3
- package/src/config.ts +3 -0
- package/src/driftClient.ts +116 -123
- package/src/driftClientConfig.ts +1 -0
- package/src/idl/drift.json +21 -2
- package/src/tx/retryTxSender.ts +67 -24
- package/src/tx/types.ts +9 -0
- package/src/types.ts +8 -2
- 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/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, OrderType, 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, OrderTriggerCondition } 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
|
|
@@ -220,6 +222,16 @@ export declare class DriftClient {
|
|
|
220
222
|
* @returns
|
|
221
223
|
*/
|
|
222
224
|
modifyPerpOrder(orderId: number, newBaseAmount?: BN, newLimitPrice?: BN, newOraclePriceOffset?: number): Promise<TransactionSignature>;
|
|
225
|
+
/**
|
|
226
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
227
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
228
|
+
* @param userOrderId: The open order to modify
|
|
229
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
230
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
231
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
232
|
+
* @returns
|
|
233
|
+
*/
|
|
234
|
+
modifyPerpOrderByUserOrderId(userOrderId: number, newBaseAmount?: BN, newLimitPrice?: BN, newOraclePriceOffset?: number): Promise<TransactionSignature>;
|
|
223
235
|
/**
|
|
224
236
|
* Modifies an open order (spot or perp) by closing it and replacing it with a new order.
|
|
225
237
|
* @param orderId: The open order to modify
|
|
@@ -229,27 +241,24 @@ export declare class DriftClient {
|
|
|
229
241
|
* @param newOrderType: Optional - New order type for the order.
|
|
230
242
|
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
231
243
|
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
244
|
+
* @param auctionDuration: Only required if order type changed to market from something else
|
|
245
|
+
* @param auctionStartPrice: Only required if order type changed to market from something else
|
|
246
|
+
* @param auctionEndPrice: Only required if order type changed to market from something else
|
|
232
247
|
* @returns
|
|
233
248
|
*/
|
|
234
|
-
modifyOrder({ orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }: {
|
|
249
|
+
modifyOrder({ orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, newTriggerCondition, isSpot, auctionDuration, auctionStartPrice, auctionEndPrice, }: {
|
|
235
250
|
orderId: number;
|
|
236
251
|
newBaseAmount?: BN;
|
|
237
252
|
newLimitPrice?: BN;
|
|
238
253
|
newOraclePriceOffset?: number;
|
|
239
254
|
newOrderType?: OrderType;
|
|
240
255
|
newTriggerPrice?: BN;
|
|
256
|
+
newTriggerCondition?: OrderTriggerCondition;
|
|
241
257
|
isSpot?: boolean;
|
|
258
|
+
auctionDuration?: number;
|
|
259
|
+
auctionStartPrice?: BN;
|
|
260
|
+
auctionEndPrice?: BN;
|
|
242
261
|
}): Promise<TransactionSignature>;
|
|
243
|
-
/**
|
|
244
|
-
* Modifies an open order by closing it and replacing it with a new order.
|
|
245
|
-
* @deprecated use modifyOrderByUserOrderId instead
|
|
246
|
-
* @param userOrderId: The open order to modify
|
|
247
|
-
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
248
|
-
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
249
|
-
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
250
|
-
* @returns
|
|
251
|
-
*/
|
|
252
|
-
modifyPerpOrderByUserOrderId(userOrderId: number, newBaseAmount?: BN, newLimitPrice?: BN, newOraclePriceOffset?: number): Promise<TransactionSignature>;
|
|
253
262
|
/**
|
|
254
263
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
255
264
|
* @param userOrderId: The open order to modify
|
|
@@ -259,16 +268,23 @@ export declare class DriftClient {
|
|
|
259
268
|
* @param newOrderType: Optional - New order type for the order.
|
|
260
269
|
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
261
270
|
* @param isSpot: Set to true if the order is a spot order
|
|
271
|
+
* @param auctionDuration: Only required if order type changed to market from something else
|
|
272
|
+
* @param auctionStartPrice: Only required if order type changed to market from something else
|
|
273
|
+
* @param auctionEndPrice: Only required if order type changed to market from something else
|
|
262
274
|
* @returns
|
|
263
275
|
*/
|
|
264
|
-
modifyOrderByUserOrderId({ userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }: {
|
|
276
|
+
modifyOrderByUserOrderId({ userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, newTriggerCondition, isSpot, auctionDuration, auctionStartPrice, auctionEndPrice, }: {
|
|
265
277
|
userOrderId: number;
|
|
266
278
|
newBaseAmount?: BN;
|
|
267
279
|
newLimitPrice?: BN;
|
|
268
280
|
newOraclePriceOffset?: number;
|
|
269
281
|
newOrderType?: OrderType;
|
|
270
282
|
newTriggerPrice?: BN;
|
|
283
|
+
newTriggerCondition?: OrderTriggerCondition;
|
|
271
284
|
isSpot?: boolean;
|
|
285
|
+
auctionDuration?: number;
|
|
286
|
+
auctionStartPrice?: BN;
|
|
287
|
+
auctionEndPrice?: BN;
|
|
272
288
|
}): Promise<TransactionSignature>;
|
|
273
289
|
settlePNLs(users: {
|
|
274
290
|
settleeUserAccountPublicKey: PublicKey;
|
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
|
|
@@ -1758,44 +1769,29 @@ class DriftClient {
|
|
|
1758
1769
|
* @returns
|
|
1759
1770
|
*/
|
|
1760
1771
|
async modifyPerpOrder(orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset) {
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
auctionStartPrice: openOrder.auctionStartPrice,
|
|
1785
|
-
auctionEndPrice: openOrder.auctionEndPrice,
|
|
1786
|
-
userOrderId: openOrder.userOrderId,
|
|
1787
|
-
};
|
|
1788
|
-
const placeOrderIx = await this.getPlacePerpOrderIx(newOrderParams);
|
|
1789
|
-
const tx = new web3_js_1.Transaction();
|
|
1790
|
-
tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
1791
|
-
units: 1000000,
|
|
1792
|
-
additionalFee: 0,
|
|
1793
|
-
}));
|
|
1794
|
-
tx.add(cancelOrderIx);
|
|
1795
|
-
tx.add(placeOrderIx);
|
|
1796
|
-
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
1797
|
-
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1798
|
-
return txSig;
|
|
1772
|
+
return this.modifyOrder({
|
|
1773
|
+
orderId,
|
|
1774
|
+
newBaseAmount,
|
|
1775
|
+
newLimitPrice,
|
|
1776
|
+
newOraclePriceOffset,
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1779
|
+
/**
|
|
1780
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
1781
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
1782
|
+
* @param userOrderId: The open order to modify
|
|
1783
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1784
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1785
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1786
|
+
* @returns
|
|
1787
|
+
*/
|
|
1788
|
+
async modifyPerpOrderByUserOrderId(userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset) {
|
|
1789
|
+
return this.modifyOrderByUserOrderId({
|
|
1790
|
+
userOrderId,
|
|
1791
|
+
newBaseAmount,
|
|
1792
|
+
newLimitPrice,
|
|
1793
|
+
newOraclePriceOffset,
|
|
1794
|
+
});
|
|
1799
1795
|
}
|
|
1800
1796
|
/**
|
|
1801
1797
|
* Modifies an open order (spot or perp) by closing it and replacing it with a new order.
|
|
@@ -1806,9 +1802,12 @@ class DriftClient {
|
|
|
1806
1802
|
* @param newOrderType: Optional - New order type for the order.
|
|
1807
1803
|
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
1808
1804
|
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
1805
|
+
* @param auctionDuration: Only required if order type changed to market from something else
|
|
1806
|
+
* @param auctionStartPrice: Only required if order type changed to market from something else
|
|
1807
|
+
* @param auctionEndPrice: Only required if order type changed to market from something else
|
|
1809
1808
|
* @returns
|
|
1810
1809
|
*/
|
|
1811
|
-
async modifyOrder({ orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }) {
|
|
1810
|
+
async modifyOrder({ orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, newTriggerCondition, isSpot, auctionDuration, auctionStartPrice, auctionEndPrice, }) {
|
|
1812
1811
|
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
1813
1812
|
throw new Error(`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`);
|
|
1814
1813
|
}
|
|
@@ -1817,23 +1816,37 @@ class DriftClient {
|
|
|
1817
1816
|
throw new Error(`No open order with id ${orderId.toString()}`);
|
|
1818
1817
|
}
|
|
1819
1818
|
const cancelOrderIx = await this.getCancelOrderIx(orderId);
|
|
1819
|
+
const orderTypeHasTrigger = newOrderType
|
|
1820
|
+
? types_1.isOneOfVariant(newOrderType, ['triggerlimit', 'triggerMarket'])
|
|
1821
|
+
: types_1.isOneOfVariant(openOrder.orderType, ['triggerLimit', 'triggerMarket']);
|
|
1822
|
+
const orderTypeHasLimitPrice = newOrderType
|
|
1823
|
+
? types_1.isOneOfVariant(newOrderType, ['triggerLimit', 'limit'])
|
|
1824
|
+
: types_1.isOneOfVariant(openOrder.orderType, ['triggerLimit', 'limit']);
|
|
1820
1825
|
const newOrderParams = {
|
|
1821
1826
|
orderType: newOrderType || openOrder.orderType,
|
|
1822
1827
|
marketType: openOrder.marketType,
|
|
1823
1828
|
direction: openOrder.direction,
|
|
1824
1829
|
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
1825
|
-
price:
|
|
1830
|
+
price: orderTypeHasLimitPrice
|
|
1831
|
+
? newLimitPrice || openOrder.price
|
|
1832
|
+
: undefined,
|
|
1826
1833
|
marketIndex: openOrder.marketIndex,
|
|
1827
1834
|
reduceOnly: openOrder.reduceOnly,
|
|
1828
|
-
postOnly: openOrder.postOnly
|
|
1835
|
+
postOnly: openOrder.postOnly
|
|
1836
|
+
? types_1.PostOnlyParams.MUST_POST_ONLY
|
|
1837
|
+
: types_1.PostOnlyParams.NONE,
|
|
1829
1838
|
immediateOrCancel: openOrder.immediateOrCancel,
|
|
1830
|
-
triggerPrice:
|
|
1831
|
-
|
|
1839
|
+
triggerPrice: orderTypeHasTrigger
|
|
1840
|
+
? newTriggerPrice || openOrder.triggerPrice
|
|
1841
|
+
: undefined,
|
|
1842
|
+
triggerCondition: orderTypeHasTrigger
|
|
1843
|
+
? newTriggerCondition || openOrder.triggerCondition
|
|
1844
|
+
: undefined,
|
|
1832
1845
|
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
1833
|
-
auctionDuration: openOrder.auctionDuration,
|
|
1846
|
+
auctionDuration: auctionDuration || openOrder.auctionDuration,
|
|
1834
1847
|
maxTs: openOrder.maxTs,
|
|
1835
|
-
auctionStartPrice: openOrder.auctionStartPrice,
|
|
1836
|
-
auctionEndPrice: openOrder.auctionEndPrice,
|
|
1848
|
+
auctionStartPrice: auctionStartPrice || openOrder.auctionStartPrice,
|
|
1849
|
+
auctionEndPrice: auctionEndPrice || openOrder.auctionEndPrice,
|
|
1837
1850
|
userOrderId: openOrder.userOrderId,
|
|
1838
1851
|
};
|
|
1839
1852
|
const placeOrderIx = isSpot
|
|
@@ -1856,55 +1869,6 @@ class DriftClient {
|
|
|
1856
1869
|
}
|
|
1857
1870
|
return txSig;
|
|
1858
1871
|
}
|
|
1859
|
-
/**
|
|
1860
|
-
* Modifies an open order by closing it and replacing it with a new order.
|
|
1861
|
-
* @deprecated use modifyOrderByUserOrderId instead
|
|
1862
|
-
* @param userOrderId: The open order to modify
|
|
1863
|
-
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1864
|
-
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1865
|
-
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
1866
|
-
* @returns
|
|
1867
|
-
*/
|
|
1868
|
-
async modifyPerpOrderByUserOrderId(userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset) {
|
|
1869
|
-
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
1870
|
-
throw new Error(`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`);
|
|
1871
|
-
}
|
|
1872
|
-
const openOrder = this.getUser().getOrderByUserOrderId(userOrderId);
|
|
1873
|
-
if (!openOrder) {
|
|
1874
|
-
throw new Error(`No open order with user order id ${userOrderId.toString()}`);
|
|
1875
|
-
}
|
|
1876
|
-
const cancelOrderIx = await this.getCancelOrderByUserIdIx(userOrderId);
|
|
1877
|
-
const newOrderParams = {
|
|
1878
|
-
orderType: openOrder.orderType,
|
|
1879
|
-
marketType: openOrder.marketType,
|
|
1880
|
-
direction: openOrder.direction,
|
|
1881
|
-
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
1882
|
-
price: newLimitPrice || openOrder.price,
|
|
1883
|
-
marketIndex: openOrder.marketIndex,
|
|
1884
|
-
reduceOnly: openOrder.reduceOnly,
|
|
1885
|
-
postOnly: openOrder.postOnly,
|
|
1886
|
-
immediateOrCancel: openOrder.immediateOrCancel,
|
|
1887
|
-
triggerPrice: openOrder.triggerPrice,
|
|
1888
|
-
triggerCondition: openOrder.triggerCondition,
|
|
1889
|
-
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
1890
|
-
auctionDuration: openOrder.auctionDuration,
|
|
1891
|
-
maxTs: openOrder.maxTs,
|
|
1892
|
-
auctionStartPrice: openOrder.auctionStartPrice,
|
|
1893
|
-
auctionEndPrice: openOrder.auctionEndPrice,
|
|
1894
|
-
userOrderId: openOrder.userOrderId,
|
|
1895
|
-
};
|
|
1896
|
-
const placeOrderIx = await this.getPlacePerpOrderIx(newOrderParams);
|
|
1897
|
-
const tx = new web3_js_1.Transaction();
|
|
1898
|
-
tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
|
|
1899
|
-
units: 1000000,
|
|
1900
|
-
additionalFee: 0,
|
|
1901
|
-
}));
|
|
1902
|
-
tx.add(cancelOrderIx);
|
|
1903
|
-
tx.add(placeOrderIx);
|
|
1904
|
-
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
1905
|
-
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
1906
|
-
return txSig;
|
|
1907
|
-
}
|
|
1908
1872
|
/**
|
|
1909
1873
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
1910
1874
|
* @param userOrderId: The open order to modify
|
|
@@ -1914,9 +1878,12 @@ class DriftClient {
|
|
|
1914
1878
|
* @param newOrderType: Optional - New order type for the order.
|
|
1915
1879
|
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
1916
1880
|
* @param isSpot: Set to true if the order is a spot order
|
|
1881
|
+
* @param auctionDuration: Only required if order type changed to market from something else
|
|
1882
|
+
* @param auctionStartPrice: Only required if order type changed to market from something else
|
|
1883
|
+
* @param auctionEndPrice: Only required if order type changed to market from something else
|
|
1917
1884
|
* @returns
|
|
1918
1885
|
*/
|
|
1919
|
-
async modifyOrderByUserOrderId({ userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, isSpot, }) {
|
|
1886
|
+
async modifyOrderByUserOrderId({ userOrderId, newBaseAmount, newLimitPrice, newOraclePriceOffset, newOrderType, newTriggerPrice, newTriggerCondition, isSpot, auctionDuration, auctionStartPrice, auctionEndPrice, }) {
|
|
1920
1887
|
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
1921
1888
|
throw new Error(`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`);
|
|
1922
1889
|
}
|
|
@@ -1925,23 +1892,37 @@ class DriftClient {
|
|
|
1925
1892
|
throw new Error(`No open order with user order id ${userOrderId.toString()}`);
|
|
1926
1893
|
}
|
|
1927
1894
|
const cancelOrderIx = await this.getCancelOrderByUserIdIx(userOrderId);
|
|
1895
|
+
const orderTypeHasTrigger = newOrderType
|
|
1896
|
+
? types_1.isOneOfVariant(newOrderType, ['triggerlimit', 'triggerMarket'])
|
|
1897
|
+
: types_1.isOneOfVariant(openOrder.orderType, ['triggerLimit', 'triggerMarket']);
|
|
1898
|
+
const orderTypeHasLimitPrice = newOrderType
|
|
1899
|
+
? types_1.isOneOfVariant(newOrderType, ['triggerLimit', 'limit'])
|
|
1900
|
+
: types_1.isOneOfVariant(openOrder.orderType, ['triggerLimit', 'limit']);
|
|
1928
1901
|
const newOrderParams = {
|
|
1929
1902
|
orderType: newOrderType || openOrder.orderType,
|
|
1930
1903
|
marketType: openOrder.marketType,
|
|
1931
1904
|
direction: openOrder.direction,
|
|
1932
1905
|
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
1933
|
-
price:
|
|
1906
|
+
price: orderTypeHasLimitPrice
|
|
1907
|
+
? newLimitPrice || openOrder.price
|
|
1908
|
+
: undefined,
|
|
1934
1909
|
marketIndex: openOrder.marketIndex,
|
|
1935
1910
|
reduceOnly: openOrder.reduceOnly,
|
|
1936
|
-
postOnly: openOrder.postOnly
|
|
1911
|
+
postOnly: openOrder.postOnly
|
|
1912
|
+
? types_1.PostOnlyParams.MUST_POST_ONLY
|
|
1913
|
+
: types_1.PostOnlyParams.NONE,
|
|
1937
1914
|
immediateOrCancel: openOrder.immediateOrCancel,
|
|
1938
|
-
triggerPrice:
|
|
1939
|
-
|
|
1915
|
+
triggerPrice: orderTypeHasTrigger
|
|
1916
|
+
? newTriggerPrice || openOrder.triggerPrice
|
|
1917
|
+
: undefined,
|
|
1918
|
+
triggerCondition: orderTypeHasTrigger
|
|
1919
|
+
? newTriggerCondition || openOrder.triggerCondition
|
|
1920
|
+
: undefined,
|
|
1940
1921
|
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
1941
|
-
auctionDuration: openOrder.auctionDuration,
|
|
1922
|
+
auctionDuration: auctionDuration || openOrder.auctionDuration,
|
|
1942
1923
|
maxTs: openOrder.maxTs,
|
|
1943
|
-
auctionStartPrice: openOrder.auctionStartPrice,
|
|
1944
|
-
auctionEndPrice: openOrder.auctionEndPrice,
|
|
1924
|
+
auctionStartPrice: auctionStartPrice || openOrder.auctionStartPrice,
|
|
1925
|
+
auctionEndPrice: auctionEndPrice || openOrder.auctionEndPrice,
|
|
1945
1926
|
userOrderId: openOrder.userOrderId,
|
|
1946
1927
|
};
|
|
1947
1928
|
const placeOrderIx = isSpot
|
package/lib/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.17.0-beta.0",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -4655,7 +4655,9 @@
|
|
|
4655
4655
|
},
|
|
4656
4656
|
{
|
|
4657
4657
|
"name": "postOnly",
|
|
4658
|
-
"type":
|
|
4658
|
+
"type": {
|
|
4659
|
+
"defined": "PostOnlyParam"
|
|
4660
|
+
}
|
|
4659
4661
|
},
|
|
4660
4662
|
{
|
|
4661
4663
|
"name": "immediateOrCancel",
|
|
@@ -5862,6 +5864,23 @@
|
|
|
5862
5864
|
]
|
|
5863
5865
|
}
|
|
5864
5866
|
},
|
|
5867
|
+
{
|
|
5868
|
+
"name": "PostOnlyParam",
|
|
5869
|
+
"type": {
|
|
5870
|
+
"kind": "enum",
|
|
5871
|
+
"variants": [
|
|
5872
|
+
{
|
|
5873
|
+
"name": "None"
|
|
5874
|
+
},
|
|
5875
|
+
{
|
|
5876
|
+
"name": "MustPostOnly"
|
|
5877
|
+
},
|
|
5878
|
+
{
|
|
5879
|
+
"name": "TryPostOnly"
|
|
5880
|
+
}
|
|
5881
|
+
]
|
|
5882
|
+
}
|
|
5883
|
+
},
|
|
5865
5884
|
{
|
|
5866
5885
|
"name": "TwapPeriod",
|
|
5867
5886
|
"type": {
|
|
@@ -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/lib/types.d.ts
CHANGED
|
@@ -886,7 +886,7 @@ export declare type OrderParams = {
|
|
|
886
886
|
price: BN;
|
|
887
887
|
marketIndex: number;
|
|
888
888
|
reduceOnly: boolean;
|
|
889
|
-
postOnly:
|
|
889
|
+
postOnly: PostOnlyParams;
|
|
890
890
|
immediateOrCancel: boolean;
|
|
891
891
|
triggerPrice: BN | null;
|
|
892
892
|
triggerCondition: OrderTriggerCondition;
|
|
@@ -897,6 +897,17 @@ export declare type OrderParams = {
|
|
|
897
897
|
auctionStartPrice: BN | null;
|
|
898
898
|
auctionEndPrice: BN | null;
|
|
899
899
|
};
|
|
900
|
+
export declare class PostOnlyParams {
|
|
901
|
+
static readonly NONE: {
|
|
902
|
+
none: {};
|
|
903
|
+
};
|
|
904
|
+
static readonly MUST_POST_ONLY: {
|
|
905
|
+
mustPostOnly: {};
|
|
906
|
+
};
|
|
907
|
+
static readonly TRY_POST_ONLY: {
|
|
908
|
+
tryPostOnly: {};
|
|
909
|
+
};
|
|
910
|
+
}
|
|
900
911
|
export declare type NecessaryOrderParams = {
|
|
901
912
|
orderType: OrderType;
|
|
902
913
|
marketIndex: number;
|
package/lib/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultOrderParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.UserStatus = exports.MarketStatus = exports.ExchangeStatus = void 0;
|
|
3
|
+
exports.DefaultOrderParams = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.UserStatus = exports.MarketStatus = exports.ExchangeStatus = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
5
|
// # Utility Types / Enums / Constants
|
|
6
6
|
var ExchangeStatus;
|
|
@@ -232,6 +232,12 @@ LiquidationType.BORROW_BANKRUPTCY = {
|
|
|
232
232
|
LiquidationType.LIQUIDATE_SPOT = {
|
|
233
233
|
liquidateSpot: {},
|
|
234
234
|
};
|
|
235
|
+
class PostOnlyParams {
|
|
236
|
+
}
|
|
237
|
+
exports.PostOnlyParams = PostOnlyParams;
|
|
238
|
+
PostOnlyParams.NONE = { none: {} };
|
|
239
|
+
PostOnlyParams.MUST_POST_ONLY = { mustPostOnly: {} }; // Tx fails if order can't be post only
|
|
240
|
+
PostOnlyParams.TRY_POST_ONLY = { tryPostOnly: {} }; // Tx succeeds and order not placed if can't be post only
|
|
235
241
|
exports.DefaultOrderParams = {
|
|
236
242
|
orderType: OrderType.MARKET,
|
|
237
243
|
marketType: MarketType.PERP,
|
|
@@ -241,7 +247,7 @@ exports.DefaultOrderParams = {
|
|
|
241
247
|
price: _1.ZERO,
|
|
242
248
|
marketIndex: 0,
|
|
243
249
|
reduceOnly: false,
|
|
244
|
-
postOnly:
|
|
250
|
+
postOnly: PostOnlyParams.NONE,
|
|
245
251
|
immediateOrCancel: false,
|
|
246
252
|
triggerPrice: null,
|
|
247
253
|
triggerCondition: OrderTriggerCondition.ABOVE,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.17.0-beta.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -53,10 +53,11 @@
|
|
|
53
53
|
"eslint-plugin-prettier": "^3.4.0",
|
|
54
54
|
"mocha": "^10.0.0",
|
|
55
55
|
"prettier": "^2.4.1",
|
|
56
|
-
"ts-node": "^10.8.0"
|
|
56
|
+
"ts-node": "^10.8.0",
|
|
57
|
+
"typescript": "^4.9.5"
|
|
57
58
|
},
|
|
58
59
|
"description": "SDK for Drift Protocol",
|
|
59
60
|
"engines": {
|
|
60
61
|
"node": ">=12"
|
|
61
62
|
}
|
|
62
|
-
}
|
|
63
|
+
}
|
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/driftClient.ts
CHANGED
|
@@ -25,6 +25,9 @@ import {
|
|
|
25
25
|
TxParams,
|
|
26
26
|
SerumV3FulfillmentConfigAccount,
|
|
27
27
|
isVariant,
|
|
28
|
+
OrderTriggerCondition,
|
|
29
|
+
isOneOfVariant,
|
|
30
|
+
PostOnlyParams,
|
|
28
31
|
} from './types';
|
|
29
32
|
import * as anchor from '@project-serum/anchor';
|
|
30
33
|
import driftIDL from './idl/drift.json';
|
|
@@ -42,6 +45,7 @@ import {
|
|
|
42
45
|
Signer,
|
|
43
46
|
SystemProgram,
|
|
44
47
|
ComputeBudgetProgram,
|
|
48
|
+
AddressLookupTableAccount,
|
|
45
49
|
} from '@solana/web3.js';
|
|
46
50
|
|
|
47
51
|
import { TokenFaucet } from './tokenFaucet';
|
|
@@ -77,7 +81,7 @@ import { WebSocketDriftClientAccountSubscriber } from './accounts/webSocketDrift
|
|
|
77
81
|
import { RetryTxSender } from './tx/retryTxSender';
|
|
78
82
|
import { User } from './user';
|
|
79
83
|
import { UserSubscriptionConfig } from './userConfig';
|
|
80
|
-
import { getMarketsAndOraclesForSubscription } from './config';
|
|
84
|
+
import { configs, getMarketsAndOraclesForSubscription } from './config';
|
|
81
85
|
import { WRAPPED_SOL_MINT } from './constants/spotMarkets';
|
|
82
86
|
import { UserStats } from './userStats';
|
|
83
87
|
import { isSpotPositionAvailable } from './math/spotPosition';
|
|
@@ -112,6 +116,7 @@ export class DriftClient {
|
|
|
112
116
|
perpMarketLastSlotCache = new Map<number, number>();
|
|
113
117
|
spotMarketLastSlotCache = new Map<number, number>();
|
|
114
118
|
authority: PublicKey;
|
|
119
|
+
marketLookupTable: PublicKey;
|
|
115
120
|
|
|
116
121
|
public get isSubscribed() {
|
|
117
122
|
return this._isSubscribed && this.accountSubscriber.isSubscribed;
|
|
@@ -178,6 +183,13 @@ export class DriftClient {
|
|
|
178
183
|
oracleInfos = oracleInfos ? oracleInfos : envOracleInfos;
|
|
179
184
|
}
|
|
180
185
|
|
|
186
|
+
this.marketLookupTable = config.marketLookupTable;
|
|
187
|
+
if (config.env && !this.marketLookupTable) {
|
|
188
|
+
this.marketLookupTable = new PublicKey(
|
|
189
|
+
configs[config.env].MARKET_LOOKUP_TABLE
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
181
193
|
if (config.accountSubscription?.type === 'polling') {
|
|
182
194
|
this.accountSubscriber = new PollingDriftClientAccountSubscriber(
|
|
183
195
|
this.program,
|
|
@@ -387,6 +399,15 @@ export class DriftClient {
|
|
|
387
399
|
)) as SerumV3FulfillmentConfigAccount;
|
|
388
400
|
}
|
|
389
401
|
|
|
402
|
+
public async fetchMarketLookupTableAccount(): Promise<AddressLookupTableAccount> {
|
|
403
|
+
if (!this.marketLookupTable) {
|
|
404
|
+
throw Error('Market lookup table address not set');
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return (await this.connection.getAddressLookupTable(this.marketLookupTable))
|
|
408
|
+
.value;
|
|
409
|
+
}
|
|
410
|
+
|
|
390
411
|
/**
|
|
391
412
|
* Update the wallet to use for drift transactions and linked user account
|
|
392
413
|
* @param newWallet
|
|
@@ -3031,51 +3052,35 @@ export class DriftClient {
|
|
|
3031
3052
|
newLimitPrice?: BN,
|
|
3032
3053
|
newOraclePriceOffset?: number
|
|
3033
3054
|
): Promise<TransactionSignature> {
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
if (!openOrder) {
|
|
3042
|
-
throw new Error(`No open order with id ${orderId.toString()}`);
|
|
3043
|
-
}
|
|
3044
|
-
const cancelOrderIx = await this.getCancelOrderIx(orderId);
|
|
3045
|
-
|
|
3046
|
-
const newOrderParams: OptionalOrderParams = {
|
|
3047
|
-
orderType: openOrder.orderType,
|
|
3048
|
-
marketType: openOrder.marketType,
|
|
3049
|
-
direction: openOrder.direction,
|
|
3050
|
-
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
3051
|
-
price: newLimitPrice || openOrder.price,
|
|
3052
|
-
marketIndex: openOrder.marketIndex,
|
|
3053
|
-
reduceOnly: openOrder.reduceOnly,
|
|
3054
|
-
postOnly: openOrder.postOnly,
|
|
3055
|
-
immediateOrCancel: openOrder.immediateOrCancel,
|
|
3056
|
-
triggerPrice: openOrder.triggerPrice,
|
|
3057
|
-
triggerCondition: openOrder.triggerCondition,
|
|
3058
|
-
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
3059
|
-
auctionDuration: openOrder.auctionDuration,
|
|
3060
|
-
maxTs: openOrder.maxTs,
|
|
3061
|
-
auctionStartPrice: openOrder.auctionStartPrice,
|
|
3062
|
-
auctionEndPrice: openOrder.auctionEndPrice,
|
|
3063
|
-
userOrderId: openOrder.userOrderId,
|
|
3064
|
-
};
|
|
3065
|
-
const placeOrderIx = await this.getPlacePerpOrderIx(newOrderParams);
|
|
3055
|
+
return this.modifyOrder({
|
|
3056
|
+
orderId,
|
|
3057
|
+
newBaseAmount,
|
|
3058
|
+
newLimitPrice,
|
|
3059
|
+
newOraclePriceOffset,
|
|
3060
|
+
});
|
|
3061
|
+
}
|
|
3066
3062
|
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3063
|
+
/**
|
|
3064
|
+
* Modifies an open order by closing it and replacing it with a new order.
|
|
3065
|
+
* @deprecated use modifyOrderByUserOrderId instead
|
|
3066
|
+
* @param userOrderId: The open order to modify
|
|
3067
|
+
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3068
|
+
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3069
|
+
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3070
|
+
* @returns
|
|
3071
|
+
*/
|
|
3072
|
+
public async modifyPerpOrderByUserOrderId(
|
|
3073
|
+
userOrderId: number,
|
|
3074
|
+
newBaseAmount?: BN,
|
|
3075
|
+
newLimitPrice?: BN,
|
|
3076
|
+
newOraclePriceOffset?: number
|
|
3077
|
+
): Promise<TransactionSignature> {
|
|
3078
|
+
return this.modifyOrderByUserOrderId({
|
|
3079
|
+
userOrderId,
|
|
3080
|
+
newBaseAmount,
|
|
3081
|
+
newLimitPrice,
|
|
3082
|
+
newOraclePriceOffset,
|
|
3083
|
+
});
|
|
3079
3084
|
}
|
|
3080
3085
|
|
|
3081
3086
|
/**
|
|
@@ -3087,6 +3092,9 @@ export class DriftClient {
|
|
|
3087
3092
|
* @param newOrderType: Optional - New order type for the order.
|
|
3088
3093
|
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
3089
3094
|
* @param isSpot: Optional - Set to true if the order is a spot order
|
|
3095
|
+
* @param auctionDuration: Only required if order type changed to market from something else
|
|
3096
|
+
* @param auctionStartPrice: Only required if order type changed to market from something else
|
|
3097
|
+
* @param auctionEndPrice: Only required if order type changed to market from something else
|
|
3090
3098
|
* @returns
|
|
3091
3099
|
*/
|
|
3092
3100
|
public async modifyOrder({
|
|
@@ -3096,7 +3104,11 @@ export class DriftClient {
|
|
|
3096
3104
|
newOraclePriceOffset,
|
|
3097
3105
|
newOrderType,
|
|
3098
3106
|
newTriggerPrice,
|
|
3107
|
+
newTriggerCondition,
|
|
3099
3108
|
isSpot,
|
|
3109
|
+
auctionDuration,
|
|
3110
|
+
auctionStartPrice,
|
|
3111
|
+
auctionEndPrice,
|
|
3100
3112
|
}: {
|
|
3101
3113
|
orderId: number;
|
|
3102
3114
|
newBaseAmount?: BN;
|
|
@@ -3104,7 +3116,11 @@ export class DriftClient {
|
|
|
3104
3116
|
newOraclePriceOffset?: number;
|
|
3105
3117
|
newOrderType?: OrderType;
|
|
3106
3118
|
newTriggerPrice?: BN;
|
|
3119
|
+
newTriggerCondition?: OrderTriggerCondition;
|
|
3107
3120
|
isSpot?: boolean;
|
|
3121
|
+
auctionDuration?: number;
|
|
3122
|
+
auctionStartPrice?: BN;
|
|
3123
|
+
auctionEndPrice?: BN;
|
|
3108
3124
|
}): Promise<TransactionSignature> {
|
|
3109
3125
|
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
3110
3126
|
throw new Error(
|
|
@@ -3118,23 +3134,38 @@ export class DriftClient {
|
|
|
3118
3134
|
}
|
|
3119
3135
|
const cancelOrderIx = await this.getCancelOrderIx(orderId);
|
|
3120
3136
|
|
|
3137
|
+
const orderTypeHasTrigger = newOrderType
|
|
3138
|
+
? isOneOfVariant(newOrderType, ['triggerlimit', 'triggerMarket'])
|
|
3139
|
+
: isOneOfVariant(openOrder.orderType, ['triggerLimit', 'triggerMarket']);
|
|
3140
|
+
const orderTypeHasLimitPrice = newOrderType
|
|
3141
|
+
? isOneOfVariant(newOrderType, ['triggerLimit', 'limit'])
|
|
3142
|
+
: isOneOfVariant(openOrder.orderType, ['triggerLimit', 'limit']);
|
|
3143
|
+
|
|
3121
3144
|
const newOrderParams: OptionalOrderParams = {
|
|
3122
3145
|
orderType: newOrderType || openOrder.orderType,
|
|
3123
3146
|
marketType: openOrder.marketType,
|
|
3124
3147
|
direction: openOrder.direction,
|
|
3125
3148
|
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
3126
|
-
price:
|
|
3149
|
+
price: orderTypeHasLimitPrice
|
|
3150
|
+
? newLimitPrice || openOrder.price
|
|
3151
|
+
: undefined,
|
|
3127
3152
|
marketIndex: openOrder.marketIndex,
|
|
3128
3153
|
reduceOnly: openOrder.reduceOnly,
|
|
3129
|
-
postOnly: openOrder.postOnly
|
|
3154
|
+
postOnly: openOrder.postOnly
|
|
3155
|
+
? PostOnlyParams.MUST_POST_ONLY
|
|
3156
|
+
: PostOnlyParams.NONE,
|
|
3130
3157
|
immediateOrCancel: openOrder.immediateOrCancel,
|
|
3131
|
-
triggerPrice:
|
|
3132
|
-
|
|
3158
|
+
triggerPrice: orderTypeHasTrigger
|
|
3159
|
+
? newTriggerPrice || openOrder.triggerPrice
|
|
3160
|
+
: undefined,
|
|
3161
|
+
triggerCondition: orderTypeHasTrigger
|
|
3162
|
+
? newTriggerCondition || openOrder.triggerCondition
|
|
3163
|
+
: undefined,
|
|
3133
3164
|
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
3134
|
-
auctionDuration: openOrder.auctionDuration,
|
|
3165
|
+
auctionDuration: auctionDuration || openOrder.auctionDuration,
|
|
3135
3166
|
maxTs: openOrder.maxTs,
|
|
3136
|
-
auctionStartPrice: openOrder.auctionStartPrice,
|
|
3137
|
-
auctionEndPrice: openOrder.auctionEndPrice,
|
|
3167
|
+
auctionStartPrice: auctionStartPrice || openOrder.auctionStartPrice,
|
|
3168
|
+
auctionEndPrice: auctionEndPrice || openOrder.auctionEndPrice,
|
|
3138
3169
|
userOrderId: openOrder.userOrderId,
|
|
3139
3170
|
};
|
|
3140
3171
|
const placeOrderIx = isSpot
|
|
@@ -3162,70 +3193,6 @@ export class DriftClient {
|
|
|
3162
3193
|
return txSig;
|
|
3163
3194
|
}
|
|
3164
3195
|
|
|
3165
|
-
/**
|
|
3166
|
-
* Modifies an open order by closing it and replacing it with a new order.
|
|
3167
|
-
* @deprecated use modifyOrderByUserOrderId instead
|
|
3168
|
-
* @param userOrderId: The open order to modify
|
|
3169
|
-
* @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3170
|
-
* @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3171
|
-
* @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
|
|
3172
|
-
* @returns
|
|
3173
|
-
*/
|
|
3174
|
-
public async modifyPerpOrderByUserOrderId(
|
|
3175
|
-
userOrderId: number,
|
|
3176
|
-
newBaseAmount?: BN,
|
|
3177
|
-
newLimitPrice?: BN,
|
|
3178
|
-
newOraclePriceOffset?: number
|
|
3179
|
-
): Promise<TransactionSignature> {
|
|
3180
|
-
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
3181
|
-
throw new Error(
|
|
3182
|
-
`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`
|
|
3183
|
-
);
|
|
3184
|
-
}
|
|
3185
|
-
|
|
3186
|
-
const openOrder = this.getUser().getOrderByUserOrderId(userOrderId);
|
|
3187
|
-
if (!openOrder) {
|
|
3188
|
-
throw new Error(
|
|
3189
|
-
`No open order with user order id ${userOrderId.toString()}`
|
|
3190
|
-
);
|
|
3191
|
-
}
|
|
3192
|
-
const cancelOrderIx = await this.getCancelOrderByUserIdIx(userOrderId);
|
|
3193
|
-
|
|
3194
|
-
const newOrderParams: OptionalOrderParams = {
|
|
3195
|
-
orderType: openOrder.orderType,
|
|
3196
|
-
marketType: openOrder.marketType,
|
|
3197
|
-
direction: openOrder.direction,
|
|
3198
|
-
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
3199
|
-
price: newLimitPrice || openOrder.price,
|
|
3200
|
-
marketIndex: openOrder.marketIndex,
|
|
3201
|
-
reduceOnly: openOrder.reduceOnly,
|
|
3202
|
-
postOnly: openOrder.postOnly,
|
|
3203
|
-
immediateOrCancel: openOrder.immediateOrCancel,
|
|
3204
|
-
triggerPrice: openOrder.triggerPrice,
|
|
3205
|
-
triggerCondition: openOrder.triggerCondition,
|
|
3206
|
-
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
3207
|
-
auctionDuration: openOrder.auctionDuration,
|
|
3208
|
-
maxTs: openOrder.maxTs,
|
|
3209
|
-
auctionStartPrice: openOrder.auctionStartPrice,
|
|
3210
|
-
auctionEndPrice: openOrder.auctionEndPrice,
|
|
3211
|
-
userOrderId: openOrder.userOrderId,
|
|
3212
|
-
};
|
|
3213
|
-
const placeOrderIx = await this.getPlacePerpOrderIx(newOrderParams);
|
|
3214
|
-
|
|
3215
|
-
const tx = new Transaction();
|
|
3216
|
-
tx.add(
|
|
3217
|
-
ComputeBudgetProgram.requestUnits({
|
|
3218
|
-
units: 1_000_000,
|
|
3219
|
-
additionalFee: 0,
|
|
3220
|
-
})
|
|
3221
|
-
);
|
|
3222
|
-
tx.add(cancelOrderIx);
|
|
3223
|
-
tx.add(placeOrderIx);
|
|
3224
|
-
const { txSig, slot } = await this.sendTransaction(tx, [], this.opts);
|
|
3225
|
-
this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
|
|
3226
|
-
return txSig;
|
|
3227
|
-
}
|
|
3228
|
-
|
|
3229
3196
|
/**
|
|
3230
3197
|
* Modifies an open order by closing it and replacing it with a new order.
|
|
3231
3198
|
* @param userOrderId: The open order to modify
|
|
@@ -3235,6 +3202,9 @@ export class DriftClient {
|
|
|
3235
3202
|
* @param newOrderType: Optional - New order type for the order.
|
|
3236
3203
|
* @param newTriggerPrice: Optional - Thew new trigger price for the order.
|
|
3237
3204
|
* @param isSpot: Set to true if the order is a spot order
|
|
3205
|
+
* @param auctionDuration: Only required if order type changed to market from something else
|
|
3206
|
+
* @param auctionStartPrice: Only required if order type changed to market from something else
|
|
3207
|
+
* @param auctionEndPrice: Only required if order type changed to market from something else
|
|
3238
3208
|
* @returns
|
|
3239
3209
|
*/
|
|
3240
3210
|
public async modifyOrderByUserOrderId({
|
|
@@ -3244,7 +3214,11 @@ export class DriftClient {
|
|
|
3244
3214
|
newOraclePriceOffset,
|
|
3245
3215
|
newOrderType,
|
|
3246
3216
|
newTriggerPrice,
|
|
3217
|
+
newTriggerCondition,
|
|
3247
3218
|
isSpot,
|
|
3219
|
+
auctionDuration,
|
|
3220
|
+
auctionStartPrice,
|
|
3221
|
+
auctionEndPrice,
|
|
3248
3222
|
}: {
|
|
3249
3223
|
userOrderId: number;
|
|
3250
3224
|
newBaseAmount?: BN;
|
|
@@ -3252,7 +3226,11 @@ export class DriftClient {
|
|
|
3252
3226
|
newOraclePriceOffset?: number;
|
|
3253
3227
|
newOrderType?: OrderType;
|
|
3254
3228
|
newTriggerPrice?: BN;
|
|
3229
|
+
newTriggerCondition?: OrderTriggerCondition;
|
|
3255
3230
|
isSpot?: boolean;
|
|
3231
|
+
auctionDuration?: number;
|
|
3232
|
+
auctionStartPrice?: BN;
|
|
3233
|
+
auctionEndPrice?: BN;
|
|
3256
3234
|
}): Promise<TransactionSignature> {
|
|
3257
3235
|
if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
|
|
3258
3236
|
throw new Error(
|
|
@@ -3268,23 +3246,38 @@ export class DriftClient {
|
|
|
3268
3246
|
}
|
|
3269
3247
|
const cancelOrderIx = await this.getCancelOrderByUserIdIx(userOrderId);
|
|
3270
3248
|
|
|
3249
|
+
const orderTypeHasTrigger = newOrderType
|
|
3250
|
+
? isOneOfVariant(newOrderType, ['triggerlimit', 'triggerMarket'])
|
|
3251
|
+
: isOneOfVariant(openOrder.orderType, ['triggerLimit', 'triggerMarket']);
|
|
3252
|
+
const orderTypeHasLimitPrice = newOrderType
|
|
3253
|
+
? isOneOfVariant(newOrderType, ['triggerLimit', 'limit'])
|
|
3254
|
+
: isOneOfVariant(openOrder.orderType, ['triggerLimit', 'limit']);
|
|
3255
|
+
|
|
3271
3256
|
const newOrderParams: OptionalOrderParams = {
|
|
3272
3257
|
orderType: newOrderType || openOrder.orderType,
|
|
3273
3258
|
marketType: openOrder.marketType,
|
|
3274
3259
|
direction: openOrder.direction,
|
|
3275
3260
|
baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
|
|
3276
|
-
price:
|
|
3261
|
+
price: orderTypeHasLimitPrice
|
|
3262
|
+
? newLimitPrice || openOrder.price
|
|
3263
|
+
: undefined,
|
|
3277
3264
|
marketIndex: openOrder.marketIndex,
|
|
3278
3265
|
reduceOnly: openOrder.reduceOnly,
|
|
3279
|
-
postOnly: openOrder.postOnly
|
|
3266
|
+
postOnly: openOrder.postOnly
|
|
3267
|
+
? PostOnlyParams.MUST_POST_ONLY
|
|
3268
|
+
: PostOnlyParams.NONE,
|
|
3280
3269
|
immediateOrCancel: openOrder.immediateOrCancel,
|
|
3281
|
-
triggerPrice:
|
|
3282
|
-
|
|
3270
|
+
triggerPrice: orderTypeHasTrigger
|
|
3271
|
+
? newTriggerPrice || openOrder.triggerPrice
|
|
3272
|
+
: undefined,
|
|
3273
|
+
triggerCondition: orderTypeHasTrigger
|
|
3274
|
+
? newTriggerCondition || openOrder.triggerCondition
|
|
3275
|
+
: undefined,
|
|
3283
3276
|
oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
|
|
3284
|
-
auctionDuration: openOrder.auctionDuration,
|
|
3277
|
+
auctionDuration: auctionDuration || openOrder.auctionDuration,
|
|
3285
3278
|
maxTs: openOrder.maxTs,
|
|
3286
|
-
auctionStartPrice: openOrder.auctionStartPrice,
|
|
3287
|
-
auctionEndPrice: openOrder.auctionEndPrice,
|
|
3279
|
+
auctionStartPrice: auctionStartPrice || openOrder.auctionStartPrice,
|
|
3280
|
+
auctionEndPrice: auctionEndPrice || openOrder.auctionEndPrice,
|
|
3288
3281
|
userOrderId: openOrder.userOrderId,
|
|
3289
3282
|
};
|
|
3290
3283
|
const placeOrderIx = isSpot
|
package/src/driftClientConfig.ts
CHANGED
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.17.0-beta.0",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -4655,7 +4655,9 @@
|
|
|
4655
4655
|
},
|
|
4656
4656
|
{
|
|
4657
4657
|
"name": "postOnly",
|
|
4658
|
-
"type":
|
|
4658
|
+
"type": {
|
|
4659
|
+
"defined": "PostOnlyParam"
|
|
4660
|
+
}
|
|
4659
4661
|
},
|
|
4660
4662
|
{
|
|
4661
4663
|
"name": "immediateOrCancel",
|
|
@@ -5862,6 +5864,23 @@
|
|
|
5862
5864
|
]
|
|
5863
5865
|
}
|
|
5864
5866
|
},
|
|
5867
|
+
{
|
|
5868
|
+
"name": "PostOnlyParam",
|
|
5869
|
+
"type": {
|
|
5870
|
+
"kind": "enum",
|
|
5871
|
+
"variants": [
|
|
5872
|
+
{
|
|
5873
|
+
"name": "None"
|
|
5874
|
+
},
|
|
5875
|
+
{
|
|
5876
|
+
"name": "MustPostOnly"
|
|
5877
|
+
},
|
|
5878
|
+
{
|
|
5879
|
+
"name": "TryPostOnly"
|
|
5880
|
+
}
|
|
5881
|
+
]
|
|
5882
|
+
}
|
|
5883
|
+
},
|
|
5865
5884
|
{
|
|
5866
5885
|
"name": "TwapPeriod",
|
|
5867
5886
|
"type": {
|
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/src/types.ts
CHANGED
|
@@ -846,7 +846,7 @@ export type OrderParams = {
|
|
|
846
846
|
price: BN;
|
|
847
847
|
marketIndex: number;
|
|
848
848
|
reduceOnly: boolean;
|
|
849
|
-
postOnly:
|
|
849
|
+
postOnly: PostOnlyParams;
|
|
850
850
|
immediateOrCancel: boolean;
|
|
851
851
|
triggerPrice: BN | null;
|
|
852
852
|
triggerCondition: OrderTriggerCondition;
|
|
@@ -858,6 +858,12 @@ export type OrderParams = {
|
|
|
858
858
|
auctionEndPrice: BN | null;
|
|
859
859
|
};
|
|
860
860
|
|
|
861
|
+
export class PostOnlyParams {
|
|
862
|
+
static readonly NONE = { none: {} };
|
|
863
|
+
static readonly MUST_POST_ONLY = { mustPostOnly: {} }; // Tx fails if order can't be post only
|
|
864
|
+
static readonly TRY_POST_ONLY = { tryPostOnly: {} }; // Tx succeeds and order not placed if can't be post only
|
|
865
|
+
}
|
|
866
|
+
|
|
861
867
|
export type NecessaryOrderParams = {
|
|
862
868
|
orderType: OrderType;
|
|
863
869
|
marketIndex: number;
|
|
@@ -878,7 +884,7 @@ export const DefaultOrderParams: OrderParams = {
|
|
|
878
884
|
price: ZERO,
|
|
879
885
|
marketIndex: 0,
|
|
880
886
|
reduceOnly: false,
|
|
881
|
-
postOnly:
|
|
887
|
+
postOnly: PostOnlyParams.NONE,
|
|
882
888
|
immediateOrCancel: false,
|
|
883
889
|
triggerPrice: null,
|
|
884
890
|
triggerCondition: OrderTriggerCondition.ABOVE,
|
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;
|