@drift-labs/sdk 2.31.1-beta.2 → 2.31.1-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -1
- package/lib/accounts/mockUserAccountSubscriber.d.ts +23 -0
- package/lib/accounts/mockUserAccountSubscriber.js +31 -0
- package/lib/constants/perpMarkets.js +20 -0
- package/lib/dlob/orderBookLevels.js +2 -2
- package/lib/driftClient.d.ts +57 -4
- package/lib/driftClient.js +244 -205
- package/lib/driftClientConfig.d.ts +2 -1
- package/lib/idl/drift.json +31 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/marinade/index.d.ts +11 -0
- package/lib/marinade/index.js +36 -0
- package/lib/marinade/types.d.ts +1963 -0
- package/lib/marinade/types.js +1965 -0
- package/lib/math/spotBalance.d.ts +9 -2
- package/lib/math/spotBalance.js +54 -6
- package/lib/math/superStake.d.ts +22 -0
- package/lib/math/superStake.js +108 -0
- package/lib/math/tiers.d.ts +4 -0
- package/lib/math/tiers.js +52 -0
- package/lib/tx/retryTxSender.d.ts +12 -3
- package/lib/tx/retryTxSender.js +22 -22
- package/lib/tx/types.d.ts +2 -2
- package/lib/user.d.ts +10 -1
- package/lib/user.js +39 -8
- package/lib/userConfig.d.ts +4 -0
- package/lib/userStats.js +4 -1
- package/lib/userStatsConfig.d.ts +2 -0
- package/package.json +1 -1
- package/src/accounts/mockUserAccountSubscriber.ts +53 -0
- package/src/config.ts +2 -2
- package/src/constants/perpMarkets.ts +20 -0
- package/src/dlob/orderBookLevels.ts +3 -2
- package/src/driftClient.ts +440 -224
- package/src/driftClientConfig.ts +2 -1
- package/src/idl/drift.json +31 -1
- package/src/index.ts +2 -0
- package/src/marinade/idl/idl.json +1962 -0
- package/src/marinade/index.ts +64 -0
- package/src/marinade/types.ts +3925 -0
- package/src/math/spotBalance.ts +83 -5
- package/src/math/superStake.ts +148 -0
- package/src/math/tiers.ts +44 -0
- package/src/tx/retryTxSender.ts +39 -35
- package/src/tx/types.ts +2 -2
- package/src/user.ts +63 -12
- package/src/userConfig.ts +5 -0
- package/src/userStats.ts +4 -0
- package/src/userStatsConfig.ts +3 -0
- package/tests/spot/test.ts +156 -0
package/lib/driftClient.js
CHANGED
|
@@ -52,6 +52,7 @@ const market_1 = require("./math/market");
|
|
|
52
52
|
const fetch_1 = require("./accounts/fetch");
|
|
53
53
|
const spotMarket_1 = require("./math/spotMarket");
|
|
54
54
|
const memcmp_1 = require("./memcmp");
|
|
55
|
+
const marinade_1 = require("./marinade");
|
|
55
56
|
/**
|
|
56
57
|
* # DriftClient
|
|
57
58
|
* This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
|
|
@@ -64,11 +65,13 @@ class DriftClient {
|
|
|
64
65
|
this._isSubscribed = val;
|
|
65
66
|
}
|
|
66
67
|
constructor(config) {
|
|
67
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
68
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
68
69
|
this.users = new Map();
|
|
69
70
|
this._isSubscribed = false;
|
|
70
71
|
this.perpMarketLastSlotCache = new Map();
|
|
71
72
|
this.spotMarketLastSlotCache = new Map();
|
|
73
|
+
this.mustIncludePerpMarketIndexes = new Set();
|
|
74
|
+
this.mustIncludeSpotMarketIndexes = new Set();
|
|
72
75
|
this.connection = config.connection;
|
|
73
76
|
this.wallet = config.wallet;
|
|
74
77
|
this.opts = config.opts || anchor_1.AnchorProvider.defaultOptions();
|
|
@@ -78,6 +81,10 @@ class DriftClient {
|
|
|
78
81
|
this.activeSubAccountId = (_c = config.activeSubAccountId) !== null && _c !== void 0 ? _c : 0;
|
|
79
82
|
this.skipLoadUsers = (_d = config.skipLoadUsers) !== null && _d !== void 0 ? _d : false;
|
|
80
83
|
this.txVersion = (_e = config.txVersion) !== null && _e !== void 0 ? _e : 'legacy';
|
|
84
|
+
this.txParams = {
|
|
85
|
+
computeUnits: (_g = (_f = config.txParams) === null || _f === void 0 ? void 0 : _f.computeUnits) !== null && _g !== void 0 ? _g : 600000,
|
|
86
|
+
computeUnitsPrice: (_j = (_h = config.txParams) === null || _h === void 0 ? void 0 : _h.computeUnitsPrice) !== null && _j !== void 0 ? _j : 0,
|
|
87
|
+
};
|
|
81
88
|
if (config.includeDelegates && config.subAccountIds) {
|
|
82
89
|
throw new Error('Can only pass one of includeDelegates or subAccountIds. If you want to specify subaccount ids for multiple authorities, pass authoritySubaccountMap instead');
|
|
83
90
|
}
|
|
@@ -92,16 +99,25 @@ class DriftClient {
|
|
|
92
99
|
: config.subAccountIds
|
|
93
100
|
? new Map([[this.authority.toString(), config.subAccountIds]])
|
|
94
101
|
: new Map();
|
|
95
|
-
this.includeDelegates = (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
:
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
this.includeDelegates = (_k = config.includeDelegates) !== null && _k !== void 0 ? _k : false;
|
|
103
|
+
if (((_l = config.accountSubscription) === null || _l === void 0 ? void 0 : _l.type) === 'polling') {
|
|
104
|
+
this.userAccountSubscriptionConfig = {
|
|
105
|
+
type: 'polling',
|
|
106
|
+
accountLoader: config.accountSubscription.accountLoader,
|
|
107
|
+
};
|
|
108
|
+
this.userStatsAccountSubscriptionConfig = {
|
|
109
|
+
type: 'polling',
|
|
110
|
+
accountLoader: config.accountSubscription.accountLoader,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
this.userAccountSubscriptionConfig = {
|
|
115
|
+
type: 'websocket',
|
|
116
|
+
};
|
|
117
|
+
this.userStatsAccountSubscriptionConfig = {
|
|
118
|
+
type: 'websocket',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
105
121
|
if (config.userStats) {
|
|
106
122
|
this.userStats = new userStats_1.UserStats({
|
|
107
123
|
driftClient: this,
|
|
@@ -116,14 +132,19 @@ class DriftClient {
|
|
|
116
132
|
const noMarketsAndOraclesSpecified = config.perpMarketIndexes === undefined &&
|
|
117
133
|
config.spotMarketIndexes === undefined &&
|
|
118
134
|
config.oracleInfos === undefined;
|
|
119
|
-
if (((
|
|
120
|
-
this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (
|
|
135
|
+
if (((_m = config.accountSubscription) === null || _m === void 0 ? void 0 : _m.type) === 'polling') {
|
|
136
|
+
this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_o = config.perpMarketIndexes) !== null && _o !== void 0 ? _o : [], (_p = config.spotMarketIndexes) !== null && _p !== void 0 ? _p : [], (_q = config.oracleInfos) !== null && _q !== void 0 ? _q : [], noMarketsAndOraclesSpecified);
|
|
121
137
|
}
|
|
122
138
|
else {
|
|
123
|
-
this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (
|
|
139
|
+
this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_r = config.perpMarketIndexes) !== null && _r !== void 0 ? _r : [], (_s = config.spotMarketIndexes) !== null && _s !== void 0 ? _s : [], (_t = config.oracleInfos) !== null && _t !== void 0 ? _t : [], noMarketsAndOraclesSpecified);
|
|
124
140
|
}
|
|
125
141
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
126
|
-
this.txSender =
|
|
142
|
+
this.txSender =
|
|
143
|
+
(_u = config.txSender) !== null && _u !== void 0 ? _u : new retryTxSender_1.RetryTxSender({
|
|
144
|
+
connection: this.connection,
|
|
145
|
+
wallet: this.wallet,
|
|
146
|
+
opts: this.opts,
|
|
147
|
+
});
|
|
127
148
|
}
|
|
128
149
|
getUserMapKey(subAccountId, authority) {
|
|
129
150
|
return `${subAccountId}_${authority.toString()}`;
|
|
@@ -274,7 +295,7 @@ class DriftClient {
|
|
|
274
295
|
const newProgram = new anchor_1.Program(drift_json_1.default, this.program.programId, newProvider);
|
|
275
296
|
this.skipLoadUsers = false;
|
|
276
297
|
// Update provider for txSender with new wallet details
|
|
277
|
-
this.txSender.
|
|
298
|
+
this.txSender.wallet = newWallet;
|
|
278
299
|
this.wallet = newWallet;
|
|
279
300
|
this.provider = newProvider;
|
|
280
301
|
this.program = newProgram;
|
|
@@ -304,7 +325,7 @@ class DriftClient {
|
|
|
304
325
|
this.userStats = new userStats_1.UserStats({
|
|
305
326
|
driftClient: this,
|
|
306
327
|
userStatsAccountPublicKey: this.getUserStatsAccountPublicKey(),
|
|
307
|
-
accountSubscription: this.
|
|
328
|
+
accountSubscription: this.userStatsAccountSubscriptionConfig,
|
|
308
329
|
});
|
|
309
330
|
await this.userStats.subscribe();
|
|
310
331
|
}
|
|
@@ -487,6 +508,27 @@ class DriftClient {
|
|
|
487
508
|
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
488
509
|
return txSig;
|
|
489
510
|
}
|
|
511
|
+
async getUpdateUserMarginTradingEnabledIx(marginTradingEnabled, subAccountId = 0, userAccountPublicKey) {
|
|
512
|
+
const userAccountPublicKeyToUse = userAccountPublicKey ||
|
|
513
|
+
(0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId);
|
|
514
|
+
await this.addUser(subAccountId, this.wallet.publicKey);
|
|
515
|
+
let remainingAccounts;
|
|
516
|
+
try {
|
|
517
|
+
remainingAccounts = this.getRemainingAccounts({
|
|
518
|
+
userAccounts: [this.getUserAccount(subAccountId)],
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
remainingAccounts = [];
|
|
523
|
+
}
|
|
524
|
+
return await this.program.instruction.updateUserMarginTradingEnabled(subAccountId, marginTradingEnabled, {
|
|
525
|
+
accounts: {
|
|
526
|
+
user: userAccountPublicKeyToUse,
|
|
527
|
+
authority: this.wallet.publicKey,
|
|
528
|
+
},
|
|
529
|
+
remainingAccounts,
|
|
530
|
+
});
|
|
531
|
+
}
|
|
490
532
|
async updateUserMarginTradingEnabled(marginTradingEnabled, subAccountId = 0) {
|
|
491
533
|
const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId);
|
|
492
534
|
await this.addUser(subAccountId, this.wallet.publicKey);
|
|
@@ -606,10 +648,16 @@ class DriftClient {
|
|
|
606
648
|
authority = authority !== null && authority !== void 0 ? authority : this.authority;
|
|
607
649
|
const userMapKey = this.getUserMapKey(subAccountId, authority);
|
|
608
650
|
if (!this.users.has(userMapKey)) {
|
|
609
|
-
throw new Error(`
|
|
651
|
+
throw new Error(`DriftClient has no user for user id ${userMapKey}`);
|
|
610
652
|
}
|
|
611
653
|
return this.users.get(userMapKey);
|
|
612
654
|
}
|
|
655
|
+
hasUser(subAccountId, authority) {
|
|
656
|
+
subAccountId = subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId;
|
|
657
|
+
authority = authority !== null && authority !== void 0 ? authority : this.authority;
|
|
658
|
+
const userMapKey = this.getUserMapKey(subAccountId, authority);
|
|
659
|
+
return this.users.has(userMapKey);
|
|
660
|
+
}
|
|
613
661
|
getUsers() {
|
|
614
662
|
// delegate users get added to the end
|
|
615
663
|
return [...this.users.values()]
|
|
@@ -692,6 +740,21 @@ class DriftClient {
|
|
|
692
740
|
amount = typeof amount === 'number' ? new anchor_1.BN(amount) : amount;
|
|
693
741
|
return amount.mul(numericConstants_1.PRICE_PRECISION);
|
|
694
742
|
}
|
|
743
|
+
/**
|
|
744
|
+
* Each drift instruction must include perp and sport market accounts in the ix remaining accounts.
|
|
745
|
+
* Use this function to force a subset of markets to be included in the remaining accounts for every ix
|
|
746
|
+
*
|
|
747
|
+
* @param perpMarketIndexes
|
|
748
|
+
* @param spotMarketIndexes
|
|
749
|
+
*/
|
|
750
|
+
mustIncludeMarketsInIx({ perpMarketIndexes, spotMarketIndexes, }) {
|
|
751
|
+
perpMarketIndexes.forEach((perpMarketIndex) => {
|
|
752
|
+
this.mustIncludePerpMarketIndexes.add(perpMarketIndex);
|
|
753
|
+
});
|
|
754
|
+
spotMarketIndexes.forEach((spotMarketIndex) => {
|
|
755
|
+
this.mustIncludeSpotMarketIndexes.add(spotMarketIndex);
|
|
756
|
+
});
|
|
757
|
+
}
|
|
695
758
|
getRemainingAccounts(params) {
|
|
696
759
|
var _a;
|
|
697
760
|
const { oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap } = this.getRemainingAccountMapsForUsers(params.userAccounts);
|
|
@@ -701,30 +764,7 @@ class DriftClient {
|
|
|
701
764
|
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
702
765
|
// otherwise remove from slot
|
|
703
766
|
if (slot > lastUserSlot) {
|
|
704
|
-
|
|
705
|
-
perpMarketAccountMap.set(marketIndex, {
|
|
706
|
-
pubkey: perpMarketAccount.pubkey,
|
|
707
|
-
isSigner: false,
|
|
708
|
-
isWritable: false,
|
|
709
|
-
});
|
|
710
|
-
oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
|
|
711
|
-
pubkey: perpMarketAccount.amm.oracle,
|
|
712
|
-
isSigner: false,
|
|
713
|
-
isWritable: false,
|
|
714
|
-
});
|
|
715
|
-
const spotMarketAccount = this.getSpotMarketAccount(perpMarketAccount.quoteSpotMarketIndex);
|
|
716
|
-
spotMarketAccountMap.set(perpMarketAccount.quoteSpotMarketIndex, {
|
|
717
|
-
pubkey: spotMarketAccount.pubkey,
|
|
718
|
-
isSigner: false,
|
|
719
|
-
isWritable: false,
|
|
720
|
-
});
|
|
721
|
-
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
722
|
-
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
723
|
-
pubkey: spotMarketAccount.oracle,
|
|
724
|
-
isSigner: false,
|
|
725
|
-
isWritable: false,
|
|
726
|
-
});
|
|
727
|
-
}
|
|
767
|
+
this.addPerpMarketToRemainingAccountMaps(marketIndex, false, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
|
|
728
768
|
}
|
|
729
769
|
else {
|
|
730
770
|
this.perpMarketLastSlotCache.delete(marketIndex);
|
|
@@ -734,19 +774,7 @@ class DriftClient {
|
|
|
734
774
|
// if cache has more recent slot than user positions account slot, add market to remaining accounts
|
|
735
775
|
// otherwise remove from slot
|
|
736
776
|
if (slot > lastUserSlot) {
|
|
737
|
-
|
|
738
|
-
spotMarketAccountMap.set(marketIndex, {
|
|
739
|
-
pubkey: spotMarketAccount.pubkey,
|
|
740
|
-
isSigner: false,
|
|
741
|
-
isWritable: false,
|
|
742
|
-
});
|
|
743
|
-
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
744
|
-
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
745
|
-
pubkey: spotMarketAccount.oracle,
|
|
746
|
-
isSigner: false,
|
|
747
|
-
isWritable: false,
|
|
748
|
-
});
|
|
749
|
-
}
|
|
777
|
+
this.addSpotMarketToRemainingAccountMaps(marketIndex, false, oracleAccountMap, spotMarketAccountMap);
|
|
750
778
|
}
|
|
751
779
|
else {
|
|
752
780
|
this.spotMarketLastSlotCache.delete(marketIndex);
|
|
@@ -754,91 +782,32 @@ class DriftClient {
|
|
|
754
782
|
}
|
|
755
783
|
}
|
|
756
784
|
if (params.readablePerpMarketIndex !== undefined) {
|
|
757
|
-
const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
});
|
|
763
|
-
oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
|
|
764
|
-
pubkey: perpMarketAccount.amm.oracle,
|
|
765
|
-
isSigner: false,
|
|
766
|
-
isWritable: false,
|
|
767
|
-
});
|
|
768
|
-
const spotMarketAccount = this.getSpotMarketAccount(perpMarketAccount.quoteSpotMarketIndex);
|
|
769
|
-
spotMarketAccountMap.set(perpMarketAccount.quoteSpotMarketIndex, {
|
|
770
|
-
pubkey: spotMarketAccount.pubkey,
|
|
771
|
-
isSigner: false,
|
|
772
|
-
isWritable: false,
|
|
773
|
-
});
|
|
774
|
-
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
775
|
-
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
776
|
-
pubkey: spotMarketAccount.oracle,
|
|
777
|
-
isSigner: false,
|
|
778
|
-
isWritable: false,
|
|
779
|
-
});
|
|
785
|
+
const readablePerpMarketIndexes = Array.isArray(params.readablePerpMarketIndex)
|
|
786
|
+
? params.readablePerpMarketIndex
|
|
787
|
+
: [params.readablePerpMarketIndex];
|
|
788
|
+
for (const marketIndex of readablePerpMarketIndexes) {
|
|
789
|
+
this.addPerpMarketToRemainingAccountMaps(marketIndex, false, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
|
|
780
790
|
}
|
|
781
791
|
}
|
|
792
|
+
for (const perpMarketIndex of this.mustIncludePerpMarketIndexes.values()) {
|
|
793
|
+
this.addPerpMarketToRemainingAccountMaps(perpMarketIndex, false, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
|
|
794
|
+
}
|
|
782
795
|
if (params.readableSpotMarketIndexes !== undefined) {
|
|
783
796
|
for (const readableSpotMarketIndex of params.readableSpotMarketIndexes) {
|
|
784
|
-
|
|
785
|
-
spotMarketAccountMap.set(readableSpotMarketIndex, {
|
|
786
|
-
pubkey: spotMarketAccount.pubkey,
|
|
787
|
-
isSigner: false,
|
|
788
|
-
isWritable: false,
|
|
789
|
-
});
|
|
790
|
-
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
791
|
-
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
792
|
-
pubkey: spotMarketAccount.oracle,
|
|
793
|
-
isSigner: false,
|
|
794
|
-
isWritable: false,
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
+
this.addSpotMarketToRemainingAccountMaps(readableSpotMarketIndex, false, oracleAccountMap, spotMarketAccountMap);
|
|
797
798
|
}
|
|
798
799
|
}
|
|
800
|
+
for (const spotMarketIndex of this.mustIncludeSpotMarketIndexes.values()) {
|
|
801
|
+
this.addSpotMarketToRemainingAccountMaps(spotMarketIndex, false, oracleAccountMap, spotMarketAccountMap);
|
|
802
|
+
}
|
|
799
803
|
if (params.writablePerpMarketIndexes !== undefined) {
|
|
800
804
|
for (const writablePerpMarketIndex of params.writablePerpMarketIndexes) {
|
|
801
|
-
|
|
802
|
-
perpMarketAccountMap.set(writablePerpMarketIndex, {
|
|
803
|
-
pubkey: perpMarketAccount.pubkey,
|
|
804
|
-
isSigner: false,
|
|
805
|
-
isWritable: true,
|
|
806
|
-
});
|
|
807
|
-
oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
|
|
808
|
-
pubkey: perpMarketAccount.amm.oracle,
|
|
809
|
-
isSigner: false,
|
|
810
|
-
isWritable: false,
|
|
811
|
-
});
|
|
812
|
-
const spotMarketAccount = this.getSpotMarketAccount(perpMarketAccount.quoteSpotMarketIndex);
|
|
813
|
-
spotMarketAccountMap.set(perpMarketAccount.quoteSpotMarketIndex, {
|
|
814
|
-
pubkey: spotMarketAccount.pubkey,
|
|
815
|
-
isSigner: false,
|
|
816
|
-
isWritable: false,
|
|
817
|
-
});
|
|
818
|
-
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
819
|
-
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
820
|
-
pubkey: spotMarketAccount.oracle,
|
|
821
|
-
isSigner: false,
|
|
822
|
-
isWritable: false,
|
|
823
|
-
});
|
|
824
|
-
}
|
|
805
|
+
this.addPerpMarketToRemainingAccountMaps(writablePerpMarketIndex, true, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
|
|
825
806
|
}
|
|
826
807
|
}
|
|
827
808
|
if (params.writableSpotMarketIndexes !== undefined) {
|
|
828
809
|
for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
|
|
829
|
-
|
|
830
|
-
spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
|
|
831
|
-
pubkey: spotMarketAccount.pubkey,
|
|
832
|
-
isSigner: false,
|
|
833
|
-
isWritable: true,
|
|
834
|
-
});
|
|
835
|
-
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
836
|
-
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
837
|
-
pubkey: spotMarketAccount.oracle,
|
|
838
|
-
isSigner: false,
|
|
839
|
-
isWritable: false,
|
|
840
|
-
});
|
|
841
|
-
}
|
|
810
|
+
this.addSpotMarketToRemainingAccountMaps(writableSpotMarketIndex, true, oracleAccountMap, spotMarketAccountMap);
|
|
842
811
|
}
|
|
843
812
|
}
|
|
844
813
|
return [
|
|
@@ -847,6 +816,35 @@ class DriftClient {
|
|
|
847
816
|
...perpMarketAccountMap.values(),
|
|
848
817
|
];
|
|
849
818
|
}
|
|
819
|
+
addPerpMarketToRemainingAccountMaps(marketIndex, writable, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap) {
|
|
820
|
+
const perpMarketAccount = this.getPerpMarketAccount(marketIndex);
|
|
821
|
+
perpMarketAccountMap.set(marketIndex, {
|
|
822
|
+
pubkey: perpMarketAccount.pubkey,
|
|
823
|
+
isSigner: false,
|
|
824
|
+
isWritable: writable,
|
|
825
|
+
});
|
|
826
|
+
oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
|
|
827
|
+
pubkey: perpMarketAccount.amm.oracle,
|
|
828
|
+
isSigner: false,
|
|
829
|
+
isWritable: false,
|
|
830
|
+
});
|
|
831
|
+
this.addSpotMarketToRemainingAccountMaps(perpMarketAccount.quoteSpotMarketIndex, false, oracleAccountMap, spotMarketAccountMap);
|
|
832
|
+
}
|
|
833
|
+
addSpotMarketToRemainingAccountMaps(marketIndex, writable, oracleAccountMap, spotMarketAccountMap) {
|
|
834
|
+
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
835
|
+
spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
|
|
836
|
+
pubkey: spotMarketAccount.pubkey,
|
|
837
|
+
isSigner: false,
|
|
838
|
+
isWritable: writable,
|
|
839
|
+
});
|
|
840
|
+
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
841
|
+
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
842
|
+
pubkey: spotMarketAccount.oracle,
|
|
843
|
+
isSigner: false,
|
|
844
|
+
isWritable: false,
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
}
|
|
850
848
|
getRemainingAccountMapsForUsers(userAccounts) {
|
|
851
849
|
const oracleAccountMap = new Map();
|
|
852
850
|
const spotMarketAccountMap = new Map();
|
|
@@ -854,63 +852,16 @@ class DriftClient {
|
|
|
854
852
|
for (const userAccount of userAccounts) {
|
|
855
853
|
for (const spotPosition of userAccount.spotPositions) {
|
|
856
854
|
if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
|
|
857
|
-
|
|
858
|
-
spotMarketAccountMap.set(spotPosition.marketIndex, {
|
|
859
|
-
pubkey: spotMarket.pubkey,
|
|
860
|
-
isSigner: false,
|
|
861
|
-
isWritable: false,
|
|
862
|
-
});
|
|
863
|
-
if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
864
|
-
oracleAccountMap.set(spotMarket.oracle.toString(), {
|
|
865
|
-
pubkey: spotMarket.oracle,
|
|
866
|
-
isSigner: false,
|
|
867
|
-
isWritable: false,
|
|
868
|
-
});
|
|
869
|
-
}
|
|
855
|
+
this.addSpotMarketToRemainingAccountMaps(spotPosition.marketIndex, false, oracleAccountMap, spotMarketAccountMap);
|
|
870
856
|
if (!spotPosition.openAsks.eq(numericConstants_1.ZERO) ||
|
|
871
857
|
!spotPosition.openBids.eq(numericConstants_1.ZERO)) {
|
|
872
|
-
|
|
873
|
-
spotMarketAccountMap.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, {
|
|
874
|
-
pubkey: quoteSpotMarket.pubkey,
|
|
875
|
-
isSigner: false,
|
|
876
|
-
isWritable: false,
|
|
877
|
-
});
|
|
878
|
-
if (!quoteSpotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
879
|
-
oracleAccountMap.set(quoteSpotMarket.oracle.toString(), {
|
|
880
|
-
pubkey: quoteSpotMarket.oracle,
|
|
881
|
-
isSigner: false,
|
|
882
|
-
isWritable: false,
|
|
883
|
-
});
|
|
884
|
-
}
|
|
858
|
+
this.addSpotMarketToRemainingAccountMaps(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, false, oracleAccountMap, spotMarketAccountMap);
|
|
885
859
|
}
|
|
886
860
|
}
|
|
887
861
|
}
|
|
888
862
|
for (const position of userAccount.perpPositions) {
|
|
889
863
|
if (!(0, position_1.positionIsAvailable)(position)) {
|
|
890
|
-
|
|
891
|
-
perpMarketAccountMap.set(position.marketIndex, {
|
|
892
|
-
pubkey: perpMarketAccount.pubkey,
|
|
893
|
-
isWritable: false,
|
|
894
|
-
isSigner: false,
|
|
895
|
-
});
|
|
896
|
-
oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
|
|
897
|
-
pubkey: perpMarketAccount.amm.oracle,
|
|
898
|
-
isWritable: false,
|
|
899
|
-
isSigner: false,
|
|
900
|
-
});
|
|
901
|
-
const spotMarketAccount = this.getSpotMarketAccount(perpMarketAccount.quoteSpotMarketIndex);
|
|
902
|
-
spotMarketAccountMap.set(perpMarketAccount.quoteSpotMarketIndex, {
|
|
903
|
-
pubkey: spotMarketAccount.pubkey,
|
|
904
|
-
isSigner: false,
|
|
905
|
-
isWritable: false,
|
|
906
|
-
});
|
|
907
|
-
if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
|
|
908
|
-
oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
|
|
909
|
-
pubkey: spotMarketAccount.oracle,
|
|
910
|
-
isSigner: false,
|
|
911
|
-
isWritable: false,
|
|
912
|
-
});
|
|
913
|
-
}
|
|
864
|
+
this.addPerpMarketToRemainingAccountMaps(position.marketIndex, false, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
|
|
914
865
|
}
|
|
915
866
|
}
|
|
916
867
|
}
|
|
@@ -1064,7 +1015,7 @@ class DriftClient {
|
|
|
1064
1015
|
return (0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, associatedTokenAddress, this.wallet.publicKey, tokenMintAddress);
|
|
1065
1016
|
}
|
|
1066
1017
|
/**
|
|
1067
|
-
* Creates the
|
|
1018
|
+
* Creates the User account for a user, and deposits some initial collateral
|
|
1068
1019
|
* @param amount
|
|
1069
1020
|
* @param userTokenAccount
|
|
1070
1021
|
* @param marketIndex
|
|
@@ -1349,6 +1300,19 @@ class DriftClient {
|
|
|
1349
1300
|
remainingAccounts: remainingAccounts,
|
|
1350
1301
|
});
|
|
1351
1302
|
}
|
|
1303
|
+
getQuoteValuePerLpShare(marketIndex) {
|
|
1304
|
+
const perpMarketAccount = this.getPerpMarketAccount(marketIndex);
|
|
1305
|
+
const openBids = anchor_1.BN.max(perpMarketAccount.amm.baseAssetReserve.sub(perpMarketAccount.amm.minBaseAssetReserve), numericConstants_1.ZERO);
|
|
1306
|
+
const openAsks = anchor_1.BN.max(perpMarketAccount.amm.maxBaseAssetReserve.sub(perpMarketAccount.amm.baseAssetReserve), numericConstants_1.ZERO);
|
|
1307
|
+
const oraclePriceData = this.getOracleDataForPerpMarket(marketIndex);
|
|
1308
|
+
const maxOpenBidsAsks = anchor_1.BN.max(openBids, openAsks);
|
|
1309
|
+
const quoteValuePerLpShare = maxOpenBidsAsks
|
|
1310
|
+
.mul(oraclePriceData.price)
|
|
1311
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
1312
|
+
.div(numericConstants_1.PRICE_PRECISION)
|
|
1313
|
+
.div(perpMarketAccount.amm.sqrtK);
|
|
1314
|
+
return quoteValuePerLpShare;
|
|
1315
|
+
}
|
|
1352
1316
|
/**
|
|
1353
1317
|
* @deprecated use {@link placePerpOrder} or {@link placeAndTakePerpOrder} instead
|
|
1354
1318
|
*/
|
|
@@ -1608,23 +1572,45 @@ class DriftClient {
|
|
|
1608
1572
|
});
|
|
1609
1573
|
}
|
|
1610
1574
|
async cancelAndPlaceOrders(cancelOrderParams, placeOrderParams, txParams) {
|
|
1611
|
-
const
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1575
|
+
const ixs = [
|
|
1576
|
+
await this.getCancelOrdersIx(cancelOrderParams.marketType, cancelOrderParams.marketIndex, cancelOrderParams.direction),
|
|
1577
|
+
await this.getPlaceOrdersIx(placeOrderParams),
|
|
1578
|
+
];
|
|
1579
|
+
const tx = await this.buildTransaction(ixs, txParams);
|
|
1580
|
+
const { txSig } = await this.sendTransaction(tx, [], this.opts);
|
|
1581
|
+
return txSig;
|
|
1582
|
+
}
|
|
1583
|
+
async placeOrders(params, txParams) {
|
|
1584
|
+
const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getPlaceOrdersIx(params), txParams), [], this.opts);
|
|
1585
|
+
return txSig;
|
|
1586
|
+
}
|
|
1587
|
+
async getPlaceOrdersIx(params) {
|
|
1588
|
+
const userAccountPublicKey = await this.getUserAccountPublicKey();
|
|
1589
|
+
const readablePerpMarketIndex = [];
|
|
1590
|
+
const readableSpotMarketIndexes = [];
|
|
1591
|
+
for (const param of params) {
|
|
1592
|
+
if ((0, types_1.isVariant)(param.marketType, 'perp')) {
|
|
1593
|
+
readablePerpMarketIndex.push(param.marketIndex);
|
|
1620
1594
|
}
|
|
1621
1595
|
else {
|
|
1622
|
-
|
|
1596
|
+
readableSpotMarketIndexes.push(param.marketIndex);
|
|
1623
1597
|
}
|
|
1624
|
-
tx.add(ix);
|
|
1625
1598
|
}
|
|
1626
|
-
const
|
|
1627
|
-
|
|
1599
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
1600
|
+
userAccounts: [this.getUserAccount()],
|
|
1601
|
+
readablePerpMarketIndex,
|
|
1602
|
+
readableSpotMarketIndexes,
|
|
1603
|
+
useMarketLastSlotCache: true,
|
|
1604
|
+
});
|
|
1605
|
+
return await this.program.instruction.placeOrders(params, {
|
|
1606
|
+
accounts: {
|
|
1607
|
+
state: await this.getStatePublicKey(),
|
|
1608
|
+
user: userAccountPublicKey,
|
|
1609
|
+
userStats: this.getUserStatsAccountPublicKey(),
|
|
1610
|
+
authority: this.wallet.publicKey,
|
|
1611
|
+
},
|
|
1612
|
+
remainingAccounts,
|
|
1613
|
+
});
|
|
1628
1614
|
}
|
|
1629
1615
|
async fillPerpOrder(userAccountPublicKey, user, order, makerInfo, referrerInfo, txParams) {
|
|
1630
1616
|
const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getFillPerpOrderIx(userAccountPublicKey, user, order, makerInfo, referrerInfo), txParams), [], this.opts);
|
|
@@ -1960,6 +1946,25 @@ class DriftClient {
|
|
|
1960
1946
|
* @param txParams
|
|
1961
1947
|
*/
|
|
1962
1948
|
async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, }) {
|
|
1949
|
+
const { ixs, lookupTables } = await this.getJupiterSwapIx({
|
|
1950
|
+
jupiterClient,
|
|
1951
|
+
outMarketIndex,
|
|
1952
|
+
inMarketIndex,
|
|
1953
|
+
outAssociatedTokenAccount,
|
|
1954
|
+
inAssociatedTokenAccount,
|
|
1955
|
+
amount,
|
|
1956
|
+
slippageBps,
|
|
1957
|
+
swapMode,
|
|
1958
|
+
route,
|
|
1959
|
+
reduceOnly,
|
|
1960
|
+
});
|
|
1961
|
+
const tx = (await this.buildTransaction(ixs, txParams, 0, lookupTables));
|
|
1962
|
+
const { txSig, slot } = await this.sendTransaction(tx);
|
|
1963
|
+
this.spotMarketLastSlotCache.set(outMarketIndex, slot);
|
|
1964
|
+
this.spotMarketLastSlotCache.set(inMarketIndex, slot);
|
|
1965
|
+
return txSig;
|
|
1966
|
+
}
|
|
1967
|
+
async getJupiterSwapIx({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, userAccountPublicKey, }) {
|
|
1963
1968
|
const outMarket = this.getSpotMarketAccount(outMarketIndex);
|
|
1964
1969
|
const inMarket = this.getSpotMarketAccount(inMarketIndex);
|
|
1965
1970
|
if (!route) {
|
|
@@ -2010,18 +2015,15 @@ class DriftClient {
|
|
|
2010
2015
|
inTokenAccount: inAssociatedTokenAccount,
|
|
2011
2016
|
outTokenAccount: outAssociatedTokenAccount,
|
|
2012
2017
|
reduceOnly,
|
|
2018
|
+
userAccountPublicKey,
|
|
2013
2019
|
});
|
|
2014
|
-
const
|
|
2020
|
+
const ixs = [
|
|
2015
2021
|
...preInstructions,
|
|
2016
2022
|
beginSwapIx,
|
|
2017
2023
|
...jupiterInstructions,
|
|
2018
2024
|
endSwapIx,
|
|
2019
2025
|
];
|
|
2020
|
-
|
|
2021
|
-
const { txSig, slot } = await this.sendTransaction(tx);
|
|
2022
|
-
this.spotMarketLastSlotCache.set(outMarketIndex, slot);
|
|
2023
|
-
this.spotMarketLastSlotCache.set(inMarketIndex, slot);
|
|
2024
|
-
return txSig;
|
|
2026
|
+
return { ixs, lookupTables };
|
|
2025
2027
|
}
|
|
2026
2028
|
/**
|
|
2027
2029
|
* Get the drift begin_swap and end_swap instructions
|
|
@@ -2032,11 +2034,14 @@ class DriftClient {
|
|
|
2032
2034
|
* @param inTokenAccount the token account to move the tokens being sold
|
|
2033
2035
|
* @param outTokenAccount the token account to receive the tokens being bought
|
|
2034
2036
|
* @param limitPrice the limit price of the swap
|
|
2037
|
+
* @param reduceOnly
|
|
2038
|
+
* @param userAccountPublicKey optional, specify a custom userAccountPublicKey to use instead of getting the current user account; can be helpful if the account is being created within the current tx
|
|
2035
2039
|
*/
|
|
2036
|
-
async getSwapIx({ outMarketIndex, inMarketIndex, amountIn, inTokenAccount, outTokenAccount, limitPrice, reduceOnly, }) {
|
|
2037
|
-
const
|
|
2040
|
+
async getSwapIx({ outMarketIndex, inMarketIndex, amountIn, inTokenAccount, outTokenAccount, limitPrice, reduceOnly, userAccountPublicKey, }) {
|
|
2041
|
+
const userAccountPublicKeyToUse = userAccountPublicKey || (await this.getUserAccountPublicKey());
|
|
2042
|
+
const userAccounts = this.hasUser() ? [this.getUserAccount()] : [];
|
|
2038
2043
|
const remainingAccounts = this.getRemainingAccounts({
|
|
2039
|
-
userAccounts
|
|
2044
|
+
userAccounts,
|
|
2040
2045
|
writableSpotMarketIndexes: [outMarketIndex, inMarketIndex],
|
|
2041
2046
|
});
|
|
2042
2047
|
const outSpotMarket = this.getSpotMarketAccount(outMarketIndex);
|
|
@@ -2044,7 +2049,7 @@ class DriftClient {
|
|
|
2044
2049
|
const beginSwapIx = await this.program.instruction.beginSwap(inMarketIndex, outMarketIndex, amountIn, {
|
|
2045
2050
|
accounts: {
|
|
2046
2051
|
state: await this.getStatePublicKey(),
|
|
2047
|
-
user:
|
|
2052
|
+
user: userAccountPublicKeyToUse,
|
|
2048
2053
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
2049
2054
|
authority: this.authority,
|
|
2050
2055
|
outSpotMarketVault: outSpotMarket.vault,
|
|
@@ -2060,7 +2065,7 @@ class DriftClient {
|
|
|
2060
2065
|
const endSwapIx = await this.program.instruction.endSwap(inMarketIndex, outMarketIndex, limitPrice !== null && limitPrice !== void 0 ? limitPrice : null, reduceOnly !== null && reduceOnly !== void 0 ? reduceOnly : null, {
|
|
2061
2066
|
accounts: {
|
|
2062
2067
|
state: await this.getStatePublicKey(),
|
|
2063
|
-
user:
|
|
2068
|
+
user: userAccountPublicKeyToUse,
|
|
2064
2069
|
userStats: this.getUserStatsAccountPublicKey(),
|
|
2065
2070
|
authority: this.authority,
|
|
2066
2071
|
outSpotMarketVault: outSpotMarket.vault,
|
|
@@ -2075,6 +2080,40 @@ class DriftClient {
|
|
|
2075
2080
|
});
|
|
2076
2081
|
return { beginSwapIx, endSwapIx };
|
|
2077
2082
|
}
|
|
2083
|
+
async stakeForMSOL({ amount }) {
|
|
2084
|
+
const ixs = await this.getStakeForMSOLIx({ amount });
|
|
2085
|
+
const tx = await this.buildTransaction(ixs);
|
|
2086
|
+
return this.sendTransaction(tx);
|
|
2087
|
+
}
|
|
2088
|
+
async getStakeForMSOLIx({ amount, userAccountPublicKey, }) {
|
|
2089
|
+
const wSOLMint = this.getSpotMarketAccount(1).mint;
|
|
2090
|
+
const mSOLAccount = await this.getAssociatedTokenAccount(2);
|
|
2091
|
+
const wSOLAccount = await this.getAssociatedTokenAccount(1, false);
|
|
2092
|
+
const wSOLAccountExists = await this.checkIfAccountExists(wSOLAccount);
|
|
2093
|
+
const closeWSOLIx = (0, spl_token_1.createCloseAccountInstruction)(wSOLAccount, this.wallet.publicKey, this.wallet.publicKey);
|
|
2094
|
+
const createWSOLIx = await this.createAssociatedTokenAccountIdempotentInstruction(wSOLAccount, this.wallet.publicKey, this.wallet.publicKey, wSOLMint);
|
|
2095
|
+
const { beginSwapIx, endSwapIx } = await this.getSwapIx({
|
|
2096
|
+
inMarketIndex: 1,
|
|
2097
|
+
outMarketIndex: 2,
|
|
2098
|
+
amountIn: amount,
|
|
2099
|
+
inTokenAccount: wSOLAccount,
|
|
2100
|
+
outTokenAccount: mSOLAccount,
|
|
2101
|
+
userAccountPublicKey,
|
|
2102
|
+
});
|
|
2103
|
+
const program = (0, marinade_1.getMarinadeFinanceProgram)(this.provider);
|
|
2104
|
+
const depositIx = await (0, marinade_1.getMarinadeDepositIx)({
|
|
2105
|
+
program,
|
|
2106
|
+
mSOLAccount: mSOLAccount,
|
|
2107
|
+
transferFrom: this.wallet.publicKey,
|
|
2108
|
+
amount,
|
|
2109
|
+
});
|
|
2110
|
+
const ixs = [];
|
|
2111
|
+
if (!wSOLAccountExists) {
|
|
2112
|
+
ixs.push(createWSOLIx);
|
|
2113
|
+
}
|
|
2114
|
+
ixs.push(beginSwapIx, closeWSOLIx, depositIx, createWSOLIx, endSwapIx);
|
|
2115
|
+
return ixs;
|
|
2116
|
+
}
|
|
2078
2117
|
async triggerOrder(userAccountPublicKey, user, order, txParams) {
|
|
2079
2118
|
const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getTriggerOrderIx(userAccountPublicKey, user, order), txParams), [], this.opts);
|
|
2080
2119
|
return txSig;
|
|
@@ -3049,13 +3088,13 @@ class DriftClient {
|
|
|
3049
3088
|
async buildTransaction(instructions, txParams, txVersion, lookupTables) {
|
|
3050
3089
|
var _a, _b;
|
|
3051
3090
|
const allIx = [];
|
|
3052
|
-
const computeUnits = (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a :
|
|
3091
|
+
const computeUnits = (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : this.txParams.computeUnits;
|
|
3053
3092
|
if (computeUnits !== 200000) {
|
|
3054
3093
|
allIx.push(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
3055
3094
|
units: computeUnits,
|
|
3056
3095
|
}));
|
|
3057
3096
|
}
|
|
3058
|
-
const computeUnitsPrice = (_b = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) !== null && _b !== void 0 ? _b :
|
|
3097
|
+
const computeUnitsPrice = (_b = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) !== null && _b !== void 0 ? _b : this.txParams.computeUnitsPrice;
|
|
3059
3098
|
if (computeUnitsPrice !== 0) {
|
|
3060
3099
|
allIx.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
3061
3100
|
microLamports: computeUnitsPrice,
|