@drift-labs/sdk 2.21.0-beta.0 → 2.21.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dlob/DLOB.js +6 -2
- package/lib/driftClient.d.ts +4 -3
- package/lib/driftClient.js +26 -5
- package/lib/idl/drift.json +58 -1
- package/lib/tx/retryTxSender.js +2 -2
- package/lib/types.d.ts +1 -1
- package/lib/user.js +1 -1
- package/lib/userMap/userMap.d.ts +1 -0
- package/lib/userMap/userMap.js +41 -0
- package/lib/userMap/userStatsMap.d.ts +1 -0
- package/lib/userMap/userStatsMap.js +19 -0
- package/package.json +1 -1
- package/src/assert/assert.js +9 -0
- package/src/dlob/DLOB.ts +4 -0
- package/src/driftClient.ts +34 -5
- package/src/idl/drift.json +58 -1
- package/src/token/index.js +38 -0
- package/src/tx/retryTxSender.ts +3 -2
- package/src/types.ts +1 -1
- package/src/user.ts +1 -1
- package/src/userMap/userMap.ts +52 -1
- package/src/userMap/userStatsMap.ts +32 -1
- package/src/util/computeUnits.js +27 -0
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
package/lib/dlob/DLOB.js
CHANGED
|
@@ -633,8 +633,10 @@ class DLOB {
|
|
|
633
633
|
* @returns
|
|
634
634
|
*/
|
|
635
635
|
*getMakerLimitAsks(marketIndex, slot, marketType, oraclePriceData, fallbackBid) {
|
|
636
|
+
const isPerpMarket = (0, __1.isVariant)(marketType, 'perp');
|
|
636
637
|
for (const node of this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
|
|
637
|
-
if (
|
|
638
|
+
if (isPerpMarket &&
|
|
639
|
+
fallbackBid &&
|
|
638
640
|
node.getPrice(oraclePriceData, slot).lte(fallbackBid)) {
|
|
639
641
|
continue;
|
|
640
642
|
}
|
|
@@ -668,8 +670,10 @@ class DLOB {
|
|
|
668
670
|
* @returns
|
|
669
671
|
*/
|
|
670
672
|
*getMakerLimitBids(marketIndex, slot, marketType, oraclePriceData, fallbackAsk) {
|
|
673
|
+
const isPerpMarket = (0, __1.isVariant)(marketType, 'perp');
|
|
671
674
|
for (const node of this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData)) {
|
|
672
|
-
if (
|
|
675
|
+
if (isPerpMarket &&
|
|
676
|
+
fallbackAsk &&
|
|
673
677
|
node.getPrice(oraclePriceData, slot).gte(fallbackAsk)) {
|
|
674
678
|
continue;
|
|
675
679
|
}
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -145,7 +145,7 @@ export declare class DriftClient {
|
|
|
145
145
|
* @param fromSubAccountId
|
|
146
146
|
* @returns
|
|
147
147
|
*/
|
|
148
|
-
initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
|
|
148
|
+
initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<[TransactionSignature, PublicKey]>;
|
|
149
149
|
initializeUserAccountForDevnet(subAccountId: number, name: string, marketIndex: number, tokenFaucet: TokenFaucet, amount: BN, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
|
|
150
150
|
withdraw(amount: BN, marketIndex: number, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionSignature>;
|
|
151
151
|
getWithdrawIx(amount: BN, marketIndex: number, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionInstruction>;
|
|
@@ -191,6 +191,7 @@ export declare class DriftClient {
|
|
|
191
191
|
getCancelOrdersIx(marketType: MarketType | null, marketIndex: number | null, direction: PositionDirection | null): Promise<TransactionInstruction>;
|
|
192
192
|
fillPerpOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Pick<Order, 'marketIndex' | 'orderId'>, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
|
193
193
|
getFillPerpOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Pick<Order, 'marketIndex' | 'orderId'>, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
|
|
194
|
+
getRevertFillIx(): Promise<TransactionInstruction>;
|
|
194
195
|
placeSpotOrder(orderParams: OptionalOrderParams, txParams?: TxParams): Promise<TransactionSignature>;
|
|
195
196
|
getPlaceSpotOrderIx(orderParams: OptionalOrderParams): Promise<TransactionInstruction>;
|
|
196
197
|
fillSpotOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Order, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
|
@@ -201,8 +202,8 @@ export declare class DriftClient {
|
|
|
201
202
|
getTriggerOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order): Promise<TransactionInstruction>;
|
|
202
203
|
forceCancelOrders(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
|
|
203
204
|
getForceCancelOrdersIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
updateUserIdle(userAccountPublicKey: PublicKey, user: UserAccount, txParams?: TxParams): Promise<TransactionSignature>;
|
|
206
|
+
getUpdateUserIdleIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<TransactionInstruction>;
|
|
206
207
|
placeAndTakePerpOrder(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
|
207
208
|
getPlaceAndTakePerpOrderIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo | MakerInfo[], referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
|
|
208
209
|
placeAndMakePerpOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<TransactionSignature>;
|
package/lib/driftClient.js
CHANGED
|
@@ -820,12 +820,21 @@ class DriftClient {
|
|
|
820
820
|
* @param fromSubAccountId
|
|
821
821
|
* @returns
|
|
822
822
|
*/
|
|
823
|
-
async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, fromSubAccountId, referrerInfo) {
|
|
823
|
+
async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, fromSubAccountId, referrerInfo, txParams) {
|
|
824
|
+
var _a;
|
|
824
825
|
const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
|
|
825
826
|
const additionalSigners = [];
|
|
826
827
|
const spotMarket = this.getSpotMarketAccount(marketIndex);
|
|
827
828
|
const isSolMarket = spotMarket.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
|
|
828
829
|
const tx = new web3_js_1.Transaction();
|
|
830
|
+
tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
|
|
831
|
+
units: (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : 600000,
|
|
832
|
+
}));
|
|
833
|
+
if (txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) {
|
|
834
|
+
tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
|
|
835
|
+
microLamports: txParams.computeUnitsPrice,
|
|
836
|
+
}));
|
|
837
|
+
}
|
|
829
838
|
const authority = this.wallet.publicKey;
|
|
830
839
|
const createWSOLTokenAccount = isSolMarket && userTokenAccount.equals(authority);
|
|
831
840
|
if (createWSOLTokenAccount) {
|
|
@@ -1357,6 +1366,18 @@ class DriftClient {
|
|
|
1357
1366
|
remainingAccounts,
|
|
1358
1367
|
});
|
|
1359
1368
|
}
|
|
1369
|
+
async getRevertFillIx() {
|
|
1370
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1371
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
1372
|
+
return this.program.instruction.revertFill({
|
|
1373
|
+
accounts: {
|
|
1374
|
+
state: await this.getStatePublicKey(),
|
|
1375
|
+
filler: fillerPublicKey,
|
|
1376
|
+
fillerStats: fillerStatsPublicKey,
|
|
1377
|
+
authority: this.wallet.publicKey,
|
|
1378
|
+
},
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1360
1381
|
async placeSpotOrder(orderParams, txParams) {
|
|
1361
1382
|
const { txSig, slot } = await this.sendTransaction((0, utils_1.wrapInTx)(await this.getPlaceSpotOrderIx(orderParams), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
|
|
1362
1383
|
this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
|
|
@@ -1592,16 +1613,16 @@ class DriftClient {
|
|
|
1592
1613
|
remainingAccounts,
|
|
1593
1614
|
});
|
|
1594
1615
|
}
|
|
1595
|
-
async
|
|
1596
|
-
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.
|
|
1616
|
+
async updateUserIdle(userAccountPublicKey, user, txParams) {
|
|
1617
|
+
const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateUserIdleIx(userAccountPublicKey, user), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice), [], this.opts);
|
|
1597
1618
|
return txSig;
|
|
1598
1619
|
}
|
|
1599
|
-
async
|
|
1620
|
+
async getUpdateUserIdleIx(userAccountPublicKey, userAccount) {
|
|
1600
1621
|
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
1601
1622
|
const remainingAccounts = this.getRemainingAccounts({
|
|
1602
1623
|
userAccounts: [userAccount],
|
|
1603
1624
|
});
|
|
1604
|
-
return await this.program.instruction.
|
|
1625
|
+
return await this.program.instruction.updateUserIdle({
|
|
1605
1626
|
accounts: {
|
|
1606
1627
|
state: await this.getStatePublicKey(),
|
|
1607
1628
|
filler: fillerPublicKey,
|
package/lib/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.21.0-beta.
|
|
2
|
+
"version": "2.21.0-beta.2",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -909,6 +909,32 @@
|
|
|
909
909
|
}
|
|
910
910
|
]
|
|
911
911
|
},
|
|
912
|
+
{
|
|
913
|
+
"name": "revertFill",
|
|
914
|
+
"accounts": [
|
|
915
|
+
{
|
|
916
|
+
"name": "state",
|
|
917
|
+
"isMut": false,
|
|
918
|
+
"isSigner": false
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
"name": "authority",
|
|
922
|
+
"isMut": false,
|
|
923
|
+
"isSigner": true
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
"name": "filler",
|
|
927
|
+
"isMut": true,
|
|
928
|
+
"isSigner": false
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"name": "fillerStats",
|
|
932
|
+
"isMut": true,
|
|
933
|
+
"isSigner": false
|
|
934
|
+
}
|
|
935
|
+
],
|
|
936
|
+
"args": []
|
|
937
|
+
},
|
|
912
938
|
{
|
|
913
939
|
"name": "fillSpotOrder",
|
|
914
940
|
"accounts": [
|
|
@@ -1023,6 +1049,32 @@
|
|
|
1023
1049
|
],
|
|
1024
1050
|
"args": []
|
|
1025
1051
|
},
|
|
1052
|
+
{
|
|
1053
|
+
"name": "updateUserIdle",
|
|
1054
|
+
"accounts": [
|
|
1055
|
+
{
|
|
1056
|
+
"name": "state",
|
|
1057
|
+
"isMut": false,
|
|
1058
|
+
"isSigner": false
|
|
1059
|
+
},
|
|
1060
|
+
{
|
|
1061
|
+
"name": "authority",
|
|
1062
|
+
"isMut": false,
|
|
1063
|
+
"isSigner": true
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
"name": "filler",
|
|
1067
|
+
"isMut": true,
|
|
1068
|
+
"isSigner": false
|
|
1069
|
+
},
|
|
1070
|
+
{
|
|
1071
|
+
"name": "user",
|
|
1072
|
+
"isMut": true,
|
|
1073
|
+
"isSigner": false
|
|
1074
|
+
}
|
|
1075
|
+
],
|
|
1076
|
+
"args": []
|
|
1077
|
+
},
|
|
1026
1078
|
{
|
|
1027
1079
|
"name": "settlePnl",
|
|
1028
1080
|
"accounts": [
|
|
@@ -8742,6 +8794,11 @@
|
|
|
8742
8794
|
"code": 6238,
|
|
8743
8795
|
"name": "UserNotInactive",
|
|
8744
8796
|
"msg": "User Not Inactive"
|
|
8797
|
+
},
|
|
8798
|
+
{
|
|
8799
|
+
"code": 6239,
|
|
8800
|
+
"name": "RevertFill",
|
|
8801
|
+
"msg": "RevertFill"
|
|
8745
8802
|
}
|
|
8746
8803
|
]
|
|
8747
8804
|
}
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -31,12 +31,12 @@ class RetryTxSender {
|
|
|
31
31
|
async prepareTx(tx, additionalSigners, opts) {
|
|
32
32
|
tx.feePayer = this.provider.wallet.publicKey;
|
|
33
33
|
tx.recentBlockhash = (await this.provider.connection.getRecentBlockhash(opts.preflightCommitment)).blockhash;
|
|
34
|
-
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
35
34
|
additionalSigners
|
|
36
35
|
.filter((s) => s !== undefined)
|
|
37
36
|
.forEach((kp) => {
|
|
38
|
-
|
|
37
|
+
tx.partialSign(kp);
|
|
39
38
|
});
|
|
39
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
40
40
|
return signedTx;
|
|
41
41
|
}
|
|
42
42
|
async sendVersionedTransaction(ixs, lookupTableAccounts, additionalSigners, opts) {
|
package/lib/types.d.ts
CHANGED
package/lib/user.js
CHANGED
|
@@ -1214,7 +1214,7 @@ class User {
|
|
|
1214
1214
|
}
|
|
1215
1215
|
canMakeIdle(slot, slotsBeforeIdle) {
|
|
1216
1216
|
const userAccount = this.getUserAccount();
|
|
1217
|
-
if (userAccount.
|
|
1217
|
+
if (userAccount.idle) {
|
|
1218
1218
|
return false;
|
|
1219
1219
|
}
|
|
1220
1220
|
const userLastActiveSlot = userAccount.lastActiveSlot;
|
package/lib/userMap/userMap.d.ts
CHANGED
package/lib/userMap/userMap.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.UserMap = void 0;
|
|
4
7
|
const __1 = require("..");
|
|
5
8
|
const web3_js_1 = require("@solana/web3.js");
|
|
9
|
+
const bs58_1 = __importDefault(require("bs58"));
|
|
6
10
|
class UserMap {
|
|
7
11
|
constructor(driftClient, accountSubscription) {
|
|
8
12
|
this.userMap = new Map();
|
|
@@ -131,5 +135,42 @@ class UserMap {
|
|
|
131
135
|
size() {
|
|
132
136
|
return this.userMap.size;
|
|
133
137
|
}
|
|
138
|
+
async sync(includeIdle = true) {
|
|
139
|
+
let filters = undefined;
|
|
140
|
+
if (!includeIdle) {
|
|
141
|
+
filters = [
|
|
142
|
+
{
|
|
143
|
+
memcmp: {
|
|
144
|
+
offset: 4350,
|
|
145
|
+
bytes: bs58_1.default.encode(Uint8Array.from([0])),
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
const programAccounts = await this.driftClient.connection.getProgramAccounts(this.driftClient.program.programId, {
|
|
151
|
+
commitment: this.driftClient.connection.commitment,
|
|
152
|
+
filters: [
|
|
153
|
+
{
|
|
154
|
+
memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
|
|
155
|
+
},
|
|
156
|
+
...(Array.isArray(filters) ? filters : []),
|
|
157
|
+
],
|
|
158
|
+
});
|
|
159
|
+
const programAccountMap = new Map();
|
|
160
|
+
for (const programAccount of programAccounts) {
|
|
161
|
+
programAccountMap.set(programAccount.pubkey.toString(), programAccount.account);
|
|
162
|
+
}
|
|
163
|
+
for (const key of programAccountMap.keys()) {
|
|
164
|
+
if (!this.has(key)) {
|
|
165
|
+
await this.addPubkey(new web3_js_1.PublicKey(key));
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
for (const [key, user] of this.userMap.entries()) {
|
|
169
|
+
if (!programAccountMap.has(key)) {
|
|
170
|
+
await user.unsubscribe();
|
|
171
|
+
this.userMap.delete(key);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
134
175
|
}
|
|
135
176
|
exports.UserMap = UserMap;
|
|
@@ -137,5 +137,24 @@ class UserStatsMap {
|
|
|
137
137
|
size() {
|
|
138
138
|
return this.userStatsMap.size;
|
|
139
139
|
}
|
|
140
|
+
async sync() {
|
|
141
|
+
const programAccounts = await this.driftClient.connection.getProgramAccounts(this.driftClient.program.programId, {
|
|
142
|
+
commitment: this.driftClient.connection.commitment,
|
|
143
|
+
filters: [
|
|
144
|
+
{
|
|
145
|
+
memcmp: this.driftClient.program.coder.accounts.memcmp('UserStats'),
|
|
146
|
+
},
|
|
147
|
+
],
|
|
148
|
+
});
|
|
149
|
+
const programAccountMap = new Map();
|
|
150
|
+
for (const programAccount of programAccounts) {
|
|
151
|
+
programAccountMap.set(new web3_js_1.PublicKey(programAccount.account.data.slice(8, 40)).toString(), programAccount.account);
|
|
152
|
+
}
|
|
153
|
+
for (const key of programAccountMap.keys()) {
|
|
154
|
+
if (!this.has(key)) {
|
|
155
|
+
await this.addUserStat(new web3_js_1.PublicKey(key));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
140
159
|
}
|
|
141
160
|
exports.UserStatsMap = UserStatsMap;
|
package/package.json
CHANGED
package/src/dlob/DLOB.ts
CHANGED
|
@@ -1148,6 +1148,7 @@ export class DLOB {
|
|
|
1148
1148
|
oraclePriceData: OraclePriceData,
|
|
1149
1149
|
fallbackBid?: BN
|
|
1150
1150
|
): Generator<DLOBNode> {
|
|
1151
|
+
const isPerpMarket = isVariant(marketType, 'perp');
|
|
1151
1152
|
for (const node of this.getRestingLimitAsks(
|
|
1152
1153
|
marketIndex,
|
|
1153
1154
|
slot,
|
|
@@ -1155,6 +1156,7 @@ export class DLOB {
|
|
|
1155
1156
|
oraclePriceData
|
|
1156
1157
|
)) {
|
|
1157
1158
|
if (
|
|
1159
|
+
isPerpMarket &&
|
|
1158
1160
|
fallbackBid &&
|
|
1159
1161
|
node.getPrice(oraclePriceData, slot).lte(fallbackBid)
|
|
1160
1162
|
) {
|
|
@@ -1213,6 +1215,7 @@ export class DLOB {
|
|
|
1213
1215
|
oraclePriceData: OraclePriceData,
|
|
1214
1216
|
fallbackAsk?: BN
|
|
1215
1217
|
): Generator<DLOBNode> {
|
|
1218
|
+
const isPerpMarket = isVariant(marketType, 'perp');
|
|
1216
1219
|
for (const node of this.getRestingLimitBids(
|
|
1217
1220
|
marketIndex,
|
|
1218
1221
|
slot,
|
|
@@ -1220,6 +1223,7 @@ export class DLOB {
|
|
|
1220
1223
|
oraclePriceData
|
|
1221
1224
|
)) {
|
|
1222
1225
|
if (
|
|
1226
|
+
isPerpMarket &&
|
|
1223
1227
|
fallbackAsk &&
|
|
1224
1228
|
node.getPrice(oraclePriceData, slot).gte(fallbackAsk)
|
|
1225
1229
|
) {
|
package/src/driftClient.ts
CHANGED
|
@@ -1329,7 +1329,8 @@ export class DriftClient {
|
|
|
1329
1329
|
subAccountId = 0,
|
|
1330
1330
|
name = DEFAULT_USER_NAME,
|
|
1331
1331
|
fromSubAccountId?: number,
|
|
1332
|
-
referrerInfo?: ReferrerInfo
|
|
1332
|
+
referrerInfo?: ReferrerInfo,
|
|
1333
|
+
txParams?: TxParams
|
|
1333
1334
|
): Promise<[TransactionSignature, PublicKey]> {
|
|
1334
1335
|
const [userAccountPublicKey, initializeUserAccountIx] =
|
|
1335
1336
|
await this.getInitializeUserInstructions(
|
|
@@ -1346,6 +1347,20 @@ export class DriftClient {
|
|
|
1346
1347
|
|
|
1347
1348
|
const tx = new Transaction();
|
|
1348
1349
|
|
|
1350
|
+
tx.add(
|
|
1351
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
1352
|
+
units: txParams?.computeUnits ?? 600_000,
|
|
1353
|
+
})
|
|
1354
|
+
);
|
|
1355
|
+
|
|
1356
|
+
if (txParams?.computeUnitsPrice) {
|
|
1357
|
+
tx.add(
|
|
1358
|
+
ComputeBudgetProgram.setComputeUnitPrice({
|
|
1359
|
+
microLamports: txParams.computeUnitsPrice,
|
|
1360
|
+
})
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1349
1364
|
const authority = this.wallet.publicKey;
|
|
1350
1365
|
|
|
1351
1366
|
const createWSOLTokenAccount =
|
|
@@ -2394,6 +2409,20 @@ export class DriftClient {
|
|
|
2394
2409
|
});
|
|
2395
2410
|
}
|
|
2396
2411
|
|
|
2412
|
+
public async getRevertFillIx(): Promise<TransactionInstruction> {
|
|
2413
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
2414
|
+
const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
|
|
2415
|
+
|
|
2416
|
+
return this.program.instruction.revertFill({
|
|
2417
|
+
accounts: {
|
|
2418
|
+
state: await this.getStatePublicKey(),
|
|
2419
|
+
filler: fillerPublicKey,
|
|
2420
|
+
fillerStats: fillerStatsPublicKey,
|
|
2421
|
+
authority: this.wallet.publicKey,
|
|
2422
|
+
},
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2397
2426
|
public async placeSpotOrder(
|
|
2398
2427
|
orderParams: OptionalOrderParams,
|
|
2399
2428
|
txParams?: TxParams
|
|
@@ -2759,14 +2788,14 @@ export class DriftClient {
|
|
|
2759
2788
|
});
|
|
2760
2789
|
}
|
|
2761
2790
|
|
|
2762
|
-
public async
|
|
2791
|
+
public async updateUserIdle(
|
|
2763
2792
|
userAccountPublicKey: PublicKey,
|
|
2764
2793
|
user: UserAccount,
|
|
2765
2794
|
txParams?: TxParams
|
|
2766
2795
|
): Promise<TransactionSignature> {
|
|
2767
2796
|
const { txSig } = await this.txSender.send(
|
|
2768
2797
|
wrapInTx(
|
|
2769
|
-
await this.
|
|
2798
|
+
await this.getUpdateUserIdleIx(userAccountPublicKey, user),
|
|
2770
2799
|
txParams?.computeUnits,
|
|
2771
2800
|
txParams?.computeUnitsPrice
|
|
2772
2801
|
),
|
|
@@ -2776,7 +2805,7 @@ export class DriftClient {
|
|
|
2776
2805
|
return txSig;
|
|
2777
2806
|
}
|
|
2778
2807
|
|
|
2779
|
-
public async
|
|
2808
|
+
public async getUpdateUserIdleIx(
|
|
2780
2809
|
userAccountPublicKey: PublicKey,
|
|
2781
2810
|
userAccount: UserAccount
|
|
2782
2811
|
): Promise<TransactionInstruction> {
|
|
@@ -2786,7 +2815,7 @@ export class DriftClient {
|
|
|
2786
2815
|
userAccounts: [userAccount],
|
|
2787
2816
|
});
|
|
2788
2817
|
|
|
2789
|
-
return await this.program.instruction.
|
|
2818
|
+
return await this.program.instruction.updateUserIdle({
|
|
2790
2819
|
accounts: {
|
|
2791
2820
|
state: await this.getStatePublicKey(),
|
|
2792
2821
|
filler: fillerPublicKey,
|
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.21.0-beta.
|
|
2
|
+
"version": "2.21.0-beta.2",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -909,6 +909,32 @@
|
|
|
909
909
|
}
|
|
910
910
|
]
|
|
911
911
|
},
|
|
912
|
+
{
|
|
913
|
+
"name": "revertFill",
|
|
914
|
+
"accounts": [
|
|
915
|
+
{
|
|
916
|
+
"name": "state",
|
|
917
|
+
"isMut": false,
|
|
918
|
+
"isSigner": false
|
|
919
|
+
},
|
|
920
|
+
{
|
|
921
|
+
"name": "authority",
|
|
922
|
+
"isMut": false,
|
|
923
|
+
"isSigner": true
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
"name": "filler",
|
|
927
|
+
"isMut": true,
|
|
928
|
+
"isSigner": false
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
"name": "fillerStats",
|
|
932
|
+
"isMut": true,
|
|
933
|
+
"isSigner": false
|
|
934
|
+
}
|
|
935
|
+
],
|
|
936
|
+
"args": []
|
|
937
|
+
},
|
|
912
938
|
{
|
|
913
939
|
"name": "fillSpotOrder",
|
|
914
940
|
"accounts": [
|
|
@@ -1023,6 +1049,32 @@
|
|
|
1023
1049
|
],
|
|
1024
1050
|
"args": []
|
|
1025
1051
|
},
|
|
1052
|
+
{
|
|
1053
|
+
"name": "updateUserIdle",
|
|
1054
|
+
"accounts": [
|
|
1055
|
+
{
|
|
1056
|
+
"name": "state",
|
|
1057
|
+
"isMut": false,
|
|
1058
|
+
"isSigner": false
|
|
1059
|
+
},
|
|
1060
|
+
{
|
|
1061
|
+
"name": "authority",
|
|
1062
|
+
"isMut": false,
|
|
1063
|
+
"isSigner": true
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
"name": "filler",
|
|
1067
|
+
"isMut": true,
|
|
1068
|
+
"isSigner": false
|
|
1069
|
+
},
|
|
1070
|
+
{
|
|
1071
|
+
"name": "user",
|
|
1072
|
+
"isMut": true,
|
|
1073
|
+
"isSigner": false
|
|
1074
|
+
}
|
|
1075
|
+
],
|
|
1076
|
+
"args": []
|
|
1077
|
+
},
|
|
1026
1078
|
{
|
|
1027
1079
|
"name": "settlePnl",
|
|
1028
1080
|
"accounts": [
|
|
@@ -8742,6 +8794,11 @@
|
|
|
8742
8794
|
"code": 6238,
|
|
8743
8795
|
"name": "UserNotInactive",
|
|
8744
8796
|
"msg": "User Not Inactive"
|
|
8797
|
+
},
|
|
8798
|
+
{
|
|
8799
|
+
"code": 6239,
|
|
8800
|
+
"name": "RevertFill",
|
|
8801
|
+
"msg": "RevertFill"
|
|
8745
8802
|
}
|
|
8746
8803
|
]
|
|
8747
8804
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTokenAccount = void 0;
|
|
4
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
function parseTokenAccount(data) {
|
|
7
|
+
const accountInfo = spl_token_1.AccountLayout.decode(data);
|
|
8
|
+
accountInfo.mint = new web3_js_1.PublicKey(accountInfo.mint);
|
|
9
|
+
accountInfo.owner = new web3_js_1.PublicKey(accountInfo.owner);
|
|
10
|
+
accountInfo.amount = spl_token_1.u64.fromBuffer(accountInfo.amount);
|
|
11
|
+
if (accountInfo.delegateOption === 0) {
|
|
12
|
+
accountInfo.delegate = null;
|
|
13
|
+
// eslint-disable-next-line new-cap
|
|
14
|
+
accountInfo.delegatedAmount = new spl_token_1.u64(0);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
accountInfo.delegate = new web3_js_1.PublicKey(accountInfo.delegate);
|
|
18
|
+
accountInfo.delegatedAmount = spl_token_1.u64.fromBuffer(accountInfo.delegatedAmount);
|
|
19
|
+
}
|
|
20
|
+
accountInfo.isInitialized = accountInfo.state !== 0;
|
|
21
|
+
accountInfo.isFrozen = accountInfo.state === 2;
|
|
22
|
+
if (accountInfo.isNativeOption === 1) {
|
|
23
|
+
accountInfo.rentExemptReserve = spl_token_1.u64.fromBuffer(accountInfo.isNative);
|
|
24
|
+
accountInfo.isNative = true;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
accountInfo.rentExemptReserve = null;
|
|
28
|
+
accountInfo.isNative = false;
|
|
29
|
+
}
|
|
30
|
+
if (accountInfo.closeAuthorityOption === 0) {
|
|
31
|
+
accountInfo.closeAuthority = null;
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
accountInfo.closeAuthority = new web3_js_1.PublicKey(accountInfo.closeAuthority);
|
|
35
|
+
}
|
|
36
|
+
return accountInfo;
|
|
37
|
+
}
|
|
38
|
+
exports.parseTokenAccount = parseTokenAccount;
|
package/src/tx/retryTxSender.ts
CHANGED
|
@@ -75,13 +75,14 @@ export class RetryTxSender implements TxSender {
|
|
|
75
75
|
)
|
|
76
76
|
).blockhash;
|
|
77
77
|
|
|
78
|
-
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
79
78
|
additionalSigners
|
|
80
79
|
.filter((s): s is Signer => s !== undefined)
|
|
81
80
|
.forEach((kp) => {
|
|
82
|
-
|
|
81
|
+
tx.partialSign(kp);
|
|
83
82
|
});
|
|
84
83
|
|
|
84
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
85
|
+
|
|
85
86
|
return signedTx;
|
|
86
87
|
}
|
|
87
88
|
|
package/src/types.ts
CHANGED
package/src/user.ts
CHANGED
package/src/userMap/userMap.ts
CHANGED
|
@@ -15,7 +15,9 @@ import {
|
|
|
15
15
|
LPRecord,
|
|
16
16
|
} from '..';
|
|
17
17
|
|
|
18
|
-
import { PublicKey } from '@solana/web3.js';
|
|
18
|
+
import { AccountInfo, PublicKey } from '@solana/web3.js';
|
|
19
|
+
import { Buffer } from 'buffer';
|
|
20
|
+
import bs58 from 'bs58';
|
|
19
21
|
|
|
20
22
|
export interface UserMapInterface {
|
|
21
23
|
fetchAllUsers(): Promise<void>;
|
|
@@ -177,4 +179,53 @@ export class UserMap implements UserMapInterface {
|
|
|
177
179
|
public size(): number {
|
|
178
180
|
return this.userMap.size;
|
|
179
181
|
}
|
|
182
|
+
|
|
183
|
+
public async sync(includeIdle = true) {
|
|
184
|
+
let filters = undefined;
|
|
185
|
+
if (!includeIdle) {
|
|
186
|
+
filters = [
|
|
187
|
+
{
|
|
188
|
+
memcmp: {
|
|
189
|
+
offset: 4350,
|
|
190
|
+
bytes: bs58.encode(Uint8Array.from([0])),
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const programAccounts =
|
|
197
|
+
await this.driftClient.connection.getProgramAccounts(
|
|
198
|
+
this.driftClient.program.programId,
|
|
199
|
+
{
|
|
200
|
+
commitment: this.driftClient.connection.commitment,
|
|
201
|
+
filters: [
|
|
202
|
+
{
|
|
203
|
+
memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
|
|
204
|
+
},
|
|
205
|
+
...(Array.isArray(filters) ? filters : []),
|
|
206
|
+
],
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
const programAccountMap = new Map<string, AccountInfo<Buffer>>();
|
|
211
|
+
for (const programAccount of programAccounts) {
|
|
212
|
+
programAccountMap.set(
|
|
213
|
+
programAccount.pubkey.toString(),
|
|
214
|
+
programAccount.account
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
for (const key of programAccountMap.keys()) {
|
|
219
|
+
if (!this.has(key)) {
|
|
220
|
+
await this.addPubkey(new PublicKey(key));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
for (const [key, user] of this.userMap.entries()) {
|
|
225
|
+
if (!programAccountMap.has(key)) {
|
|
226
|
+
await user.unsubscribe();
|
|
227
|
+
this.userMap.delete(key);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
180
231
|
}
|
|
@@ -17,9 +17,10 @@ import {
|
|
|
17
17
|
InsuranceFundStakeRecord,
|
|
18
18
|
} from '..';
|
|
19
19
|
import { ProgramAccount } from '@project-serum/anchor';
|
|
20
|
-
import { PublicKey } from '@solana/web3.js';
|
|
20
|
+
import { AccountInfo, PublicKey } from '@solana/web3.js';
|
|
21
21
|
|
|
22
22
|
import { UserMap } from './userMap';
|
|
23
|
+
import { Buffer } from 'buffer';
|
|
23
24
|
|
|
24
25
|
export class UserStatsMap {
|
|
25
26
|
/**
|
|
@@ -190,4 +191,34 @@ export class UserStatsMap {
|
|
|
190
191
|
public size(): number {
|
|
191
192
|
return this.userStatsMap.size;
|
|
192
193
|
}
|
|
194
|
+
|
|
195
|
+
public async sync() {
|
|
196
|
+
const programAccounts =
|
|
197
|
+
await this.driftClient.connection.getProgramAccounts(
|
|
198
|
+
this.driftClient.program.programId,
|
|
199
|
+
{
|
|
200
|
+
commitment: this.driftClient.connection.commitment,
|
|
201
|
+
filters: [
|
|
202
|
+
{
|
|
203
|
+
memcmp:
|
|
204
|
+
this.driftClient.program.coder.accounts.memcmp('UserStats'),
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
const programAccountMap = new Map<string, AccountInfo<Buffer>>();
|
|
211
|
+
for (const programAccount of programAccounts) {
|
|
212
|
+
programAccountMap.set(
|
|
213
|
+
new PublicKey(programAccount.account.data.slice(8, 40)).toString(),
|
|
214
|
+
programAccount.account
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
for (const key of programAccountMap.keys()) {
|
|
219
|
+
if (!this.has(key)) {
|
|
220
|
+
await this.addUserStat(new PublicKey(key));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
193
224
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.findComputeUnitConsumption = void 0;
|
|
13
|
+
function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
|
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
const tx = yield connection.getTransaction(txSignature, { commitment });
|
|
16
|
+
const computeUnits = [];
|
|
17
|
+
const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`);
|
|
18
|
+
tx.meta.logMessages.forEach((logMessage) => {
|
|
19
|
+
const match = logMessage.match(regex);
|
|
20
|
+
if (match && match[1]) {
|
|
21
|
+
computeUnits.push(match[1]);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return computeUnits;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
exports.findComputeUnitConsumption = findComputeUnitConsumption;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTokenAddress = void 0;
|
|
4
|
+
const spl_token_1 = require("@solana/spl-token");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const getTokenAddress = (mintAddress, userPubKey) => {
|
|
7
|
+
return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
|
|
8
|
+
};
|
|
9
|
+
exports.getTokenAddress = getTokenAddress;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.promiseTimeout = void 0;
|
|
4
|
+
function promiseTimeout(promise, timeoutMs) {
|
|
5
|
+
let timeoutId;
|
|
6
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
7
|
+
timeoutId = setTimeout(() => resolve(null), timeoutMs);
|
|
8
|
+
});
|
|
9
|
+
return Promise.race([promise, timeoutPromise]).then((result) => {
|
|
10
|
+
clearTimeout(timeoutId);
|
|
11
|
+
return result;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
exports.promiseTimeout = promiseTimeout;
|
package/src/util/tps.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.estimateTps = void 0;
|
|
13
|
+
function estimateTps(programId, connection, failed) {
|
|
14
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
15
|
+
let signatures = yield connection.getSignaturesForAddress(programId, undefined, 'finalized');
|
|
16
|
+
if (failed) {
|
|
17
|
+
signatures = signatures.filter((signature) => signature.err);
|
|
18
|
+
}
|
|
19
|
+
const numberOfSignatures = signatures.length;
|
|
20
|
+
if (numberOfSignatures === 0) {
|
|
21
|
+
return 0;
|
|
22
|
+
}
|
|
23
|
+
return (numberOfSignatures /
|
|
24
|
+
(signatures[0].blockTime - signatures[numberOfSignatures - 1].blockTime));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
exports.estimateTps = estimateTps;
|