@drift-labs/sdk 2.30.0-beta.0 → 2.30.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/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
- package/lib/accounts/pollingTokenAccountSubscriber.js +5 -2
- package/lib/accounts/types.d.ts +3 -3
- package/lib/constants/spotMarkets.js +10 -0
- package/lib/dlob/DLOB.d.ts +20 -1
- package/lib/dlob/DLOB.js +39 -0
- package/lib/driftClient.d.ts +51 -2
- package/lib/driftClient.js +162 -13
- package/lib/events/types.d.ts +3 -2
- package/lib/events/types.js +1 -0
- package/lib/examples/makeTradeExample.js +1 -1
- package/lib/idl/drift.json +279 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/jupiter/jupiterClient.d.ts +86 -0
- package/lib/jupiter/jupiterClient.js +109 -0
- package/lib/math/spotBalance.d.ts +41 -0
- package/lib/math/spotBalance.js +41 -0
- package/lib/token/index.d.ts +3 -2
- package/lib/token/index.js +9 -32
- package/lib/tokenFaucet.d.ts +3 -3
- package/lib/tokenFaucet.js +4 -9
- package/lib/tx/retryTxSender.js +3 -0
- package/lib/types.d.ts +29 -1
- package/lib/types.js +6 -1
- package/lib/wallet.d.ts +5 -3
- package/lib/wallet.js +19 -7
- package/package.json +2 -2
- package/src/accounts/pollingTokenAccountSubscriber.ts +8 -5
- package/src/accounts/types.ts +3 -3
- package/src/assert/assert.js +9 -0
- package/src/constants/spotMarkets.ts +11 -0
- package/src/dlob/DLOB.ts +75 -0
- package/src/driftClient.ts +288 -37
- package/src/events/types.ts +5 -1
- package/src/examples/makeTradeExample.ts +2 -4
- package/src/idl/drift.json +279 -2
- package/src/index.ts +1 -0
- package/src/jupiter/jupiterClient.ts +214 -0
- package/src/math/spotBalance.ts +41 -0
- package/src/token/index.js +38 -0
- package/src/token/index.ts +12 -36
- package/src/tokenFaucet.ts +15 -34
- package/src/tx/retryTxSender.ts +4 -0
- package/src/types.ts +32 -1
- package/src/util/computeUnits.js +27 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/src/wallet.ts +34 -12
- package/tests/dlob/helpers.ts +9 -0
- package/tests/dlob/test.ts +218 -40
- package/dlob_read.ts +0 -155
- package/lib/util/getTokenAddress.d.ts +0 -2
- package/lib/util/getTokenAddress.js +0 -9
- package/src/util/getTokenAddress.ts +0 -18
|
@@ -5,7 +5,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
|
|
|
5
5
|
import { EventEmitter } from 'events';
|
|
6
6
|
import { PublicKey } from '@solana/web3.js';
|
|
7
7
|
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
8
|
-
import {
|
|
8
|
+
import { Account } from '@solana/spl-token';
|
|
9
9
|
export declare class PollingTokenAccountSubscriber implements TokenAccountSubscriber {
|
|
10
10
|
isSubscribed: boolean;
|
|
11
11
|
program: Program;
|
|
@@ -14,13 +14,13 @@ export declare class PollingTokenAccountSubscriber implements TokenAccountSubscr
|
|
|
14
14
|
accountLoader: BulkAccountLoader;
|
|
15
15
|
callbackId?: string;
|
|
16
16
|
errorCallbackId?: string;
|
|
17
|
-
tokenAccountAndSlot?: DataAndSlot<
|
|
17
|
+
tokenAccountAndSlot?: DataAndSlot<Account>;
|
|
18
18
|
constructor(publicKey: PublicKey, accountLoader: BulkAccountLoader);
|
|
19
19
|
subscribe(): Promise<boolean>;
|
|
20
20
|
addToAccountLoader(): Promise<void>;
|
|
21
21
|
fetch(): Promise<void>;
|
|
22
22
|
unsubscribe(): Promise<void>;
|
|
23
23
|
assertIsSubscribed(): void;
|
|
24
|
-
getTokenAccountAndSlot(): DataAndSlot<
|
|
24
|
+
getTokenAccountAndSlot(): DataAndSlot<Account>;
|
|
25
25
|
didSubscriptionSucceed(): boolean;
|
|
26
26
|
}
|
|
@@ -34,7 +34,7 @@ class PollingTokenAccountSubscriber {
|
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
this.callbackId = await this.accountLoader.addAccount(this.publicKey, (buffer, slot) => {
|
|
37
|
-
const tokenAccount = (0, token_1.parseTokenAccount)(buffer);
|
|
37
|
+
const tokenAccount = (0, token_1.parseTokenAccount)(buffer, this.publicKey);
|
|
38
38
|
this.tokenAccountAndSlot = { data: tokenAccount, slot };
|
|
39
39
|
// @ts-ignore
|
|
40
40
|
this.eventEmitter.emit('tokenAccountUpdate', tokenAccount);
|
|
@@ -47,7 +47,10 @@ class PollingTokenAccountSubscriber {
|
|
|
47
47
|
async fetch() {
|
|
48
48
|
await this.accountLoader.load();
|
|
49
49
|
const { buffer, slot } = this.accountLoader.getBufferAndSlot(this.publicKey);
|
|
50
|
-
this.tokenAccountAndSlot = {
|
|
50
|
+
this.tokenAccountAndSlot = {
|
|
51
|
+
data: (0, token_1.parseTokenAccount)(buffer, this.publicKey),
|
|
52
|
+
slot,
|
|
53
|
+
};
|
|
51
54
|
}
|
|
52
55
|
async unsubscribe() {
|
|
53
56
|
if (!this.isSubscribed) {
|
package/lib/accounts/types.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { SpotMarketAccount, PerpMarketAccount, OracleSource, StateAccount, UserA
|
|
|
4
4
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
5
|
import { EventEmitter } from 'events';
|
|
6
6
|
import { PublicKey } from '@solana/web3.js';
|
|
7
|
-
import {
|
|
7
|
+
import { Account } from '@solana/spl-token';
|
|
8
8
|
import { OracleInfo, OraclePriceData } from '..';
|
|
9
9
|
export interface AccountSubscriber<T> {
|
|
10
10
|
dataAndSlot?: DataAndSlot<T>;
|
|
@@ -57,7 +57,7 @@ export interface UserAccountSubscriber {
|
|
|
57
57
|
getUserAccountAndSlot(): DataAndSlot<UserAccount>;
|
|
58
58
|
}
|
|
59
59
|
export interface TokenAccountEvents {
|
|
60
|
-
tokenAccountUpdate: (payload:
|
|
60
|
+
tokenAccountUpdate: (payload: Account) => void;
|
|
61
61
|
update: void;
|
|
62
62
|
error: (e: Error) => void;
|
|
63
63
|
}
|
|
@@ -67,7 +67,7 @@ export interface TokenAccountSubscriber {
|
|
|
67
67
|
subscribe(): Promise<boolean>;
|
|
68
68
|
fetch(): Promise<void>;
|
|
69
69
|
unsubscribe(): Promise<void>;
|
|
70
|
-
getTokenAccountAndSlot(): DataAndSlot<
|
|
70
|
+
getTokenAccountAndSlot(): DataAndSlot<Account>;
|
|
71
71
|
}
|
|
72
72
|
export interface OracleEvents {
|
|
73
73
|
oracleUpdate: (payload: OraclePriceData) => void;
|
|
@@ -58,6 +58,16 @@ exports.MainnetSpotMarkets = [
|
|
|
58
58
|
serumMarket: new web3_js_1.PublicKey('8BnEgHoWFysVcuFFX7QztDmzuH8r5ZFvyP3sYwn1XTh6'),
|
|
59
59
|
phoenixMarket: new web3_js_1.PublicKey('4DoNfFBfF7UokCC2FQzriy7yHK6DY6NVdYpuekQ5pRgg'),
|
|
60
60
|
},
|
|
61
|
+
{
|
|
62
|
+
symbol: 'mSOL',
|
|
63
|
+
marketIndex: 2,
|
|
64
|
+
oracle: new web3_js_1.PublicKey('E4v1BBgoso9s64TQvmyownAVJbhbEPGyzA3qn4n46qj9'),
|
|
65
|
+
oracleSource: __1.OracleSource.PYTH,
|
|
66
|
+
mint: new web3_js_1.PublicKey('mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So'),
|
|
67
|
+
precision: new __1.BN(10).pow(numericConstants_1.NINE),
|
|
68
|
+
precisionExp: numericConstants_1.NINE,
|
|
69
|
+
serumMarket: new web3_js_1.PublicKey('9Lyhks5bQQxb9EyyX55NtgKQzpM4WK7JCmeaWuQ5MoXD'),
|
|
70
|
+
},
|
|
61
71
|
];
|
|
62
72
|
exports.SpotMarkets = {
|
|
63
73
|
devnet: exports.DevnetSpotMarkets,
|
package/lib/dlob/DLOB.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NodeList } from './NodeList';
|
|
2
|
-
import { BN, DLOBNode, DLOBNodeType, DriftClient, MarketType, MarketTypeStr, OraclePriceData, Order, OrderActionRecord, OrderRecord, PerpMarketAccount, SlotSubscriber, SpotMarketAccount, StateAccount, TriggerOrderNode, UserMap } from '..';
|
|
2
|
+
import { BN, DLOBNode, DLOBNodeType, DriftClient, MarketType, MarketTypeStr, OraclePriceData, Order, OrderActionRecord, OrderRecord, PerpMarketAccount, PositionDirection, SlotSubscriber, SpotMarketAccount, StateAccount, TriggerOrderNode, UserMap } from '..';
|
|
3
3
|
import { PublicKey } from '@solana/web3.js';
|
|
4
4
|
import { DLOBOrders } from './DLOBOrders';
|
|
5
5
|
import { L2OrderBook, L2OrderBookGenerator, L3OrderBook } from './orderBookLevels';
|
|
@@ -135,5 +135,24 @@ export declare class DLOB {
|
|
|
135
135
|
slot: number;
|
|
136
136
|
oraclePriceData: OraclePriceData;
|
|
137
137
|
}): L3OrderBook;
|
|
138
|
+
private estimateFillExactBaseAmountInForSide;
|
|
139
|
+
/**
|
|
140
|
+
*
|
|
141
|
+
* @param param.marketIndex the index of the market
|
|
142
|
+
* @param param.marketType the type of the market
|
|
143
|
+
* @param param.baseAmount the base amount in to estimate
|
|
144
|
+
* @param param.orderDirection the direction of the trade
|
|
145
|
+
* @param param.slot current slot for estimating dlob node price
|
|
146
|
+
* @param param.oraclePriceData the oracle price data
|
|
147
|
+
* @returns the estimated quote amount filled: QUOTE_PRECISION
|
|
148
|
+
*/
|
|
149
|
+
estimateFillWithExactBaseAmount({ marketIndex, marketType, baseAmount, orderDirection, slot, oraclePriceData, }: {
|
|
150
|
+
marketIndex: number;
|
|
151
|
+
marketType: MarketType;
|
|
152
|
+
baseAmount: BN;
|
|
153
|
+
orderDirection: PositionDirection;
|
|
154
|
+
slot: number;
|
|
155
|
+
oraclePriceData: OraclePriceData;
|
|
156
|
+
}): BN;
|
|
138
157
|
}
|
|
139
158
|
export {};
|
package/lib/dlob/DLOB.js
CHANGED
|
@@ -1023,5 +1023,44 @@ class DLOB {
|
|
|
1023
1023
|
asks,
|
|
1024
1024
|
};
|
|
1025
1025
|
}
|
|
1026
|
+
estimateFillExactBaseAmountInForSide(baseAmountIn, oraclePriceData, slot, dlobSide) {
|
|
1027
|
+
let runningSumQuote = __1.ZERO;
|
|
1028
|
+
let runningSumBase = __1.ZERO;
|
|
1029
|
+
for (const side of dlobSide) {
|
|
1030
|
+
const price = side.getPrice(oraclePriceData, slot); //side.order.quoteAssetAmount.div(side.order.baseAssetAmount);
|
|
1031
|
+
const baseAmountRemaining = side.order.baseAssetAmount.sub(side.order.baseAssetAmountFilled);
|
|
1032
|
+
if (runningSumBase.add(baseAmountRemaining).gt(baseAmountIn)) {
|
|
1033
|
+
const remainingBase = baseAmountIn.sub(runningSumBase);
|
|
1034
|
+
runningSumBase = runningSumBase.add(remainingBase);
|
|
1035
|
+
runningSumQuote = runningSumQuote.add(remainingBase.mul(price));
|
|
1036
|
+
break;
|
|
1037
|
+
}
|
|
1038
|
+
else {
|
|
1039
|
+
runningSumBase = runningSumBase.add(baseAmountRemaining);
|
|
1040
|
+
runningSumQuote = runningSumQuote.add(baseAmountRemaining.mul(price));
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
return runningSumQuote
|
|
1044
|
+
.mul(__1.QUOTE_PRECISION)
|
|
1045
|
+
.div(__1.BASE_PRECISION.mul(__1.PRICE_PRECISION));
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
*
|
|
1049
|
+
* @param param.marketIndex the index of the market
|
|
1050
|
+
* @param param.marketType the type of the market
|
|
1051
|
+
* @param param.baseAmount the base amount in to estimate
|
|
1052
|
+
* @param param.orderDirection the direction of the trade
|
|
1053
|
+
* @param param.slot current slot for estimating dlob node price
|
|
1054
|
+
* @param param.oraclePriceData the oracle price data
|
|
1055
|
+
* @returns the estimated quote amount filled: QUOTE_PRECISION
|
|
1056
|
+
*/
|
|
1057
|
+
estimateFillWithExactBaseAmount({ marketIndex, marketType, baseAmount, orderDirection, slot, oraclePriceData, }) {
|
|
1058
|
+
if ((0, __1.isVariant)(orderDirection, 'long')) {
|
|
1059
|
+
return this.estimateFillExactBaseAmountInForSide(baseAmount, oraclePriceData, slot, this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData));
|
|
1060
|
+
}
|
|
1061
|
+
else if ((0, __1.isVariant)(orderDirection, 'short')) {
|
|
1062
|
+
return this.estimateFillExactBaseAmountInForSide(baseAmount, oraclePriceData, slot, this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData));
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1026
1065
|
}
|
|
1027
1066
|
exports.DLOB = DLOB;
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { AnchorProvider, BN, Program, ProgramAccount } from '@coral-xyz/anchor';
|
|
3
|
-
import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount, ReferrerNameAccount, OrderTriggerCondition, PerpMarketExtendedInfo, UserStatsAccount, PhoenixV1FulfillmentConfigAccount, ModifyOrderPolicy } from './types';
|
|
3
|
+
import { StateAccount, IWallet, PositionDirection, UserAccount, PerpMarketAccount, OrderParams, Order, SpotMarketAccount, SpotPosition, MakerInfo, TakerInfo, OptionalOrderParams, ReferrerInfo, MarketType, TxParams, SerumV3FulfillmentConfigAccount, ReferrerNameAccount, OrderTriggerCondition, PerpMarketExtendedInfo, UserStatsAccount, PhoenixV1FulfillmentConfigAccount, ModifyOrderPolicy, SwapReduceOnly } from './types';
|
|
4
4
|
import * as anchor from '@coral-xyz/anchor';
|
|
5
5
|
import { Connection, PublicKey, TransactionSignature, ConfirmOptions, Transaction, TransactionInstruction, AccountMeta, Signer, AddressLookupTableAccount, TransactionVersion, VersionedTransaction } from '@solana/web3.js';
|
|
6
6
|
import { TokenFaucet } from './tokenFaucet';
|
|
@@ -13,6 +13,7 @@ import { DriftClientConfig } from './driftClientConfig';
|
|
|
13
13
|
import { User } from './user';
|
|
14
14
|
import { UserSubscriptionConfig } from './userConfig';
|
|
15
15
|
import { UserStats } from './userStats';
|
|
16
|
+
import { JupiterClient, Route, SwapMode } from './jupiter/jupiterClient';
|
|
16
17
|
type RemainingAccountParams = {
|
|
17
18
|
userAccounts: UserAccount[];
|
|
18
19
|
writablePerpMarketIndexes?: number[];
|
|
@@ -171,6 +172,7 @@ export declare class DriftClient {
|
|
|
171
172
|
* @param useNative
|
|
172
173
|
*/
|
|
173
174
|
getAssociatedTokenAccount(marketIndex: number, useNative?: boolean): Promise<PublicKey>;
|
|
175
|
+
createAssociatedTokenAccountIdempotentInstruction(account: PublicKey, payer: PublicKey, owner: PublicKey, mint: PublicKey): TransactionInstruction;
|
|
174
176
|
/**
|
|
175
177
|
* Deposit funds into the given spot market
|
|
176
178
|
*
|
|
@@ -274,6 +276,53 @@ export declare class DriftClient {
|
|
|
274
276
|
addSpotFulfillmentAccounts(marketIndex: number, remainingAccounts: AccountMeta[], fulfillmentConfig?: SerumV3FulfillmentConfigAccount | PhoenixV1FulfillmentConfigAccount): void;
|
|
275
277
|
addSerumRemainingAccounts(marketIndex: number, remainingAccounts: AccountMeta[], fulfillmentConfig: SerumV3FulfillmentConfigAccount): void;
|
|
276
278
|
addPhoenixRemainingAccounts(marketIndex: number, remainingAccounts: AccountMeta[], fulfillmentConfig: PhoenixV1FulfillmentConfigAccount): void;
|
|
279
|
+
/**
|
|
280
|
+
* Swap tokens in drift account using jupiter
|
|
281
|
+
* @param jupiterClient jupiter client to find routes and jupiter instructions
|
|
282
|
+
* @param outMarketIndex the market index of the token you're buying
|
|
283
|
+
* @param inMarketIndex the market index of the token you're selling
|
|
284
|
+
* @param outAssociatedTokenAccount the token account to receive the token being sold on jupiter
|
|
285
|
+
* @param inAssociatedTokenAccount the token account to
|
|
286
|
+
* @param amount the amount of the token to sell
|
|
287
|
+
* @param slippageBps the max slippage passed to jupiter api
|
|
288
|
+
* @param route the jupiter route to use for the swap
|
|
289
|
+
* @param txParams
|
|
290
|
+
*/
|
|
291
|
+
swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, }: {
|
|
292
|
+
jupiterClient: JupiterClient;
|
|
293
|
+
outMarketIndex: number;
|
|
294
|
+
inMarketIndex: number;
|
|
295
|
+
outAssociatedTokenAccount?: PublicKey;
|
|
296
|
+
inAssociatedTokenAccount?: PublicKey;
|
|
297
|
+
amount: BN;
|
|
298
|
+
slippageBps?: number;
|
|
299
|
+
swapMode?: SwapMode;
|
|
300
|
+
route?: Route;
|
|
301
|
+
reduceOnly?: SwapReduceOnly;
|
|
302
|
+
txParams?: TxParams;
|
|
303
|
+
}): Promise<TransactionSignature>;
|
|
304
|
+
/**
|
|
305
|
+
* Get the drift begin_swap and end_swap instructions
|
|
306
|
+
*
|
|
307
|
+
* @param outMarketIndex the market index of the token you're buying
|
|
308
|
+
* @param inMarketIndex the market index of the token you're selling
|
|
309
|
+
* @param amountIn the amount of the token to sell
|
|
310
|
+
* @param inTokenAccount the token account to move the tokens being sold
|
|
311
|
+
* @param outTokenAccount the token account to receive the tokens being bought
|
|
312
|
+
* @param limitPrice the limit price of the swap
|
|
313
|
+
*/
|
|
314
|
+
getSwapIx({ outMarketIndex, inMarketIndex, amountIn, inTokenAccount, outTokenAccount, limitPrice, reduceOnly, }: {
|
|
315
|
+
outMarketIndex: number;
|
|
316
|
+
inMarketIndex: number;
|
|
317
|
+
amountIn: BN;
|
|
318
|
+
inTokenAccount: PublicKey;
|
|
319
|
+
outTokenAccount: PublicKey;
|
|
320
|
+
limitPrice?: BN;
|
|
321
|
+
reduceOnly?: SwapReduceOnly;
|
|
322
|
+
}): Promise<{
|
|
323
|
+
beginSwapIx: TransactionInstruction;
|
|
324
|
+
endSwapIx: TransactionInstruction;
|
|
325
|
+
}>;
|
|
277
326
|
triggerOrder(userAccountPublicKey: PublicKey, user: UserAccount, order: Order, txParams?: TxParams): Promise<TransactionSignature>;
|
|
278
327
|
getTriggerOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order): Promise<TransactionInstruction>;
|
|
279
328
|
forceCancelOrders(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
|
|
@@ -485,6 +534,6 @@ export declare class DriftClient {
|
|
|
485
534
|
marketType: MarketType;
|
|
486
535
|
} | undefined;
|
|
487
536
|
sendTransaction(tx: Transaction | VersionedTransaction, additionalSigners?: Array<Signer>, opts?: ConfirmOptions, preSigned?: boolean): Promise<TxSigAndSlot>;
|
|
488
|
-
buildTransaction(instructions: TransactionInstruction | TransactionInstruction[], txParams?: TxParams): Promise<Transaction | VersionedTransaction>;
|
|
537
|
+
buildTransaction(instructions: TransactionInstruction | TransactionInstruction[], txParams?: TxParams, txVersion?: TransactionVersion, lookupTables?: AddressLookupTableAccount[]): Promise<Transaction | VersionedTransaction>;
|
|
489
538
|
}
|
|
490
539
|
export {};
|
package/lib/driftClient.js
CHANGED
|
@@ -411,7 +411,7 @@ class DriftClient {
|
|
|
411
411
|
}
|
|
412
412
|
const state = this.getStateAccount();
|
|
413
413
|
if (!state.whitelistMint.equals(web3_js_1.PublicKey.default)) {
|
|
414
|
-
const associatedTokenPublicKey = await
|
|
414
|
+
const associatedTokenPublicKey = await (0, spl_token_1.getAssociatedTokenAddress)(state.whitelistMint, this.wallet.publicKey);
|
|
415
415
|
remainingAccounts.push({
|
|
416
416
|
pubkey: associatedTokenPublicKey,
|
|
417
417
|
isWritable: false,
|
|
@@ -955,7 +955,25 @@ class DriftClient {
|
|
|
955
955
|
return this.wallet.publicKey;
|
|
956
956
|
}
|
|
957
957
|
const mint = spotMarket.mint;
|
|
958
|
-
return await
|
|
958
|
+
return await (0, spl_token_1.getAssociatedTokenAddress)(mint, this.wallet.publicKey);
|
|
959
|
+
}
|
|
960
|
+
createAssociatedTokenAccountIdempotentInstruction(account, payer, owner, mint) {
|
|
961
|
+
return new web3_js_1.TransactionInstruction({
|
|
962
|
+
keys: [
|
|
963
|
+
{ pubkey: payer, isSigner: true, isWritable: true },
|
|
964
|
+
{ pubkey: account, isSigner: false, isWritable: true },
|
|
965
|
+
{ pubkey: owner, isSigner: false, isWritable: false },
|
|
966
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
967
|
+
{
|
|
968
|
+
pubkey: anchor.web3.SystemProgram.programId,
|
|
969
|
+
isSigner: false,
|
|
970
|
+
isWritable: false,
|
|
971
|
+
},
|
|
972
|
+
{ pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
973
|
+
],
|
|
974
|
+
programId: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
975
|
+
data: Buffer.from([0x1]),
|
|
976
|
+
});
|
|
959
977
|
}
|
|
960
978
|
/**
|
|
961
979
|
* Deposit funds into the given spot market
|
|
@@ -988,7 +1006,7 @@ class DriftClient {
|
|
|
988
1006
|
tx.add(depositCollateralIx);
|
|
989
1007
|
// Close the wrapped sol account at the end of the transaction
|
|
990
1008
|
if (createWSOLTokenAccount) {
|
|
991
|
-
tx.add(spl_token_1.
|
|
1009
|
+
tx.add((0, spl_token_1.createCloseAccountInstruction)(associatedTokenAccount, signerAuthority, signerAuthority, []));
|
|
992
1010
|
}
|
|
993
1011
|
const { txSig, slot } = await this.sendTransaction(tx, additionalSigners, this.opts);
|
|
994
1012
|
this.spotMarketLastSlotCache.set(marketIndex, slot);
|
|
@@ -1054,13 +1072,12 @@ class DriftClient {
|
|
|
1054
1072
|
space: 165,
|
|
1055
1073
|
programId: spl_token_1.TOKEN_PROGRAM_ID,
|
|
1056
1074
|
}));
|
|
1057
|
-
result.ixs.push(spl_token_1.
|
|
1075
|
+
result.ixs.push((0, spl_token_1.createInitializeAccountInstruction)(wrappedSolAccount.publicKey, spotMarkets_1.WRAPPED_SOL_MINT, authority));
|
|
1058
1076
|
result.signers.push(wrappedSolAccount);
|
|
1059
1077
|
return result;
|
|
1060
1078
|
}
|
|
1061
1079
|
getAssociatedTokenAccountCreationIx(tokenMintAddress, associatedTokenAddress) {
|
|
1062
|
-
|
|
1063
|
-
return createAssociatedAccountIx;
|
|
1080
|
+
return (0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, associatedTokenAddress, this.wallet.publicKey, tokenMintAddress);
|
|
1064
1081
|
}
|
|
1065
1082
|
/**
|
|
1066
1083
|
* Creates the Clearing House User account for a user, and deposits some initial collateral
|
|
@@ -1108,7 +1125,7 @@ class DriftClient {
|
|
|
1108
1125
|
tx.add(initializeUserAccountIx).add(depositCollateralIx);
|
|
1109
1126
|
// Close the wrapped sol account at the end of the transaction
|
|
1110
1127
|
if (createWSOLTokenAccount) {
|
|
1111
|
-
tx.add(spl_token_1.
|
|
1128
|
+
tx.add((0, spl_token_1.createCloseAccountInstruction)(userTokenAccount, authority, authority, []));
|
|
1112
1129
|
}
|
|
1113
1130
|
const { txSig, slot } = await this.sendTransaction(tx, additionalSigners, this.opts);
|
|
1114
1131
|
this.spotMarketLastSlotCache.set(marketIndex, slot);
|
|
@@ -1166,7 +1183,7 @@ class DriftClient {
|
|
|
1166
1183
|
tx.add(withdrawCollateral);
|
|
1167
1184
|
// Close the wrapped sol account at the end of the transaction
|
|
1168
1185
|
if (createWSOLTokenAccount) {
|
|
1169
|
-
tx.add(spl_token_1.
|
|
1186
|
+
tx.add((0, spl_token_1.createCloseAccountInstruction)(associatedTokenAddress, authority, authority, []));
|
|
1170
1187
|
}
|
|
1171
1188
|
const { txSig, slot } = await this.sendTransaction(tx, additionalSigners, this.opts);
|
|
1172
1189
|
this.spotMarketLastSlotCache.set(marketIndex, slot);
|
|
@@ -1947,6 +1964,134 @@ class DriftClient {
|
|
|
1947
1964
|
isSigner: false,
|
|
1948
1965
|
});
|
|
1949
1966
|
}
|
|
1967
|
+
/**
|
|
1968
|
+
* Swap tokens in drift account using jupiter
|
|
1969
|
+
* @param jupiterClient jupiter client to find routes and jupiter instructions
|
|
1970
|
+
* @param outMarketIndex the market index of the token you're buying
|
|
1971
|
+
* @param inMarketIndex the market index of the token you're selling
|
|
1972
|
+
* @param outAssociatedTokenAccount the token account to receive the token being sold on jupiter
|
|
1973
|
+
* @param inAssociatedTokenAccount the token account to
|
|
1974
|
+
* @param amount the amount of the token to sell
|
|
1975
|
+
* @param slippageBps the max slippage passed to jupiter api
|
|
1976
|
+
* @param route the jupiter route to use for the swap
|
|
1977
|
+
* @param txParams
|
|
1978
|
+
*/
|
|
1979
|
+
async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, }) {
|
|
1980
|
+
const outMarket = this.getSpotMarketAccount(outMarketIndex);
|
|
1981
|
+
const inMarket = this.getSpotMarketAccount(inMarketIndex);
|
|
1982
|
+
if (!route) {
|
|
1983
|
+
const routes = await jupiterClient.getRoutes({
|
|
1984
|
+
inputMint: inMarket.mint,
|
|
1985
|
+
outputMint: outMarket.mint,
|
|
1986
|
+
amount,
|
|
1987
|
+
slippageBps,
|
|
1988
|
+
swapMode,
|
|
1989
|
+
});
|
|
1990
|
+
if (!routes || routes.length === 0) {
|
|
1991
|
+
throw new Error('No jupiter routes found');
|
|
1992
|
+
}
|
|
1993
|
+
route = routes[0];
|
|
1994
|
+
}
|
|
1995
|
+
const transaction = await jupiterClient.getSwapTransaction({
|
|
1996
|
+
route,
|
|
1997
|
+
userPublicKey: this.provider.wallet.publicKey,
|
|
1998
|
+
slippageBps,
|
|
1999
|
+
});
|
|
2000
|
+
const { transactionMessage, lookupTables } = await jupiterClient.getTransactionMessageAndLookupTables({
|
|
2001
|
+
transaction,
|
|
2002
|
+
});
|
|
2003
|
+
const jupiterInstructions = jupiterClient.getJupiterInstructions({
|
|
2004
|
+
transactionMessage,
|
|
2005
|
+
inputMint: inMarket.mint,
|
|
2006
|
+
outputMint: outMarket.mint,
|
|
2007
|
+
});
|
|
2008
|
+
const preInstructions = [];
|
|
2009
|
+
if (!outAssociatedTokenAccount) {
|
|
2010
|
+
outAssociatedTokenAccount = await this.getAssociatedTokenAccount(outMarket.marketIndex, false);
|
|
2011
|
+
const accountInfo = await this.connection.getAccountInfo(outAssociatedTokenAccount);
|
|
2012
|
+
if (!accountInfo) {
|
|
2013
|
+
preInstructions.push(this.createAssociatedTokenAccountIdempotentInstruction(outAssociatedTokenAccount, this.provider.wallet.publicKey, this.provider.wallet.publicKey, outMarket.mint));
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
if (!inAssociatedTokenAccount) {
|
|
2017
|
+
inAssociatedTokenAccount = await this.getAssociatedTokenAccount(inMarket.marketIndex, false);
|
|
2018
|
+
const accountInfo = await this.connection.getAccountInfo(inAssociatedTokenAccount);
|
|
2019
|
+
if (!accountInfo) {
|
|
2020
|
+
preInstructions.push(this.createAssociatedTokenAccountIdempotentInstruction(inAssociatedTokenAccount, this.provider.wallet.publicKey, this.provider.wallet.publicKey, inMarket.mint));
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
const { beginSwapIx, endSwapIx } = await this.getSwapIx({
|
|
2024
|
+
outMarketIndex,
|
|
2025
|
+
inMarketIndex,
|
|
2026
|
+
amountIn: amount,
|
|
2027
|
+
inTokenAccount: inAssociatedTokenAccount,
|
|
2028
|
+
outTokenAccount: outAssociatedTokenAccount,
|
|
2029
|
+
reduceOnly,
|
|
2030
|
+
});
|
|
2031
|
+
const instructions = [
|
|
2032
|
+
...preInstructions,
|
|
2033
|
+
beginSwapIx,
|
|
2034
|
+
...jupiterInstructions,
|
|
2035
|
+
endSwapIx,
|
|
2036
|
+
];
|
|
2037
|
+
const tx = await this.buildTransaction(instructions, txParams, 0, lookupTables);
|
|
2038
|
+
const { txSig, slot } = await this.sendTransaction(tx);
|
|
2039
|
+
this.spotMarketLastSlotCache.set(outMarketIndex, slot);
|
|
2040
|
+
this.spotMarketLastSlotCache.set(inMarketIndex, slot);
|
|
2041
|
+
return txSig;
|
|
2042
|
+
}
|
|
2043
|
+
/**
|
|
2044
|
+
* Get the drift begin_swap and end_swap instructions
|
|
2045
|
+
*
|
|
2046
|
+
* @param outMarketIndex the market index of the token you're buying
|
|
2047
|
+
* @param inMarketIndex the market index of the token you're selling
|
|
2048
|
+
* @param amountIn the amount of the token to sell
|
|
2049
|
+
* @param inTokenAccount the token account to move the tokens being sold
|
|
2050
|
+
* @param outTokenAccount the token account to receive the tokens being bought
|
|
2051
|
+
* @param limitPrice the limit price of the swap
|
|
2052
|
+
*/
|
|
2053
|
+
async getSwapIx({ outMarketIndex, inMarketIndex, amountIn, inTokenAccount, outTokenAccount, limitPrice, reduceOnly, }) {
|
|
2054
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
2055
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
2056
|
+
userAccounts: [this.getUserAccount()],
|
|
2057
|
+
writableSpotMarketIndexes: [outMarketIndex, inMarketIndex],
|
|
2058
|
+
});
|
|
2059
|
+
const outSpotMarket = this.getSpotMarketAccount(outMarketIndex);
|
|
2060
|
+
const inSpotMarket = this.getSpotMarketAccount(inMarketIndex);
|
|
2061
|
+
const beginSwapIx = await this.program.instruction.beginSwap(inMarketIndex, outMarketIndex, amountIn, {
|
|
2062
|
+
accounts: {
|
|
2063
|
+
state: await this.getStatePublicKey(),
|
|
2064
|
+
user: userAccountPublicKey,
|
|
2065
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2066
|
+
authority: this.authority,
|
|
2067
|
+
outSpotMarketVault: outSpotMarket.vault,
|
|
2068
|
+
inSpotMarketVault: inSpotMarket.vault,
|
|
2069
|
+
inTokenAccount,
|
|
2070
|
+
outTokenAccount,
|
|
2071
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
2072
|
+
driftSigner: this.getStateAccount().signer,
|
|
2073
|
+
instructions: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
2074
|
+
},
|
|
2075
|
+
remainingAccounts,
|
|
2076
|
+
});
|
|
2077
|
+
const endSwapIx = await this.program.instruction.endSwap(inMarketIndex, outMarketIndex, limitPrice !== null && limitPrice !== void 0 ? limitPrice : null, reduceOnly !== null && reduceOnly !== void 0 ? reduceOnly : null, {
|
|
2078
|
+
accounts: {
|
|
2079
|
+
state: await this.getStatePublicKey(),
|
|
2080
|
+
user: userAccountPublicKey,
|
|
2081
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
2082
|
+
authority: this.authority,
|
|
2083
|
+
outSpotMarketVault: outSpotMarket.vault,
|
|
2084
|
+
inSpotMarketVault: inSpotMarket.vault,
|
|
2085
|
+
inTokenAccount,
|
|
2086
|
+
outTokenAccount,
|
|
2087
|
+
tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
|
|
2088
|
+
driftSigner: this.getStateAccount().signer,
|
|
2089
|
+
instructions: anchor.web3.SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
2090
|
+
},
|
|
2091
|
+
remainingAccounts,
|
|
2092
|
+
});
|
|
2093
|
+
return { beginSwapIx, endSwapIx };
|
|
2094
|
+
}
|
|
1950
2095
|
async triggerOrder(userAccountPublicKey, user, order, txParams) {
|
|
1951
2096
|
const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getTriggerOrderIx(userAccountPublicKey, user, order), txParams), [], this.opts);
|
|
1952
2097
|
return txSig;
|
|
@@ -2707,7 +2852,7 @@ class DriftClient {
|
|
|
2707
2852
|
const addFundsIx = await this.getAddInsuranceFundStakeIx(marketIndex, amount, tokenAccount);
|
|
2708
2853
|
tx.add(addFundsIx);
|
|
2709
2854
|
if (createWSOLTokenAccount) {
|
|
2710
|
-
tx.add(spl_token_1.
|
|
2855
|
+
tx.add((0, spl_token_1.createCloseAccountInstruction)(tokenAccount, this.wallet.publicKey, this.wallet.publicKey, []));
|
|
2711
2856
|
}
|
|
2712
2857
|
const { txSig } = await this.sendTransaction(tx, additionalSigners, this.opts);
|
|
2713
2858
|
return txSig;
|
|
@@ -2797,7 +2942,7 @@ class DriftClient {
|
|
|
2797
2942
|
tx.add(removeStakeIx);
|
|
2798
2943
|
// Close the wrapped sol account at the end of the transaction
|
|
2799
2944
|
if (createWSOLTokenAccount) {
|
|
2800
|
-
tx.add(spl_token_1.
|
|
2945
|
+
tx.add((0, spl_token_1.createCloseAccountInstruction)(tokenAccount, this.wallet.publicKey, this.wallet.publicKey, []));
|
|
2801
2946
|
}
|
|
2802
2947
|
const { txSig } = await this.sendTransaction(tx, additionalSigners, this.opts);
|
|
2803
2948
|
return txSig;
|
|
@@ -2895,7 +3040,7 @@ class DriftClient {
|
|
|
2895
3040
|
return this.txSender.sendVersionedTransaction(tx, additionalSigners, opts);
|
|
2896
3041
|
}
|
|
2897
3042
|
}
|
|
2898
|
-
async buildTransaction(instructions, txParams) {
|
|
3043
|
+
async buildTransaction(instructions, txParams, txVersion, lookupTables) {
|
|
2899
3044
|
var _a, _b;
|
|
2900
3045
|
const allIx = [];
|
|
2901
3046
|
const computeUnits = (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : 600000;
|
|
@@ -2916,16 +3061,20 @@ class DriftClient {
|
|
|
2916
3061
|
else {
|
|
2917
3062
|
allIx.push(instructions);
|
|
2918
3063
|
}
|
|
2919
|
-
|
|
3064
|
+
txVersion = txVersion !== null && txVersion !== void 0 ? txVersion : this.txVersion;
|
|
3065
|
+
if (txVersion === 'legacy') {
|
|
2920
3066
|
return new web3_js_1.Transaction().add(...allIx);
|
|
2921
3067
|
}
|
|
2922
3068
|
else {
|
|
2923
3069
|
const marketLookupTable = await this.fetchMarketLookupTableAccount();
|
|
3070
|
+
lookupTables = lookupTables
|
|
3071
|
+
? [...lookupTables, marketLookupTable]
|
|
3072
|
+
: [marketLookupTable];
|
|
2924
3073
|
const message = new web3_js_1.TransactionMessage({
|
|
2925
3074
|
payerKey: this.provider.wallet.publicKey,
|
|
2926
3075
|
recentBlockhash: (await this.provider.connection.getRecentBlockhash(this.opts.preflightCommitment)).blockhash,
|
|
2927
3076
|
instructions: allIx,
|
|
2928
|
-
}).compileToV0Message(
|
|
3077
|
+
}).compileToV0Message(lookupTables);
|
|
2929
3078
|
return new web3_js_1.VersionedTransaction(message);
|
|
2930
3079
|
}
|
|
2931
3080
|
}
|
package/lib/events/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Commitment, TransactionSignature } from '@solana/web3.js';
|
|
2
|
-
import { DepositRecord, FundingPaymentRecord, FundingRateRecord, LiquidationRecord, NewUserRecord, OrderActionRecord, OrderRecord, SettlePnlRecord, LPRecord, InsuranceFundRecord, SpotInterestRecord, InsuranceFundStakeRecord, CurveRecord } from '../index';
|
|
2
|
+
import { DepositRecord, FundingPaymentRecord, FundingRateRecord, LiquidationRecord, NewUserRecord, OrderActionRecord, OrderRecord, SettlePnlRecord, LPRecord, InsuranceFundRecord, SpotInterestRecord, InsuranceFundStakeRecord, CurveRecord, SwapRecord } from '../index';
|
|
3
3
|
export type EventSubscriptionOptions = {
|
|
4
4
|
eventTypes?: EventType[];
|
|
5
5
|
maxEventsPerType?: number;
|
|
@@ -35,9 +35,10 @@ export type EventMap = {
|
|
|
35
35
|
SpotInterestRecord: Event<SpotInterestRecord>;
|
|
36
36
|
InsuranceFundStakeRecord: Event<InsuranceFundStakeRecord>;
|
|
37
37
|
CurveRecord: Event<CurveRecord>;
|
|
38
|
+
SwapRecord: Event<SwapRecord>;
|
|
38
39
|
};
|
|
39
40
|
export type EventType = keyof EventMap;
|
|
40
|
-
export type DriftEvent = Event<DepositRecord> | Event<FundingPaymentRecord> | Event<LiquidationRecord> | Event<FundingRateRecord> | Event<OrderRecord> | Event<OrderActionRecord> | Event<SettlePnlRecord> | Event<NewUserRecord> | Event<LPRecord> | Event<InsuranceFundRecord> | Event<SpotInterestRecord> | Event<InsuranceFundStakeRecord> | Event<CurveRecord>;
|
|
41
|
+
export type DriftEvent = Event<DepositRecord> | Event<FundingPaymentRecord> | Event<LiquidationRecord> | Event<FundingRateRecord> | Event<OrderRecord> | Event<OrderActionRecord> | Event<SettlePnlRecord> | Event<NewUserRecord> | Event<LPRecord> | Event<InsuranceFundRecord> | Event<SpotInterestRecord> | Event<InsuranceFundStakeRecord> | Event<CurveRecord> | Event<SwapRecord>;
|
|
41
42
|
export interface EventSubscriberEvents {
|
|
42
43
|
newEvent: (event: WrappedEvent<EventType>) => void;
|
|
43
44
|
}
|
package/lib/events/types.js
CHANGED
|
@@ -8,7 +8,7 @@ const web3_js_1 = require("@solana/web3.js");
|
|
|
8
8
|
const __2 = require("..");
|
|
9
9
|
const spotMarkets_1 = require("../constants/spotMarkets");
|
|
10
10
|
const getTokenAddress = (mintAddress, userPubKey) => {
|
|
11
|
-
return
|
|
11
|
+
return (0, spl_token_1.getAssociatedTokenAddress)(new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
|
|
12
12
|
};
|
|
13
13
|
exports.getTokenAddress = getTokenAddress;
|
|
14
14
|
const env = 'devnet';
|